/**
 * TASKMATE - List View Module
 * ===========================
 * Tabellarische Listenansicht der Aufgaben
 * Unterstützt gruppierte und flache Ansicht mit Inline-Bearbeitung
 */

import store from './store.js';
import api from './api.js';
import {
  $, $$, createElement, clearElement, formatDate,
  getDueDateStatus, filterTasks, getInitials, hexToRgba,
  getContrastColor, groupBy, sortBy, escapeHtml
} from './utils.js';

class ListViewManager {
  constructor() {
    // DOM Elements
    this.container = null;
    this.contentElement = null;
    this.sortSelect = null;
    this.sortDirectionBtn = null;

    // State
    this.viewMode = 'grouped'; // 'grouped' | 'flat'
    this.sortColumn = 'dueDate';
    this.sortDirection = 'asc';
    this.collapsedGroups = new Set();

    // Inline editing state
    this.editingCell = null;

    this.init();
  }

  init() {
    this.container = $('#view-list');
    this.contentElement = $('#list-content');
    this.sortSelect = $('#list-sort-select');
    this.sortDirectionBtn = $('#list-sort-direction');

    if (!this.container) return;

    this.bindEvents();

    // Subscribe to store changes for real-time updates
    store.subscribe('tasks', () => this.render());
    store.subscribe('columns', () => this.render());
    store.subscribe('filters', () => this.render());
    store.subscribe('searchResultIds', () => this.render());
    store.subscribe('users', () => this.render());
    store.subscribe('labels', () => this.render());
    store.subscribe('currentView', (view) => {
      if (view === 'list') this.render();
    });

    // Listen for app refresh events
    window.addEventListener('app:refresh', () => this.render());
  }

  bindEvents() {
    // View mode toggle
    $$('.list-toggle-btn', this.container).forEach(btn => {
      btn.addEventListener('click', () => this.setViewMode(btn.dataset.mode));
    });

    // Sort select
    if (this.sortSelect) {
      this.sortSelect.addEventListener('change', () => {
        this.sortColumn = this.sortSelect.value;
        this.render();
      });
    }

    // Sort direction button
    if (this.sortDirectionBtn) {
      this.sortDirectionBtn.addEventListener('click', () => {
        this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
        this.sortDirectionBtn.classList.toggle('asc', this.sortDirection === 'asc');
        this.render();
      });
    }

    // Delegate click events on content
    if (this.contentElement) {
      this.contentElement.addEventListener('click', (e) => this.handleContentClick(e));
      this.contentElement.addEventListener('change', (e) => this.handleContentChange(e));
      this.contentElement.addEventListener('dblclick', (e) => this.handleDoubleClick(e));
      
      // Stop editing when clicking outside
      document.addEventListener('click', (e) => {
        if (this.editingCell && !this.editingCell.contains(e.target)) {
          this.stopEditing();
        }
      });
    }
  }

  setViewMode(mode) {
    this.viewMode = mode;

    // Update toggle buttons
    $$('.list-toggle-btn', this.container).forEach(btn => {
      btn.classList.toggle('active', btn.dataset.mode === mode);
    });

    this.render();
  }

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

  render() {
    if (!this.contentElement) return;
    if (store.get('currentView') !== 'list') return;

    const tasks = this.getFilteredAndSortedTasks();

    if (tasks.length === 0) {
      this.renderEmpty();
      return;
    }

    if (this.viewMode === 'grouped') {
      this.renderGrouped(tasks);
    } else {
      this.renderFlat(tasks);
    }
  }

  getFilteredAndSortedTasks() {
    const tasks = store.get('tasks').filter(t => !t.archived);
    const filters = store.get('filters');
    const searchResultIds = store.get('searchResultIds') || [];
    const columns = store.get('columns');

    // Apply filters
    let filtered = filterTasks(tasks, filters, searchResultIds, columns);

    // Apply sorting
    filtered = this.sortTasks(filtered);

    return filtered;
  }

