/**
 * TASKMATE - Board Module
 * =======================
 * Kanban board functionality
 */

import store from './store.js';
import api from './api.js';
import syncManager from './sync.js';
import offlineManager from './offline.js';
import {
  $, $$, createElement, clearElement, formatDate,
  getDueDateStatus, calculateProgress, filterTasks,
  getInitials, hexToRgba, getContrastColor, generateTempId,
  debounce, createPriorityElement
} from './utils.js';

class BoardManager {
  constructor() {
    this.boardElement = null;
    this.draggedTask = null;
    this.draggedColumn = null;
    this.dropTarget = null;

    // Week strip calendar
    this.weekStripDate = this.getMonday(new Date());
    this.tooltip = null;
    
    this.init();
  }

  init() {
    this.boardElement = $('#board');
    this.bindEvents();
    this.bindWeekStripEvents();
    this.renderWeekStrip();

    // Subscribe to store changes
    store.subscribe('columns', () => {
      this.render();
      this.renderWeekStrip(); // Update week strip when column colors change
    });
    store.subscribe('tasks', () => {
      this.renderTasks();
      this.updateStats();
      this.renderWeekStrip();
    });
    store.subscribe('filters', () => this.renderTasks());
    store.subscribe('searchResultIds', () => this.renderTasks());
    store.subscribe('labels', () => this.renderTasks());
    store.subscribe('currentProjectId', () => {
      this.loadStats();
      this.renderWeekStrip();
    });
    
  }

  // =====================
  // STATS
  // =====================

  async loadStats() {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    try {
      const stats = await api.getStats(projectId);
      this.renderStats(stats);
    } catch (error) {
      console.error('Failed to load stats:', error);
    }
  }

  renderStats(stats) {
    const openEl = $('#board-stat-open');
    const progressEl = $('#board-stat-progress');
    const doneEl = $('#board-stat-done');
    const overdueEl = $('#board-stat-overdue');

    if (openEl) openEl.textContent = stats.open || 0;
    if (progressEl) progressEl.textContent = stats.inProgress || 0;
    if (doneEl) doneEl.textContent = stats.completed || 0;
    if (overdueEl) overdueEl.textContent = stats.overdue || 0;
  }

  updateStats() {
    // Calculate stats from current tasks in store
    const tasks = store.get('tasks').filter(t => !t.archived);
    const columns = store.get('columns');

    // Find column positions to determine status
    const columnMap = {};
    columns.forEach((col, idx) => {
      columnMap[col.id] = idx;
    });

    let open = 0;
    let inProgress = 0;
    let completed = 0;
    let overdue = 0;

    const today = new Date();
    today.setHours(0, 0, 0, 0);

    tasks.forEach(task => {
      const colIdx = columnMap[task.columnId];
      const totalCols = columns.length;

      // First column = open, last column = done, middle = in progress
      if (totalCols > 0) {
        if (colIdx === 0) {
          open++;
        } else if (colIdx === totalCols - 1) {
          completed++;
        } else {
          inProgress++;
        }
      }

      // Check overdue (only for non-completed tasks)
      if (task.dueDate && colIdx !== totalCols - 1) {
        const dueDate = new Date(task.dueDate);
        dueDate.setHours(0, 0, 0, 0);
        if (dueDate < today) {
          overdue++;
        }
      }
    });

    this.renderStats({ open, inProgress, completed, overdue });
  }

  bindEvents() {
    // Note: Add column button is rendered dynamically with its own onclick handler

    // Delegated event handling for board
    this.boardElement?.addEventListener('click', (e) => this.handleBoardClick(e));

    // Drag and drop for tasks
    this.boardElement?.addEventListener('dragstart', (e) => this.handleDragStart(e));
    this.boardElement?.addEventListener('dragend', (e) => this.handleDragEnd(e));
    this.boardElement?.addEventListener('dragover', (e) => this.handleDragOver(e));
    this.boardElement?.addEventListener('dragleave', (e) => this.handleDragLeave(e));
    this.boardElement?.addEventListener('drop', (e) => this.handleDrop(e));

    // Keyboard navigation
    document.addEventListener('keydown', (e) => this.handleKeyboard(e));
    
  }

  // =====================
  // RENDERING
  // =====================

  render() {
    if (!this.boardElement) return;

    const columns = store.get('columns');
    clearElement(this.boardElement);

    columns.forEach(column => {
      const columnElement = this.createColumnElement(column);
      this.boardElement.appendChild(columnElement);
    });

    // Add "Add Column" button
    const addColumnBtn = createElement('button', {
      className: 'btn-add-column',
      onclick: () => this.openAddColumnModal()
    }, [
      createElement('span', { className: 'icon' }, ['+']),
      'Statuskarte hinzufügen'
    ]);
    this.boardElement.appendChild(addColumnBtn);

    // Emit event for mobile column navigation
    document.dispatchEvent(new CustomEvent('columns:updated'));
  }

