/**
 * TASKMATE - Undo/Redo Module
 * ===========================
 * Undo and redo functionality
 */

import store from './store.js';
import api from './api.js';

class UndoManager {
  constructor() {
    this.bindEvents();
  }

  bindEvents() {
    window.addEventListener('undo:perform', () => this.undo());
    window.addEventListener('redo:perform', () => this.redo());
  }

  // =====================
  // UNDO/REDO
  // =====================

  async undo() {
    if (!store.canUndo()) {
      this.showInfo('Nichts zum Rückgängigmachen');
      return;
    }

    const action = store.popUndo();
    if (!action) return;

    try {
      await this.executeUndo(action);
      this.showSuccess('Rückgängig gemacht');
    } catch (error) {
      console.error('Undo failed:', error);
      this.showError('Rückgängig fehlgeschlagen');
      // Re-push to undo stack
      store.pushUndo(action);
    }
  }

  async redo() {
    if (!store.canRedo()) {
      this.showInfo('Nichts zum Wiederholen');
      return;
    }

    const action = store.popRedo();
    if (!action) return;

    try {
      await this.executeRedo(action);
      this.showSuccess('Wiederholt');
    } catch (error) {
      console.error('Redo failed:', error);
      this.showError('Wiederholen fehlgeschlagen');
    }
  }

  // =====================
  // ACTION EXECUTION
  // =====================

  async executeUndo(action) {
    const projectId = store.get('currentProjectId');

    switch (action.type) {
      case 'DELETE_TASK':
        // Restore deleted task
        const restoredTask = await api.createTask(projectId, {
          ...action.task,
          id: undefined // Let server assign new ID
        });
        store.addTask(restoredTask);
        break;

      case 'CREATE_TASK':
        // Delete created task
        await api.deleteTask(projectId, action.taskId);
        store.removeTask(action.taskId);
        break;

      case 'UPDATE_TASK':
        // Restore previous values
        await api.updateTask(projectId, action.taskId, action.previousData);
        store.updateTask(action.taskId, action.previousData);
        break;

      case 'MOVE_TASK':
        // Move back to original position
        await api.moveTask(projectId, action.taskId, action.fromColumnId, action.fromPosition);
        store.moveTask(action.taskId, action.fromColumnId, action.fromPosition);
        break;

      case 'DELETE_COLUMN':
        // Restore deleted column (without tasks - they're gone)
        const restoredColumn = await api.createColumn(projectId, action.column);
        store.addColumn(restoredColumn);
        break;

      case 'CREATE_COLUMN':
        // Delete created column
        await api.deleteColumn(projectId, action.columnId);
        store.removeColumn(action.columnId);
        break;

      case 'UPDATE_COLUMN':
        // Restore previous values
        await api.updateColumn(projectId, action.columnId, action.previousData);
        store.updateColumn(action.columnId, action.previousData);
        break;

      case 'BULK_DELETE':
        // Restore all deleted tasks
        for (const task of action.tasks) {
          const restored = await api.createTask(projectId, {
            ...task,
            id: undefined
          });
          store.addTask(restored);
        }
        break;

      case 'BULK_MOVE':
        // Move all tasks back
        for (const item of action.items) {
          await api.moveTask(projectId, item.taskId, item.fromColumnId, item.fromPosition);
          store.moveTask(item.taskId, item.fromColumnId, item.fromPosition);
        }
        break;

      case 'BULK_UPDATE':
        // Restore all previous values
        for (const item of action.items) {
          await api.updateTask(projectId, item.taskId, item.previousData);
          store.updateTask(item.taskId, item.previousData);
        }
        break;

      default:
        console.warn('Unknown undo action type:', action.type);
    }
  }