  sortTasks(tasks) {
    const columns = store.get('columns');
    const users = store.get('users');

    return sortBy(tasks, (task) => {
      switch (this.sortColumn) {
        case 'title':
          return task.title?.toLowerCase() || '';
        case 'priority':
          const priorityOrder = { high: 0, medium: 1, low: 2 };
          return priorityOrder[task.priority] ?? 1;
        case 'dueDate':
          return task.dueDate ? new Date(task.dueDate).getTime() : Infinity;
        case 'status':
          const colIndex = columns.findIndex(c => c.id === task.columnId);
          return colIndex >= 0 ? colIndex : Infinity;
        case 'assignee':
          const user = users.find(u => u.id === task.assignedTo);
          return user?.displayName?.toLowerCase() || 'zzz';
        default:
          return task.title?.toLowerCase() || '';
      }
    }, this.sortDirection);
  }

  renderEmpty() {
    this.contentElement.innerHTML = `
      <div class="list-empty">
        <svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" fill="none"/><path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="2" fill="none"/></svg>
        <h3>Keine Aufgaben gefunden</h3>
        <p>Erstellen Sie eine neue Aufgabe oder ändern Sie die Filter.</p>
      </div>
    `;
  }

  renderGrouped(tasks) {
    const columns = store.get('columns');
    const tasksByColumn = groupBy(tasks, 'columnId');

    clearElement(this.contentElement);

    columns.forEach(column => {
      const columnTasks = tasksByColumn[column.id] || [];
      if (columnTasks.length === 0) return;

      const isCollapsed = this.collapsedGroups.has(column.id);

      const group = createElement('div', { className: 'list-group' });

      // Group header
      const header = createElement('div', {
        className: `list-group-header ${isCollapsed ? 'collapsed' : ''}`,
        dataset: { columnId: column.id }
      });

      header.innerHTML = `
        <svg viewBox="0 0 24 24"><path d="m6 9 6 6 6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
        <span class="list-group-color" style="background-color: ${column.color || '#6366F1'}"></span>
        <span class="list-group-title">${escapeHtml(column.name)}</span>
        <span class="list-group-count">${columnTasks.length} Aufgabe${columnTasks.length !== 1 ? 'n' : ''}</span>
      `;

      header.addEventListener('click', () => this.toggleGroup(column.id));

      group.appendChild(header);

      // Group content (table)
      const content = createElement('div', {
        className: `list-group-content ${isCollapsed ? 'collapsed' : ''}`
      });

      // Table header
      content.appendChild(this.renderTableHeader());

      // Table rows
      columnTasks.forEach(task => {
        content.appendChild(this.renderTableRow(task, column));
      });

      group.appendChild(content);
      this.contentElement.appendChild(group);
    });
  }

  renderFlat(tasks) {
    clearElement(this.contentElement);

    const tableContainer = createElement('div', { className: 'list-table' });

    // Table header
    tableContainer.appendChild(this.renderTableHeader());

    // Table rows
    const columns = store.get('columns');
    tasks.forEach(task => {
      const column = columns.find(c => c.id === task.columnId);
      tableContainer.appendChild(this.renderTableRow(task, column));
    });

    this.contentElement.appendChild(tableContainer);
  }

  renderTableHeader() {
    const header = createElement('div', { className: 'list-table-header' });

    const columnDefs = [
      { key: 'title', label: 'Aufgabe' },
      { key: 'status', label: 'Status' },
      { key: 'priority', label: 'Priorität' },
      { key: 'dueDate', label: 'Fällig' },
      { key: 'assignee', label: 'Zugewiesen' }
    ];

    columnDefs.forEach(col => {
      const isSorted = this.sortColumn === col.key;
      const span = createElement('span', {
        className: isSorted ? `sorted ${this.sortDirection}` : '',
        dataset: { sortKey: col.key }
      });

      span.innerHTML = `
        ${col.label}
        <svg viewBox="0 0 24 24"><path d="m6 9 6 6 6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
      `;

      span.addEventListener('click', () => {
        if (this.sortColumn === col.key) {
          this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
          this.sortColumn = col.key;
          this.sortDirection = 'asc';
        }
        if (this.sortSelect) this.sortSelect.value = this.sortColumn;
        if (this.sortDirectionBtn) {
          this.sortDirectionBtn.classList.toggle('asc', this.sortDirection === 'asc');
        }
        this.render();
      });

      header.appendChild(span);
    });

    return header;
  }