  createColumnElement(column) {
    const tasks = store.getTasksByColumn(column.id);
    const columns = store.get('columns');
    const filteredTasks = filterTasks(tasks, store.get('filters'), store.get('searchResultIds'), columns);

    const columnEl = createElement('div', {
      className: 'column',
      dataset: { columnId: column.id }
    });

    // Header with column color - draggable
    const header = createElement('div', {
      className: 'column-header',
      draggable: 'true'
    });

    // Apply column color to header background
    const columnColor = column.color || '#6B7280';
    header.style.backgroundColor = columnColor;
    header.style.color = getContrastColor(columnColor);

    const title = createElement('div', { className: 'column-title' }, [
      createElement('span', {}, [column.name]),
      createElement('span', { className: 'column-count' }, [filteredTasks.length.toString()])
    ]);

    const actions = createElement('div', { className: 'column-actions' }, [
      createElement('button', {
        className: 'btn btn-icon btn-ghost',
        title: 'Spalte bearbeiten',
        dataset: { action: 'edit-column', columnId: column.id }
      }, [this.createIcon('edit')]),
      createElement('button', {
        className: 'btn btn-icon btn-ghost',
        title: 'Spalte löschen',
        dataset: { action: 'delete-column', columnId: column.id }
      }, [this.createIcon('trash')])
    ]);

    header.appendChild(title);
    header.appendChild(actions);

    // Body (task list)
    const body = createElement('div', {
      className: 'column-body',
      dataset: { columnId: column.id }
    });

    filteredTasks.forEach(task => {
      body.appendChild(this.createTaskCard(task));
    });

    // Footer (add task button)
    const footer = createElement('div', { className: 'column-footer' }, [
      createElement('button', {
        className: 'btn-add-task',
        dataset: { action: 'add-task', columnId: column.id }
      }, [
        createElement('span', {}, ['+']),
        'Aufgabe hinzufügen'
      ])
    ]);

    columnEl.appendChild(header);
    columnEl.appendChild(body);
    columnEl.appendChild(footer);

    return columnEl;
  }