  async executeRedo(action) {
    const projectId = store.get('currentProjectId');

    switch (action.type) {
      case 'DELETE_TASK':
        // Re-delete the task
        await api.deleteTask(projectId, action.task.id);
        store.removeTask(action.task.id);
        break;

      case 'CREATE_TASK':
        // Re-create the task
        const recreatedTask = await api.createTask(projectId, action.taskData);
        store.addTask(recreatedTask);
        break;

      case 'UPDATE_TASK':
        // Re-apply the update
        await api.updateTask(projectId, action.taskId, action.newData);
        store.updateTask(action.taskId, action.newData);
        break;

      case 'MOVE_TASK':
        // Re-move to new position
        await api.moveTask(projectId, action.taskId, action.toColumnId, action.toPosition);
        store.moveTask(action.taskId, action.toColumnId, action.toPosition);
        break;

      case 'DELETE_COLUMN':
        // Re-delete the column
        await api.deleteColumn(projectId, action.column.id);
        store.removeColumn(action.column.id);
        break;

      case 'CREATE_COLUMN':
        // Re-create the column
        const recreatedColumn = await api.createColumn(projectId, action.columnData);
        store.addColumn(recreatedColumn);
        break;

      case 'UPDATE_COLUMN':
        // Re-apply the update
        await api.updateColumn(projectId, action.columnId, action.newData);
        store.updateColumn(action.columnId, action.newData);
        break;

      case 'BULK_DELETE':
        // Re-delete all tasks
        for (const task of action.tasks) {
          await api.deleteTask(projectId, task.id);
          store.removeTask(task.id);
        }
        break;

      case 'BULK_MOVE':
        // Re-move all tasks
        for (const item of action.items) {
          await api.moveTask(projectId, item.taskId, item.toColumnId, item.toPosition);
          store.moveTask(item.taskId, item.toColumnId, item.toPosition);
        }
        break;

      case 'BULK_UPDATE':
        // Re-apply all updates
        for (const item of action.items) {
          await api.updateTask(projectId, item.taskId, item.newData);
          store.updateTask(item.taskId, item.newData);
        }
        break;

      default:
        console.warn('Unknown redo action type:', action.type);
    }
  }

  // =====================
  // ACTION RECORDING
  // =====================

  recordTaskDelete(task) {
    store.pushUndo({
      type: 'DELETE_TASK',
      task: { ...task }
    });
  }

  recordTaskCreate(taskId, taskData) {
    store.pushUndo({
      type: 'CREATE_TASK',
      taskId,
      taskData
    });
  }

  recordTaskUpdate(taskId, previousData, newData) {
    store.pushUndo({
      type: 'UPDATE_TASK',
      taskId,
      previousData,
      newData
    });
  }

  recordTaskMove(taskId, fromColumnId, fromPosition, toColumnId, toPosition) {
    store.pushUndo({
      type: 'MOVE_TASK',
      taskId,
      fromColumnId,
      fromPosition,
      toColumnId,
      toPosition
    });
  }

  recordColumnDelete(column) {
    store.pushUndo({
      type: 'DELETE_COLUMN',
      column: { ...column }
    });
  }

  recordColumnCreate(columnId, columnData) {
    store.pushUndo({
      type: 'CREATE_COLUMN',
      columnId,
      columnData
    });
  }

  recordColumnUpdate(columnId, previousData, newData) {
    store.pushUndo({
      type: 'UPDATE_COLUMN',
      columnId,
      previousData,
      newData
    });
  }

  recordBulkDelete(tasks) {
    store.pushUndo({
      type: 'BULK_DELETE',
      tasks: tasks.map(t => ({ ...t }))
    });
  }

  recordBulkMove(items) {
    store.pushUndo({
      type: 'BULK_MOVE',
      items: [...items]
    });
  }

  recordBulkUpdate(items) {
    store.pushUndo({
      type: 'BULK_UPDATE',
      items: [...items]
    });
  }

  // =====================
  // HELPERS
  // =====================

  showSuccess(message) {
    window.dispatchEvent(new CustomEvent('toast:show', {
      detail: { message, type: 'success' }
    }));
  }

  showError(message) {
    window.dispatchEvent(new CustomEvent('toast:show', {
      detail: { message, type: 'error' }
    }));
  }

  showInfo(message) {
    window.dispatchEvent(new CustomEvent('toast:show', {
      detail: { message, type: 'info' }
    }));
  }
}

// Create and export singleton
const undoManager = new UndoManager();

export default undoManager;