  renderTableRow(task, column) {
    const row = createElement('div', {
      className: 'list-row',
      dataset: { taskId: task.id }
    });

    // Title cell
    row.appendChild(this.renderTitleCell(task, column));

    // Status cell
    row.appendChild(this.renderStatusCell(task, column));

    // Priority cell
    row.appendChild(this.renderPriorityCell(task));

    // Due date cell
    row.appendChild(this.renderDueDateCell(task));

    // Assignee cell
    row.appendChild(this.renderAssigneeCell(task));

    return row;
  }

  renderTitleCell(task, column) {
    const cell = createElement('div', { className: 'list-cell list-cell-title' });

    // Color indicator
    const colorDot = createElement('span', {
      className: 'status-dot',
      style: { backgroundColor: column?.color || '#6366F1' }
    });
    cell.appendChild(colorDot);

    // Title text (clickable to open task)
    const titleSpan = createElement('span', {
      dataset: { action: 'open-task', taskId: task.id }
    }, [escapeHtml(task.title)]);

    cell.appendChild(titleSpan);

    return cell;
  }

  renderStatusCell(task, column) {
    const columns = store.get('columns');
    const cell = createElement('div', { className: 'list-cell list-cell-status list-cell-editable' });

    // Status dot
    const dot = createElement('span', {
      className: 'status-dot',
      style: { backgroundColor: column?.color || '#6366F1' }
    });
    cell.appendChild(dot);

    // Status dropdown
    const select = createElement('select', {
      dataset: { field: 'columnId', taskId: task.id }
    });

    columns.forEach(col => {
      const option = createElement('option', {
        value: col.id,
        selected: col.id === task.columnId
      }, [col.name]);
      select.appendChild(option);
    });

    cell.appendChild(select);

    return cell;
  }

  renderPriorityCell(task) {
    const cell = createElement('div', {
      className: `list-cell list-cell-priority ${task.priority || 'medium'} list-cell-editable`
    });

    const select = createElement('select', {
      dataset: { field: 'priority', taskId: task.id }
    });

    const priorities = [
      { value: 'high', label: 'Hoch' },
      { value: 'medium', label: 'Mittel' },
      { value: 'low', label: 'Niedrig' }
    ];

    priorities.forEach(p => {
      const option = createElement('option', {
        value: p.value,
        selected: p.value === (task.priority || 'medium')
      }, [p.label]);
      select.appendChild(option);
    });

    cell.appendChild(select);

    return cell;
  }

  renderDueDateCell(task) {
    const status = getDueDateStatus(task.dueDate);
    let className = 'list-cell list-cell-date list-cell-editable';

    if (status === 'overdue') className += ' overdue';
    else if (status === 'today') className += ' today';

    const cell = createElement('div', { className });

    const input = createElement('input', {
      type: 'date',
      value: task.dueDate ? this.formatDateForInput(task.dueDate) : '',
      dataset: { field: 'dueDate', taskId: task.id }
    });

    cell.appendChild(input);

    return cell;
  }