  createTaskCard(task) {
    const dueStatus = getDueDateStatus(task.dueDate);
    const progress = calculateProgress(task.subtasks);
    const isCompleted = this.isTaskCompleted(task);

    const classes = ['task-card'];
    if (store.get('selectedTaskIds').includes(task.id)) classes.push('selected');
    if (!isCompleted && dueStatus === 'overdue') classes.push('overdue');
    if (!isCompleted && (dueStatus === 'soon' || dueStatus === 'today')) classes.push('due-soon');

    const card = createElement('div', {
      className: classes.join(' '),
      dataset: { taskId: task.id },
      draggable: 'true'
    });

    // Header with title and priority
    const header = createElement('div', { className: 'task-card-header' }, [
      createElement('span', { className: 'task-title' }, [task.title]),
      createPriorityElement(task.priority)
    ]);
    card.appendChild(header);

    // Labels
    if (task.labels && task.labels.length > 0) {
      const labelsContainer = createElement('div', { className: 'task-card-labels' });
      task.labels.forEach(label => {
        labelsContainer.appendChild(createElement('span', {
          className: 'task-label',
          style: {
            backgroundColor: hexToRgba(label.color, 0.2),
            color: label.color
          }
        }, [label.name]));
      });
      card.appendChild(labelsContainer);
    }

    // Meta info (due date, time estimate)
    const metaItems = [];

    if (task.dueDate) {
      const dueDateClass = (!isCompleted && dueStatus === 'overdue') ? 'text-error' : '';
      // Show relative date for non-completed tasks, absolute date for completed
      const dateDisplay = isCompleted
        ? formatDate(task.dueDate, { relative: false })
        : formatDate(task.dueDate, { relative: true });
      metaItems.push(createElement('span', {
        className: `task-meta-item ${dueDateClass}`
      }, [
        this.createIcon('calendar'),
        dateDisplay
      ]));
    }

    if (task.timeEstimateMin) {
      const hours = Math.floor(task.timeEstimateMin / 60);
      const minutes = task.timeEstimateMin % 60;
      metaItems.push(createElement('span', { className: 'task-meta-item' }, [
        this.createIcon('clock'),
        this.formatEstimate(hours, minutes)
      ]));
    }

    if (metaItems.length > 0) {
      const meta = createElement('div', { className: 'task-card-meta' }, metaItems);
      card.appendChild(meta);
    }

    // Progress bar for subtasks
    if (progress) {
      const progressContainer = createElement('div', { className: 'task-card-progress' });

      const progressBar = createElement('div', { className: 'task-progress-bar' }, [
        createElement('div', {
          className: 'task-progress-fill',
          style: { width: `${progress.percentage}%` }
        })
      ]);

      const progressText = createElement('span', { className: 'task-progress-text' }, [
        `${progress.completed}/${progress.total} Unteraufgaben`
      ]);

      progressContainer.appendChild(progressBar);
      progressContainer.appendChild(progressText);
      card.appendChild(progressContainer);
    }

    // Verknüpfte Genehmigungen anzeigen
    if (task.proposals && task.proposals.length > 0) {
      const proposalsContainer = createElement('div', { className: 'task-card-proposals' });

      task.proposals.forEach(proposal => {
        const proposalItem = createElement('div', {
          className: `task-proposal-item ${proposal.approved ? 'approved' : 'pending'}`
        }, [
          createElement('span', { className: 'task-proposal-icon' }, [
            proposal.approved ? '✓' : '○'
          ]),
          createElement('span', { className: 'task-proposal-title' }, [proposal.title])
        ]);
        proposalsContainer.appendChild(proposalItem);
      });

      card.appendChild(proposalsContainer);
    }

    // Footer with assignees and counts
    const hasAssignees = task.assignees && task.assignees.length > 0;
    const hasFooterContent = hasAssignees || task.assignedTo || task.commentCount > 0 || task.attachmentCount > 0;

    if (hasFooterContent) {
      const footer = createElement('div', { className: 'task-card-footer' });

      // Assignees (Mehrfachzuweisung)
      if (hasAssignees) {
        const users = store.get('users');
        const assigneesContainer = createElement('div', { className: 'task-assignees' });

        // Avatare fuer alle zugewiesenen Benutzer anzeigen
        const maxVisible = 3; // Maximal 3 Avatare anzeigen
        const visibleAssignees = task.assignees.slice(0, maxVisible);
        const hiddenCount = task.assignees.length - maxVisible;

        visibleAssignees.forEach((assignee, index) => {
          // Aktuellen Benutzer aus Store holen (fuer aktuelle Farbe)
          const currentUser = users.find(u => u.id === assignee.id);
          const color = currentUser?.color || assignee.color || '#888';
          const name = currentUser?.display_name || assignee.display_name || assignee.username || 'Benutzer';
          
          // Initialen berechnen - currentUser hat immer die korrekten initials
          let initials = currentUser?.initials || getInitials(name) || '?';
          
          // Sicherheit: Falls initials undefined ist, Fallback verwenden
          if (!initials || initials === 'undefined') {
            initials = getInitials(currentUser?.email || name) || '?';
          }

          const avatar = createElement('span', {
            className: 'avatar task-assignee-avatar stacked',
            style: {
              backgroundColor: color,
              zIndex: 10 - index
            },
            title: name
          }, [initials]);
          assigneesContainer.appendChild(avatar);
        });

        // "+X" Anzeige wenn mehr als maxVisible Benutzer
        if (hiddenCount > 0) {
          const moreIndicator = createElement('span', {
            className: 'avatar task-assignee-avatar stacked more-indicator',
            style: { zIndex: 1 },
            title: `${hiddenCount} weitere Mitarbeitende`
          }, [`+${hiddenCount}`]);
          assigneesContainer.appendChild(moreIndicator);
        }

        footer.appendChild(assigneesContainer);
      } else if (task.assignedTo) {
        // Fallback fuer alte Einzelzuweisung (Abwaertskompatibilitaet)
        const users = store.get('users');
        const assignedUser = users.find(u => u.id === task.assignedTo);
        const currentColor = assignedUser?.color || task.assignedColor || '#888';
        const currentName = assignedUser?.display_name || assignedUser?.username || task.assignedName || 'Benutzer';
        
        // Initialen berechnen
        let initials = assignedUser?.initials || getInitials(currentName) || '?';
        if (!initials || initials === 'undefined') {
          initials = getInitials(assignedUser?.email || currentName) || '?';
        }

        const assignee = createElement('div', { className: 'task-assignees' }, [
          createElement('span', {
            className: 'avatar task-assignee-avatar',
            style: { backgroundColor: currentColor },
            title: currentName
          }, [initials])
        ]);
        footer.appendChild(assignee);
      } else {
        footer.appendChild(createElement('div'));
      }

      // Counts (comments, attachments)
      const counts = createElement('div', { className: 'task-counts' });

      if (task.commentCount > 0) {
        counts.appendChild(createElement('span', {}, [
          this.createIcon('message'),
          task.commentCount.toString()
        ]));
      }

      if (task.attachmentCount > 0) {
        counts.appendChild(createElement('span', {}, [
          this.createIcon('paperclip'),
          task.attachmentCount.toString()
        ]));
      }

      footer.appendChild(counts);
      card.appendChild(footer);
    }

    return card;
  }

  renderTasks() {
    const columns = store.get('columns');
    const searchResultIds = store.get('searchResultIds');
    const filters = store.get('filters');

    columns.forEach(column => {
      const columnBody = $(`.column-body[data-column-id="${column.id}"]`);
      if (!columnBody) return;

      const tasks = store.getTasksByColumn(column.id);
      const filteredTasks = filterTasks(tasks, filters, searchResultIds, columns);

      clearElement(columnBody);
      filteredTasks.forEach(task => {
        columnBody.appendChild(this.createTaskCard(task));
      });

      // Update count
      const countElement = $(`.column[data-column-id="${column.id}"] .column-count`);
      if (countElement) {
        countElement.textContent = filteredTasks.length.toString();
      }
    });
  }

  // =====================
  // EVENT HANDLERS
  // =====================

  handleBoardClick(e) {
    const target = e.target.closest('[data-action]');
    if (!target) {
      // Check for task card click
      const taskCard = e.target.closest('.task-card');
      if (taskCard) {
        const taskId = parseInt(taskCard.dataset.taskId);
        if (e.ctrlKey || e.metaKey) {
          store.selectTask(taskId, true);
        } else {
          this.openTaskModal(taskId);
        }
        return;
      }
      return;
    }

    const action = target.dataset.action;
    const columnId = parseInt(target.dataset.columnId);
    const taskId = parseInt(target.dataset.taskId);

    switch (action) {
      case 'add-task':
        this.openAddTaskModal(columnId);
        break;
      case 'edit-column':
        this.openEditColumnModal(columnId);
        break;
      case 'delete-column':
        this.confirmDeleteColumn(columnId);
        break;
    }
  }