  renderAssigneeCell(task) {
    const users = store.get('users');
    const cell = createElement('div', { className: 'list-cell list-cell-assignee list-cell-editable' });

    // Sammle alle zugewiesenen Benutzer aus assignees Array
    const assignedUserIds = new Set();
    
    // Verwende das assignees Array vom Backend
    if (task.assignees && Array.isArray(task.assignees)) {
      task.assignees.forEach(assignee => {
        if (assignee && assignee.id) {
          assignedUserIds.add(assignee.id);
        }
      });
    }
    
    // Fallback: Füge assigned_to hinzu falls assignees leer ist
    if (assignedUserIds.size === 0 && task.assignedTo) {
      assignedUserIds.add(task.assignedTo);
    }

    // Container für mehrere Avatare
    const avatarContainer = createElement('div', { className: 'avatar-container' });

    if (assignedUserIds.size > 0) {
      // Erstelle Avatar für jeden zugewiesenen Benutzer
      Array.from(assignedUserIds).forEach(userId => {
        const user = users.find(u => u.id === userId);
        if (user) {
          const avatar = createElement('div', {
            className: 'avatar',
            style: { backgroundColor: user.color || '#6366F1' },
            title: user.displayName // Tooltip zeigt Name beim Hover
          }, [user.initials || getInitials(user.displayName)]);
          avatarContainer.appendChild(avatar);
        }
      });
    } else {
      // Placeholder für "nicht zugewiesen"
      const placeholder = createElement('div', {
        className: 'avatar avatar-empty',
        title: 'Nicht zugewiesen'
      }, ['?']);
      avatarContainer.appendChild(placeholder);
    }

    cell.appendChild(avatarContainer);

    // User dropdown (versteckt, nur für Bearbeitung)
    const select = createElement('select', {
      className: 'assignee-select hidden',
      dataset: { field: 'assignedTo', taskId: task.id }
    });

    // Empty option
    const emptyOption = createElement('option', { value: '' }, ['Nicht zugewiesen']);
    select.appendChild(emptyOption);

    users.forEach(user => {
      const option = createElement('option', {
        value: user.id,
        selected: user.id === task.assignedTo
      }, [user.displayName]);
      select.appendChild(option);
    });

    cell.appendChild(select);

    return cell;
  }

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

  handleContentClick(e) {
    // Handle avatar click for assignee editing
    if (e.target.classList.contains('avatar') || e.target.classList.contains('avatar-empty')) {
      const cell = e.target.closest('.list-cell-assignee');
      if (cell) {
        this.startEditingAssignee(cell);
        return;
      }
    }

    // Handle click on avatar container (wenn man neben Avatar klickt)
    if (e.target.classList.contains('avatar-container')) {
      const cell = e.target.closest('.list-cell-assignee');
      if (cell) {
        this.startEditingAssignee(cell);
        return;
      }
    }

    const target = e.target.closest('[data-action]');
    if (!target) return;

    const action = target.dataset.action;
    const taskId = target.dataset.taskId;

    if (action === 'open-task' && taskId) {
      this.openTask(parseInt(taskId));
    }
  }

  /**
   * Start editing assignee
   */
  startEditingAssignee(cell) {
    // Stop any current editing
    this.stopEditing();

    // Add editing class to show dropdown and hide avatar
    cell.classList.add('editing');
    
    // Focus the select element
    const select = cell.querySelector('.assignee-select');
    if (select) {
      select.focus();
    }

    this.editingCell = cell;
  }

  /**
   * Stop editing
   */
  stopEditing() {
    if (this.editingCell) {
      this.editingCell.classList.remove('editing');
      this.editingCell = null;
    }
  }

  handleContentChange(e) {
    const target = e.target;
    const field = target.dataset.field;
    const taskId = target.dataset.taskId;

    if (field && taskId) {
      this.updateTaskField(parseInt(taskId), field, target.value);
      
      // Stop editing after change for assignee field
      if (field === 'assignedTo') {
        this.stopEditing();
      }
    }
  }

  handleDoubleClick(e) {
    const titleCell = e.target.closest('.list-cell-title span[data-action="open-task"]');
    if (titleCell) {
      const taskId = titleCell.dataset.taskId;
      if (taskId) {
        this.startInlineEdit(parseInt(taskId), titleCell);
      }
    }
  }

  toggleGroup(columnId) {
    if (this.collapsedGroups.has(columnId)) {
      this.collapsedGroups.delete(columnId);
    } else {
      this.collapsedGroups.add(columnId);
    }

    // Update DOM without full re-render
    const header = this.contentElement.querySelector(`.list-group-header[data-column-id="${columnId}"]`);
    const content = header?.nextElementSibling;

    if (header && content) {
      header.classList.toggle('collapsed');
      content.classList.toggle('collapsed');
    }
  }

  // =====================
  // INLINE EDITING
  // =====================

  startInlineEdit(taskId, element) {
    if (this.editingCell) {
      this.cancelInlineEdit();
    }

    const task = store.get('tasks').find(t => t.id === taskId);
    if (!task) return;

    this.editingCell = { taskId, element, originalValue: task.title };

    const input = createElement('input', {
      type: 'text',
      className: 'list-inline-input',
      value: task.title
    });

    input.addEventListener('blur', () => this.finishInlineEdit());
    input.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        this.finishInlineEdit();
      } else if (e.key === 'Escape') {
        this.cancelInlineEdit();
      }
    });

    element.textContent = '';
    element.appendChild(input);
    input.focus();
    input.select();
  }

  async finishInlineEdit() {
    if (!this.editingCell) return;

    const { taskId, element } = this.editingCell;
    const input = element.querySelector('input');
    const newValue = input?.value?.trim();

    if (newValue && newValue !== this.editingCell.originalValue) {
      await this.updateTaskField(taskId, 'title', newValue);
    }

    this.editingCell = null;
    this.render();
  }

  cancelInlineEdit() {
    if (!this.editingCell) return;

    const { element, originalValue } = this.editingCell;
    element.textContent = originalValue;
    this.editingCell = null;
  }

  // =====================
  // API OPERATIONS
  // =====================

  async updateTaskField(taskId, field, value) {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    const task = store.get('tasks').find(t => t.id === taskId);
    if (!task) return;

    // Prepare update data
    let updateData = {};

    if (field === 'columnId') {
      updateData.columnId = parseInt(value);
    } else if (field === 'assignedTo') {
      updateData.assignedTo = value ? parseInt(value) : null;
    } else if (field === 'dueDate') {
      updateData.dueDate = value || null;
    } else if (field === 'priority') {
      updateData.priority = value;
    } else if (field === 'title') {
      updateData.title = value;
    }

    // Optimistic update
    const tasks = store.get('tasks').map(t => {
      if (t.id === taskId) {
        return { ...t, ...updateData };
      }
      return t;
    });
    store.set('tasks', tasks);

    try {
      await api.updateTask(projectId, taskId, updateData);

      // Dispatch refresh event
      window.dispatchEvent(new CustomEvent('app:refresh'));
    } catch (error) {
      console.error('Fehler beim Aktualisieren der Aufgabe:', error);

      // Rollback on error
      const originalTasks = store.get('tasks').map(t => {
        if (t.id === taskId) {
          return task;
        }
        return t;
      });
      store.set('tasks', originalTasks);

      // Show error notification
      window.dispatchEvent(new CustomEvent('toast:show', {
        detail: {
          type: 'error',
          message: 'Fehler beim Speichern der Änderung'
        }
      }));
    }
  }

  openTask(taskId) {
    const task = store.get('tasks').find(t => t.id === taskId);
    if (task) {
      window.dispatchEvent(new CustomEvent('task:edit', { detail: { task } }));
    }
  }

  // =====================
  // UTILITIES
  // =====================

  formatDateForInput(dateString) {
    if (!dateString) return '';
    const date = new Date(dateString);
    // Use local date formatting (NOT toISOString!)
    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}`;
  }
}

// Create and export singleton instance
const listViewManager = new ListViewManager();
export default listViewManager;