  handleKeyboard(e) {
    // Only handle when board is active
    if (store.get('currentView') !== 'board') return;
    if (store.get('openModals').length > 0) return;

    // Escape to deselect
    if (e.key === 'Escape') {
      store.clearSelection();
      return;
    }

    // Delete selected tasks
    if ((e.key === 'Delete' || e.key === 'Backspace') && !e.target.matches('input, textarea')) {
      const selected = store.get('selectedTaskIds');
      if (selected.length > 0) {
        e.preventDefault();
        this.confirmDeleteTasks(selected);
      }
    }

    // Ctrl+A to select all in focused column
    if ((e.ctrlKey || e.metaKey) && e.key === 'a' && !e.target.matches('input, textarea')) {
      e.preventDefault();
      // Select all visible tasks
      const allTaskIds = store.get('tasks')
        .filter(t => !t.archived)
        .map(t => t.id);
      store.setState({ selectedTaskIds: allTaskIds });
    }
  }

  // =====================
  // DRAG AND DROP
  // =====================

  handleDragStart(e) {
    const taskCard = e.target.closest('.task-card');
    const header = e.target.closest('.column-header');
    const column = e.target.closest('.column');

    if (taskCard) {
      this.draggedTask = taskCard;
      taskCard.classList.add('dragging');
      e.dataTransfer.effectAllowed = 'move';
      e.dataTransfer.setData('text/plain', taskCard.dataset.taskId);

      store.setDragState({
        type: 'task',
        taskId: parseInt(taskCard.dataset.taskId)
      });
    } else if (header && column) {
      // Header wird gezogen -> ganze Spalte verschieben
      this.draggedColumn = column;
      column.classList.add('dragging');
      e.dataTransfer.effectAllowed = 'move';
      e.dataTransfer.setData('text/plain', column.dataset.columnId);

      store.setDragState({
        type: 'column',
        columnId: parseInt(column.dataset.columnId)
      });
    }
  }

  handleDragEnd(e) {
    if (this.draggedTask) {
      this.draggedTask.classList.remove('dragging');
      this.draggedTask = null;
    }

    if (this.draggedColumn) {
      this.draggedColumn.classList.remove('dragging');
      this.draggedColumn = null;
    }

    // Remove all drop indicators
    $$('.column-body.drag-over').forEach(el => el.classList.remove('drag-over'));
    $$('.drop-indicator').forEach(el => el.remove());
    // Remove column drag indicators
    $$('.column.drag-over-left, .column.drag-over-right').forEach(el => {
      el.classList.remove('drag-over-left', 'drag-over-right');
    });

    store.setDragState(null);
  }

  handleDragOver(e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';

    const dragState = store.get('dragState');
    if (!dragState) return;

    if (dragState.type === 'task') {
      const columnBody = e.target.closest('.column-body');
      if (columnBody) {
        columnBody.classList.add('drag-over');

        // Show drop indicator
        const taskCard = e.target.closest('.task-card');
        this.updateDropIndicator(columnBody, taskCard, e.clientY);
      }
    } else if (dragState.type === 'column') {
      const column = e.target.closest('.column');

      // Entferne alle vorherigen Drag-Over-Klassen
      $$('.column.drag-over-left, .column.drag-over-right').forEach(col => {
        if (col !== column) {
          col.classList.remove('drag-over-left', 'drag-over-right');
        }
      });

      if (column && column !== this.draggedColumn) {
        const rect = column.getBoundingClientRect();
        const midpoint = rect.left + rect.width / 2;

        if (e.clientX < midpoint) {
          column.classList.add('drag-over-left');
          column.classList.remove('drag-over-right');
        } else {
          column.classList.add('drag-over-right');
          column.classList.remove('drag-over-left');
        }
      }
    }
  }

  handleDragLeave(e) {
    const dragState = store.get('dragState');

    if (dragState?.type === 'task') {
      const columnBody = e.target.closest('.column-body');
      if (columnBody && !columnBody.contains(e.relatedTarget)) {
        columnBody.classList.remove('drag-over');
        $$('.drop-indicator', columnBody).forEach(el => el.remove());
      }
    } else if (dragState?.type === 'column') {
      const column = e.target.closest('.column');
      // Nur entfernen wenn wirklich die Spalte verlassen wird
      if (column && !column.contains(e.relatedTarget)) {
        column.classList.remove('drag-over-left', 'drag-over-right');
      }
    }
  }

  handleDrop(e) {
    e.preventDefault();

    const dragState = store.get('dragState');
    if (!dragState) return;

    // Clean up all drag-over states and indicators
    $$('.column-body.drag-over').forEach(el => el.classList.remove('drag-over'));
    $$('.drop-indicator').forEach(el => el.remove());

    if (dragState.type === 'task') {
      const columnBody = e.target.closest('.column-body');
      if (!columnBody) return;

      const columnId = parseInt(columnBody.dataset.columnId);
      const taskId = dragState.taskId;

      // Calculate position based on where the indicator was
      const taskCards = Array.from($$('.task-card', columnBody)).filter(card =>
        parseInt(card.dataset.taskId) !== taskId
      );

      // Find position based on mouse position
      let position = taskCards.length; // Default: end
      const mouseY = e.clientY;

      for (let i = 0; i < taskCards.length; i++) {
        const rect = taskCards[i].getBoundingClientRect();
        const midpoint = rect.top + rect.height / 2;
        if (mouseY < midpoint) {
          position = i;
          break;
        }
      }

      this.moveTask(taskId, columnId, position);
    } else if (dragState.type === 'column') {
      const targetColumn = e.target.closest('.column');

      if (!targetColumn || targetColumn === this.draggedColumn) {
        // Cleanup
        $$('.column.drag-over-left, .column.drag-over-right').forEach(el => {
          el.classList.remove('drag-over-left', 'drag-over-right');
        });
        return;
      }

      const columns = store.get('columns');
      const fromIndex = columns.findIndex(c => c.id === dragState.columnId);
      let toIndex = columns.findIndex(c => c.id === parseInt(targetColumn.dataset.columnId));

      // Berechne Position basierend auf Maus-Position (links oder rechts der Ziel-Spalte)
      const rect = targetColumn.getBoundingClientRect();
      const midpoint = rect.left + rect.width / 2;
      const dropOnRight = e.clientX > midpoint;

      // Wenn rechts gedroppt und von links kommend, nach rechts verschieben
      if (dropOnRight && fromIndex < toIndex) {
        // toIndex bleibt gleich (Position nach der Ziel-Spalte)
      } else if (dropOnRight && fromIndex > toIndex) {
        // Von rechts kommend, rechts droppend -> nach der Ziel-Spalte
        toIndex = toIndex + 1;
      } else if (!dropOnRight && fromIndex > toIndex) {
        // toIndex bleibt gleich (Position vor der Ziel-Spalte)
      } else if (!dropOnRight && fromIndex < toIndex) {
        // Von links kommend, links droppend -> vor der Ziel-Spalte
        toIndex = toIndex - 1;
      }

      if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) {
        this.reorderColumns(fromIndex, toIndex);
      }

      // Cleanup
      $$('.column.drag-over-left, .column.drag-over-right').forEach(el => {
        el.classList.remove('drag-over-left', 'drag-over-right');
      });
    }
  }

  updateDropIndicator(columnBody, taskCard, mouseY) {
    // Remove existing indicators
    $$('.drop-indicator', columnBody).forEach(el => el.remove());

    const indicator = createElement('div', { className: 'drop-indicator' });

    if (!taskCard) {
      // Drop at the end
      columnBody.appendChild(indicator);
    } else {
      const rect = taskCard.getBoundingClientRect();
      const midpoint = rect.top + rect.height / 2;

      if (mouseY < midpoint) {
        columnBody.insertBefore(indicator, taskCard);
      } else {
        columnBody.insertBefore(indicator, taskCard.nextSibling);
      }
    }
  }

  // =====================
  // TASK OPERATIONS
  // =====================

  async moveTask(taskId, columnId, position) {
    const projectId = store.get('currentProjectId');

    // Optimistic update
    store.moveTask(taskId, columnId, position);

    try {
      await api.moveTask(projectId, taskId, columnId, position);
      syncManager.notifyTaskMoved(taskId, columnId, position);
    } catch (error) {
      console.error('Failed to move task:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'task:move',
          projectId,
          taskId,
          columnId,
          position
        });
      } else {
        this.showError('Aufgabe konnte nicht verschoben werden');
        // Reload to restore correct state
        await this.loadData();
      }
    }
  }

  async createTask(columnId, data) {
    const projectId = store.get('currentProjectId');
    const tempId = generateTempId();

    // Optimistic update
    const optimisticTask = {
      id: tempId,
      ...data,
      columnId: columnId,
      projectId: projectId,
      position: store.getTasksByColumn(columnId).length,
      createdAt: new Date().toISOString()
    };

    store.addTask(optimisticTask);

    try {
      const task = await api.createTask(projectId, { ...data, columnId: columnId });

      // Replace optimistic task with real one
      store.removeTask(tempId);
      store.addTask(task);

      syncManager.notifyTaskCreated(task);

      return task;
    } catch (error) {
      console.error('Failed to create task:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'task:create',
          projectId,
          tempId,
          data: { ...data, columnId: columnId }
        });
        return optimisticTask;
      } else {
        store.removeTask(tempId);
        throw error;
      }
    }
  }

  async deleteTask(taskId) {
    const projectId = store.get('currentProjectId');
    const task = store.getTaskById(taskId);

    // Store for undo
    store.pushUndo({
      type: 'DELETE_TASK',
      task: { ...task }
    });

    // Optimistic delete
    store.removeTask(taskId);

    try {
      await api.deleteTask(projectId, taskId);
      syncManager.notifyTaskDeleted(taskId, task.title);
    } catch (error) {
      console.error('Failed to delete task:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'task:delete',
          projectId,
          taskId
        });
      } else {
        // Restore task on error
        store.addTask(task);
        throw error;
      }
    }
  }

  async confirmDeleteTasks(taskIds) {
    const count = taskIds.length;
    const message = count === 1
      ? 'Möchten Sie diese Aufgabe wirklich löschen?'
      : `Möchten Sie diese ${count} Aufgaben wirklich löschen?`;

    window.dispatchEvent(new CustomEvent('confirm:show', {
      detail: {
        message,
        confirmText: 'Löschen',
        confirmClass: 'btn-danger',
        onConfirm: async () => {
          for (const taskId of taskIds) {
            await this.deleteTask(taskId);
          }
          store.clearSelection();
          this.showSuccess(`${count} Aufgabe(n) gelöscht`);
        }
      }
    }));
  }

  // =====================
  // COLUMN OPERATIONS
  // =====================

  async createColumn(name, color = null, filterCategory = 'in_progress') {
    const projectId = store.get('currentProjectId');
    const tempId = generateTempId();

    const optimisticColumn = {
      id: tempId,
      name,
      color,
      filterCategory,
      projectId: projectId,
      position: store.get('columns').length
    };

    store.addColumn(optimisticColumn);

    try {
      const column = await api.createColumn(projectId, { name, color, filterCategory });

      store.removeColumn(tempId);
      store.addColumn(column);

      syncManager.notifyColumnCreated(column);

      return column;
    } catch (error) {
      console.error('Failed to create column:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'column:create',
          projectId,
          tempId,
          data: { name }
        });
        return optimisticColumn;
      } else {
        store.removeColumn(tempId);
        throw error;
      }
    }
  }

  async updateColumn(columnId, data) {
    const projectId = store.get('currentProjectId');
    const originalColumn = store.get('columns').find(c => c.id === columnId);

    store.updateColumn(columnId, data);

    try {
      const column = await api.updateColumn(projectId, columnId, data);
      store.updateColumn(columnId, column);
      syncManager.notifyColumnUpdated(column);
    } catch (error) {
      console.error('Failed to update column:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'column:update',
          projectId,
          columnId,
          data
        });
      } else {
        store.updateColumn(columnId, originalColumn);
        throw error;
      }
    }
  }

  async deleteColumn(columnId) {
    const projectId = store.get('currentProjectId');
    const column = store.get('columns').find(c => c.id === columnId);
    const tasksInColumn = store.getTasksByColumn(columnId);

    if (tasksInColumn.length > 0) {
      this.showError('Spalte enthält noch Aufgaben. Bitte verschieben oder löschen Sie diese zuerst.');
      return;
    }

    store.removeColumn(columnId);

    try {
      await api.deleteColumn(projectId, columnId);
      syncManager.notifyColumnDeleted(columnId);
    } catch (error) {
      console.error('Failed to delete column:', error);

      if (!navigator.onLine) {
        await offlineManager.queueOperation({
          type: 'column:delete',
          projectId,
          columnId
        });
      } else {
        store.addColumn(column);
        throw error;
      }
    }
  }

  async reorderColumns(fromIndex, toIndex) {
    const projectId = store.get('currentProjectId');
    const columns = [...store.get('columns')];

    // Reorder
    const [moved] = columns.splice(fromIndex, 1);
    columns.splice(toIndex, 0, moved);

    const columnIds = columns.map(c => c.id);

    store.reorderColumns(columnIds);

    try {
      // API erwartet: columnId und newPosition
      await api.reorderColumns(projectId, moved.id, toIndex);
      syncManager.notifyColumnsReordered(columnIds);
    } catch (error) {
      console.error('Failed to reorder columns:', error);
      // Reload to fix order
      await this.loadData();
    }
  }

  confirmDeleteColumn(columnId) {
    const column = store.get('columns').find(c => c.id === columnId);
    const tasksCount = store.getTasksByColumn(columnId).length;

    if (tasksCount > 0) {
      this.showError(`Die Spalte "${column.name}" enthält ${tasksCount} Aufgabe(n). Bitte verschieben oder löschen Sie diese zuerst.`);
      return;
    }

    window.dispatchEvent(new CustomEvent('confirm:show', {
      detail: {
        message: `Möchten Sie die Spalte "${column.name}" wirklich löschen?`,
        confirmText: 'Löschen',
        confirmClass: 'btn-danger',
        onConfirm: () => this.deleteColumn(columnId)
      }
    }));
  }

  // =====================
  // DATA LOADING
  // =====================

  async loadData() {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    store.setLoading(true);

    try {
      const [columns, tasks, labels] = await Promise.all([
        api.getColumns(projectId),
        api.getTasks(projectId),
        api.getLabels(projectId)
      ]);

      store.setColumns(columns);
      store.setTasks(tasks);
      store.setLabels(labels);

      this.render();
    } catch (error) {
      console.error('Failed to load board data:', error);

      // Try loading from cache
      if (!navigator.onLine || error.isOffline) {
        await offlineManager.loadOfflineData();
        this.render();
      } else {
        this.showError('Fehler beim Laden der Daten');
      }
    } finally {
      store.setLoading(false);
    }
  }

  // =====================
  // MODALS
  // =====================

  openAddColumnModal() {
    window.dispatchEvent(new CustomEvent('modal:open', {
      detail: {
        modalId: 'column-modal',
        mode: 'create'
      }
    }));
  }

  openEditColumnModal(columnId) {
    const column = store.get('columns').find(c => c.id === columnId);

    window.dispatchEvent(new CustomEvent('modal:open', {
      detail: {
        modalId: 'column-modal',
        mode: 'edit',
        data: column
      }
    }));
  }

  openAddTaskModal(columnId) {
    window.dispatchEvent(new CustomEvent('modal:open', {
      detail: {
        modalId: 'task-modal',
        mode: 'create',
        data: { columnId }
      }
    }));
  }

  openTaskModal(taskId) {
    const task = store.getTaskById(taskId);
    if (!task) return;

    store.setEditingTask(task);

    window.dispatchEvent(new CustomEvent('modal:open', {
      detail: {
        modalId: 'task-modal',
        mode: 'edit',
        data: { taskId }
      }
    }));
  }

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

  createIcon(name) {
    const icons = {
      edit: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>',
      trash: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',
      calendar: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>',
      clock: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',
      message: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
      paperclip: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>'
    };

    const span = createElement('span', { className: 'icon' });
    span.innerHTML = icons[name] || '';
    return span;
  }

  getPriorityLabel(priority) {
    const labels = {
      high: 'Hohe Priorität',
      medium: 'Mittlere Priorität',
      low: 'Niedrige Priorität'
    };
    return labels[priority] || priority;
  }

  // Check if task is in the last column (completed)
  isTaskCompleted(task) {
    const columns = store.get('columns');
    if (!columns || columns.length === 0) return false;
    const lastColumnId = columns[columns.length - 1].id;
    return task.columnId === lastColumnId;
  }

  formatEstimate(hours, minutes) {
    const parts = [];
    if (hours) parts.push(`${hours}h`);
    if (minutes) parts.push(`${minutes}m`);
    return parts.join(' ') || '-';
  }

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

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

  // =====================
  // WEEK STRIP CALENDAR
  // =====================

  getMonday(date) {
    const d = new Date(date);
    const day = d.getDay();
    const diff = d.getDate() - day + (day === 0 ? -6 : 1);
    d.setDate(diff);
    d.setHours(0, 0, 0, 0);
    return d;
  }

  // Format date as YYYY-MM-DD in local timezone (avoids UTC conversion issues)
  formatLocalDate(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }

  bindWeekStripEvents() {
    $('#week-strip-prev')?.addEventListener('click', () => {
      this.weekStripDate.setDate(this.weekStripDate.getDate() - 7);
      this.renderWeekStrip();
    });

    $('#week-strip-next')?.addEventListener('click', () => {
      this.weekStripDate.setDate(this.weekStripDate.getDate() + 7);
      this.renderWeekStrip();
    });

    $('#week-strip-today')?.addEventListener('click', () => {
      this.weekStripDate = this.getMonday(new Date());
      this.renderWeekStrip();
    });

    // Tooltip cleanup on mouse leave
    document.addEventListener('mouseleave', () => this.hideTooltip());

    // Listen for app refresh events (task create/update/delete)
    window.addEventListener('app:refresh', () => this.renderWeekStrip());

    // Listen for task modal close (in case task was edited)
    window.addEventListener('modal:close', (e) => {
      if (e.detail?.modalId === 'task-modal') {
        // Small delay to ensure store is updated
        setTimeout(() => this.renderWeekStrip(), 100);
      }
    });
  }

  renderWeekStrip() {
    const container = $('#week-strip-days');
    if (!container) return;

    const columns = store.get('columns');
    const lastColumnId = columns.length > 0 ? columns[columns.length - 1].id : null;

    // Only show open and in-progress tasks (not completed/last column)
    const tasks = store.get('tasks').filter(t =>
      !t.archived && t.columnId !== lastColumnId
    );
    const today = new Date();
    today.setHours(0, 0, 0, 0);

    const dayNames = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
    let html = '';

    for (let i = 0; i < 7; i++) {
      const date = new Date(this.weekStripDate);
      date.setDate(date.getDate() + i);
      date.setHours(0, 0, 0, 0);

      const dateStr = this.formatLocalDate(date);
      const isToday = this.formatLocalDate(date) === this.formatLocalDate(today);
      const isWeekend = i >= 5;

      // Find tasks that start or end on this day
      const dayTasks = this.getTasksForDay(tasks, dateStr);

      const classes = ['week-strip-day'];
      if (isToday) classes.push('today');
      if (isWeekend) classes.push('weekend');

      html += `
        <div class="${classes.join(' ')}" data-date="${dateStr}">
          <span class="week-strip-day-name">${dayNames[i]}</span>
          <span class="week-strip-day-number">${date.getDate()}</span>
          <div class="week-strip-day-dots">
            ${this.renderDayDots(dayTasks, dateStr)}
          </div>
        </div>
      `;
    }

    container.innerHTML = html;

    // Bind dot events
    container.querySelectorAll('.week-strip-dot').forEach(dot => {
      dot.addEventListener('mouseenter', (e) => this.showTaskTooltip(e, dot));
      dot.addEventListener('mouseleave', () => this.hideTooltip());
      dot.addEventListener('click', (e) => this.openTaskFromDot(e, dot));
    });
  }

  getTasksForDay(tasks, dateStr) {
    // Gruppiere Aufgaben nach Spalte
    const columnGroups = new Map();
    const columns = store.get('columns');

    tasks.forEach(task => {
      const startDate = task.startDate ? task.startDate.split('T')[0] : null;
      const dueDate = task.dueDate ? task.dueDate.split('T')[0] : null;

      const isStart = startDate === dateStr;
      const isEnd = dueDate === dateStr;

      if (isStart || isEnd) {
        const columnId = task.columnId;
        if (!columnGroups.has(columnId)) {
          const column = columns.find(c => c.id === columnId);
          columnGroups.set(columnId, {
            column,
            tasks: []
          });
        }
        columnGroups.get(columnId).tasks.push({
          task,
          isStart,
          isEnd
        });
      }
    });

    return columnGroups;
  }

  renderDayDots(columnGroups, dateStr) {
    if (columnGroups.size === 0) return '';

    const dots = [];

    columnGroups.forEach(({ column, tasks }, columnId) => {
      const color = column?.color || '#6B7280';
      const taskIds = tasks.map(t => t.task.id).join(',');

      // Bestimme Dot-Typ basierend auf allen Aufgaben der Spalte
      const hasStart = tasks.some(t => t.isStart);
      const hasEnd = tasks.some(t => t.isEnd);

      let typeClass = '';
      if (hasStart && hasEnd) {
        typeClass = 'both';
      } else if (hasStart) {
        typeClass = 'start';
      } else {
        typeClass = 'end';
      }

      dots.push(`<span class="week-strip-dot ${typeClass}"
                       style="color: ${color}"
                       data-column-id="${columnId}"
                       data-task-ids="${taskIds}"
                       data-column-name="${this.escapeHtml(column?.name || '')}"></span>`);
    });

    return dots.join('');
  }

  showTaskTooltip(event, dot) {
    const taskIds = dot.dataset.taskIds ? dot.dataset.taskIds.split(',').map(id => parseInt(id)) : [];
    const columnName = dot.dataset.columnName || 'Unbekannt';
    const columnId = parseInt(dot.dataset.columnId);

    if (taskIds.length === 0) return;

    const allTasks = store.get('tasks');
    const columns = store.get('columns');
    const column = columns.find(c => c.id === columnId);
    const color = column?.color || '#6B7280';

    // Sammle alle Aufgaben mit ihren Start/Ende-Infos
    const tasksWithDates = taskIds.map(taskId => {
      const task = allTasks.find(t => t.id === taskId);
      if (!task) return null;

      const dayDate = dot.closest('.week-strip-day')?.dataset.date;
      const startDate = task.startDate ? task.startDate.split('T')[0] : null;
      const dueDate = task.dueDate ? task.dueDate.split('T')[0] : null;
      const isStart = startDate === dayDate;
      const isEnd = dueDate === dayDate;

      let typeLabel = '';
      if (isStart && isEnd) {
        typeLabel = 'Start & Ende';
      } else if (isStart) {
        typeLabel = 'Start';
      } else if (isEnd) {
        typeLabel = 'Ende';
      }

      return { task, typeLabel, isStart, isEnd };
    }).filter(Boolean);

    if (tasksWithDates.length === 0) return;

    // Create tooltip
    this.hideTooltip();
    const tooltip = document.createElement('div');
    tooltip.className = 'week-strip-tooltip';

    const taskCount = tasksWithDates.length;
    const taskListHtml = tasksWithDates.map(({ task, typeLabel, isStart }) => `
      <div class="week-strip-tooltip-task">
        <span class="week-strip-tooltip-task-dot ${isStart ? 'start' : 'end'}" style="color: ${color}"></span>
        <span class="week-strip-tooltip-task-title">${this.escapeHtml(task.title)}</span>
        <span class="week-strip-tooltip-task-type">(${typeLabel})</span>
      </div>
    `).join('');

    tooltip.innerHTML = `
      <div class="week-strip-tooltip-header" style="border-left-color: ${color}">
        <span class="week-strip-tooltip-column-name">${this.escapeHtml(columnName)}</span>
        <span class="week-strip-tooltip-count">${taskCount} Aufgabe${taskCount > 1 ? 'n' : ''}</span>
      </div>
      <div class="week-strip-tooltip-task-list">
        ${taskListHtml}
      </div>
    `;

    document.body.appendChild(tooltip);
    this.tooltip = tooltip;

    // Position tooltip
    const rect = dot.getBoundingClientRect();
    const tooltipRect = tooltip.getBoundingClientRect();

    let left = rect.left + (rect.width / 2) - (tooltipRect.width / 2);
    let top = rect.bottom + 8;

    // Keep within viewport
    if (left < 10) left = 10;
    if (left + tooltipRect.width > window.innerWidth - 10) {
      left = window.innerWidth - tooltipRect.width - 10;
    }
    if (top + tooltipRect.height > window.innerHeight - 10) {
      top = rect.top - tooltipRect.height - 8;
    }

    tooltip.style.left = `${left}px`;
    tooltip.style.top = `${top}px`;
  }

  hideTooltip() {
    if (this.tooltip) {
      this.tooltip.remove();
      this.tooltip = null;
    }
  }

  openTaskFromDot(event, dot) {
    event.stopPropagation();
    const taskIds = dot.dataset.taskIds ? dot.dataset.taskIds.split(',').map(id => parseInt(id)) : [];

    if (taskIds.length === 0) return;

    // Öffne die erste Aufgabe
    const taskId = taskIds[0];

    window.dispatchEvent(new CustomEvent('modal:open', {
      detail: { modalId: 'task-modal', mode: 'edit', data: { taskId } }
    }));
  }

  escapeHtml(str) {
    if (!str) return '';
    const div = document.createElement('div');
    div.textContent = str;
    return div.innerHTML;
  }

}

// Create and export singleton
const boardManager = new BoardManager();

export default boardManager;
