/**
 * TASKMATE - Task Routes
 * ======================
 * CRUD für Aufgaben
 */

const express = require('express');
const router = express.Router();
const { getDb } = require('../database');
const logger = require('../utils/logger');
const { validators } = require('../middleware/validation');
const notificationService = require('../services/notificationService');

/**
 * Hilfsfunktion: Historie-Eintrag erstellen
 */
function addHistory(db, taskId, userId, action, fieldChanged = null, oldValue = null, newValue = null) {
  db.prepare(`
    INSERT INTO history (task_id, user_id, action, field_changed, old_value, new_value)
    VALUES (?, ?, ?, ?, ?, ?)
  `).run(taskId, userId, action, fieldChanged, oldValue, newValue);
}

/**
 * Hilfsfunktion: Vollständige Task-Daten laden
 */
function getFullTask(db, taskId) {
  const task = db.prepare(`
    SELECT t.*,
           c.username as creator_name
    FROM tasks t
    LEFT JOIN users c ON t.created_by = c.id
    WHERE t.id = ?
  `).get(taskId);

  if (!task) return null;

  // Zugewiesene Mitarbeiter laden (Mehrfachzuweisung)
  const assignees = db.prepare(`
    SELECT u.id, u.username, u.display_name, u.color
    FROM task_assignees ta
    JOIN users u ON ta.user_id = u.id
    WHERE ta.task_id = ?
    ORDER BY u.username
  `).all(taskId);

  // Labels laden
  const labels = db.prepare(`
    SELECT l.* FROM labels l
    JOIN task_labels tl ON l.id = tl.label_id
    WHERE tl.task_id = ?
  `).all(taskId);

  // Subtasks laden
  const subtasks = db.prepare(`
    SELECT * FROM subtasks WHERE task_id = ? ORDER BY position
  `).all(taskId);

  // Anhänge zählen
  const attachmentCount = db.prepare(
    'SELECT COUNT(*) as count FROM attachments WHERE task_id = ?'
  ).get(taskId).count;

  // Links zählen
  const linkCount = db.prepare(
    'SELECT COUNT(*) as count FROM links WHERE task_id = ?'
  ).get(taskId).count;

  // Kommentare zählen
  const commentCount = db.prepare(
    'SELECT COUNT(*) as count FROM comments WHERE task_id = ?'
  ).get(taskId).count;

  // Verknüpfte Genehmigungen laden
  const proposals = db.prepare(`
    SELECT p.id, p.title, p.approved, p.approved_by,
           u.display_name as approved_by_name
    FROM proposals p
    LEFT JOIN users u ON p.approved_by = u.id
    WHERE p.task_id = ? AND p.archived = 0
    ORDER BY p.created_at DESC
  `).all(taskId);

  return {
    id: task.id,
    projectId: task.project_id,
    columnId: task.column_id,
    title: task.title,
    description: task.description,
    priority: task.priority,
    startDate: task.start_date,
    dueDate: task.due_date,
    // Neues Format: Array von Mitarbeitern
    assignees: assignees.map(a => ({
      id: a.id,
      username: a.username,
      display_name: a.display_name,
      color: a.color
    })),
    // Rückwärtskompatibilität: assignedTo als erster Mitarbeiter (falls vorhanden)
    assignedTo: assignees.length > 0 ? assignees[0].id : null,
    assignedName: assignees.length > 0 ? assignees[0].username : null,
    assignedColor: assignees.length > 0 ? assignees[0].color : null,
    timeEstimateMin: task.time_estimate_min,
    dependsOn: task.depends_on,
    position: task.position,
    archived: !!task.archived,
    createdAt: task.created_at,
    createdBy: task.created_by,
    creatorName: task.creator_name,
    updatedAt: task.updated_at,
    labels: labels.map(l => ({ id: l.id, name: l.name, color: l.color })),
    subtasks: subtasks.map(s => ({
      id: s.id,
      title: s.title,
      completed: !!s.completed,
      position: s.position
    })),
    subtaskProgress: {
      total: subtasks.length,
      completed: subtasks.filter(s => s.completed).length
    },
    attachmentCount,
    linkCount,
    commentCount,
    proposals: proposals.map(p => ({
      id: p.id,
      title: p.title,
      approved: !!p.approved,
      approvedByName: p.approved_by_name
    }))
  };
}

/**
 * GET /api/tasks/all
 * Alle aktiven Aufgaben (nicht archiviert) fuer Auswahl in Vorschlaegen
 */
router.get('/all', (req, res) => {
  try {
    const db = getDb();

    const tasks = db.prepare(`
      SELECT t.id, t.title, t.project_id, p.name as project_name
      FROM tasks t
      LEFT JOIN projects p ON t.project_id = p.id
      WHERE t.archived = 0
      ORDER BY p.name, t.title
    `).all();

    res.json(tasks);
  } catch (error) {
    logger.error('Fehler beim Abrufen aller Aufgaben:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * GET /api/tasks/project/:projectId
 * Alle Aufgaben eines Projekts
 */
router.get('/project/:projectId', (req, res) => {
  try {
    const db = getDb();
    const projectId = req.params.projectId;
    const includeArchived = req.query.archived === 'true';

    let query = `
      SELECT t.id FROM tasks t
      WHERE t.project_id = ?
    `;

    if (!includeArchived) {
      query += ' AND t.archived = 0';
    }

    query += ' ORDER BY t.column_id, t.position';

    const taskIds = db.prepare(query).all(projectId);
    const tasks = taskIds.map(t => getFullTask(db, t.id));

    res.json(tasks);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Aufgaben:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * GET /api/tasks/search
 * Aufgaben suchen - durchsucht auch Subtasks, Links, Anhänge und Kommentare
 * WICHTIG: Diese Route MUSS vor /:id definiert werden!
 */
router.get('/search', (req, res) => {
  try {
    const { q, projectId, assignedTo, priority, dueBefore, dueAfter, labels, archived } = req.query;

    const db = getDb();
    const params = [];

    // Basis-Query mit LEFT JOINs für tiefe Suche
    let query = `
      SELECT DISTINCT t.id FROM tasks t
      LEFT JOIN subtasks s ON t.id = s.task_id
      LEFT JOIN links l ON t.id = l.task_id
      LEFT JOIN attachments a ON t.id = a.task_id
      LEFT JOIN comments c ON t.id = c.task_id
      WHERE 1=1
    `;

    if (projectId) {
      query += ' AND t.project_id = ?';
      params.push(projectId);
    }

    // Erweiterte Textsuche: Titel, Beschreibung, Subtasks, Links, Anhänge, Kommentare
    if (q) {
      const searchTerm = `%${q}%`;
      query += ` AND (
        t.title LIKE ?
        OR t.description LIKE ?
        OR s.title LIKE ?
        OR l.url LIKE ?
        OR l.title LIKE ?
        OR a.original_name LIKE ?
        OR c.content LIKE ?
      )`;
      params.push(searchTerm, searchTerm, searchTerm, searchTerm, searchTerm, searchTerm, searchTerm);
    }

    if (assignedTo) {
      query += ' AND t.assigned_to = ?';
      params.push(assignedTo);
    }

    if (priority) {
      query += ' AND t.priority = ?';
      params.push(priority);
    }

    if (dueBefore) {
      query += ' AND t.due_date <= ?';
      params.push(dueBefore);
    }

    if (dueAfter) {
      query += ' AND t.due_date >= ?';
      params.push(dueAfter);
    }

    if (archived !== 'true') {
      query += ' AND t.archived = 0';
    }

    if (labels) {
      const labelIds = labels.split(',').map(id => parseInt(id)).filter(id => !isNaN(id));
      if (labelIds.length > 0) {
        query += ` AND t.id IN (
          SELECT task_id FROM task_labels WHERE label_id IN (${labelIds.map(() => '?').join(',')})
        )`;
        params.push(...labelIds);
      }
    }

    query += ' ORDER BY t.due_date ASC, t.priority DESC, t.updated_at DESC LIMIT 100';

    const taskIds = db.prepare(query).all(...params);
    const tasks = taskIds.map(t => getFullTask(db, t.id));

    logger.info(`Suche nach "${q}" in Projekt ${projectId}: ${tasks.length} Treffer`);

    res.json(tasks);
  } catch (error) {
    logger.error('Fehler bei der Suche:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * GET /api/tasks/:id
 * Einzelne Aufgabe mit allen Details
 */
router.get('/:id', (req, res) => {
  try {
    const db = getDb();
    const task = getFullTask(db, req.params.id);

    if (!task) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    // Historie laden
    const history = db.prepare(`
      SELECT h.*, u.display_name, u.color
      FROM history h
      JOIN users u ON h.user_id = u.id
      WHERE h.task_id = ?
      ORDER BY h.timestamp DESC
      LIMIT 50
    `).all(req.params.id);

    task.history = history.map(h => ({
      id: h.id,
      action: h.action,
      fieldChanged: h.field_changed,
      oldValue: h.old_value,
      newValue: h.new_value,
      timestamp: h.timestamp,
      userName: h.display_name,
      userColor: h.color
    }));

    res.json(task);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Aufgabe:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * POST /api/tasks
 * Neue Aufgabe erstellen
 */
router.post('/', (req, res) => {
  try {
    const {
      projectId, columnId, title, description, priority,
      startDate, dueDate, assignees, assignedTo, timeEstimateMin, dependsOn, labels
    } = req.body;

    // Validierung
    const errors = [];
    errors.push(validators.required(projectId, 'Projekt-ID'));
    errors.push(validators.required(columnId, 'Spalten-ID'));
    errors.push(validators.required(title, 'Titel'));
    errors.push(validators.maxLength(title, 200, 'Titel'));
    if (priority) errors.push(validators.enum(priority, ['low', 'medium', 'high'], 'Priorität'));
    if (startDate) errors.push(validators.date(startDate, 'Startdatum'));
    if (dueDate) errors.push(validators.date(dueDate, 'Fälligkeitsdatum'));
    if (timeEstimateMin) errors.push(validators.positiveInteger(timeEstimateMin, 'Zeitschätzung'));

    const firstError = errors.find(e => e !== null);
    if (firstError) {
      return res.status(400).json({ error: firstError });
    }

    const db = getDb();

    // Höchste Position in der Spalte ermitteln
    const maxPos = db.prepare(
      'SELECT COALESCE(MAX(position), -1) as max FROM tasks WHERE column_id = ?'
    ).get(columnId).max;

    // Aufgabe erstellen (ohne assigned_to, wird über task_assignees gemacht)
    const result = db.prepare(`
      INSERT INTO tasks (
        project_id, column_id, title, description, priority,
        start_date, due_date, time_estimate_min, depends_on, position, created_by
      )
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(
      projectId, columnId, title, description || null, priority || 'medium',
      startDate || null, dueDate || null, timeEstimateMin || null,
      dependsOn || null, maxPos + 1, req.user.id
    );

    const taskId = result.lastInsertRowid;

    // Mitarbeiter zuweisen (Mehrfachzuweisung)
    const assigneeIds = assignees && Array.isArray(assignees) ? assignees :
                        (assignedTo ? [assignedTo] : []);
    if (assigneeIds.length > 0) {
      const insertAssignee = db.prepare('INSERT INTO task_assignees (task_id, user_id) VALUES (?, ?)');
      assigneeIds.forEach(userId => {
        try {
          insertAssignee.run(taskId, userId);
        } catch (e) {
          // User existiert nicht oder bereits zugewiesen
        }
      });
    }

    // Labels zuweisen
    if (labels && Array.isArray(labels)) {
      const insertLabel = db.prepare('INSERT INTO task_labels (task_id, label_id) VALUES (?, ?)');
      labels.forEach(labelId => {
        try {
          insertLabel.run(taskId, labelId);
        } catch (e) {
          // Label existiert nicht, ignorieren
        }
      });
    }

    // Historie
    addHistory(db, taskId, req.user.id, 'created');

    const task = getFullTask(db, taskId);

    logger.info(`Aufgabe erstellt: ${title} (ID: ${taskId}) von ${req.user.username}`);

    // WebSocket
    const io = req.app.get('io');
    io.to(`project:${projectId}`).emit('task:created', task);

    // Benachrichtigungen an zugewiesene Mitarbeiter (außer Ersteller)
    if (assigneeIds.length > 0) {
      assigneeIds.forEach(assigneeId => {
        if (assigneeId !== req.user.id) {
          notificationService.create(assigneeId, 'task:assigned', {
            taskId: taskId,
            taskTitle: title,
            projectId: projectId,
            actorId: req.user.id,
            actorName: req.user.display_name || req.user.username
          }, io);
        }
      });
    }

    res.status(201).json(task);
  } catch (error) {
    logger.error('Fehler beim Erstellen der Aufgabe:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * PUT /api/tasks/:id
 * Aufgabe aktualisieren
 */
router.put('/:id', (req, res) => {
  try {
    const taskId = req.params.id;
    const {
      title, description, priority, columnId, startDate, dueDate, assignees, assignedTo,
      timeEstimateMin, dependsOn, labels
    } = req.body;

    const db = getDb();

    const existing = db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId);
    if (!existing) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    // Validierung
    if (title) {
      const titleError = validators.maxLength(title, 200, 'Titel');
      if (titleError) return res.status(400).json({ error: titleError });
    }
    if (priority) {
      const prioError = validators.enum(priority, ['low', 'medium', 'high'], 'Priorität');
      if (prioError) return res.status(400).json({ error: prioError });
    }
    if (startDate) {
      const startDateError = validators.date(startDate, 'Startdatum');
      if (startDateError) return res.status(400).json({ error: startDateError });
    }
    if (dueDate) {
      const dateError = validators.date(dueDate, 'Fälligkeitsdatum');
      if (dateError) return res.status(400).json({ error: dateError });
    }

    // Änderungen tracken für Historie
    const changes = [];
    if (title !== undefined && title !== existing.title) {
      changes.push({ field: 'title', old: existing.title, new: title });
    }
    if (description !== undefined && description !== existing.description) {
      changes.push({ field: 'description', old: existing.description, new: description });
    }
    if (priority !== undefined && priority !== existing.priority) {
      changes.push({ field: 'priority', old: existing.priority, new: priority });
    }
    if (columnId !== undefined && columnId !== existing.column_id) {
      const oldColumn = db.prepare('SELECT name FROM columns WHERE id = ?').get(existing.column_id);
      const newColumn = db.prepare('SELECT name FROM columns WHERE id = ?').get(columnId);
      changes.push({ field: 'column', old: oldColumn?.name, new: newColumn?.name });
    }
    if (startDate !== undefined && startDate !== existing.start_date) {
      changes.push({ field: 'start_date', old: existing.start_date, new: startDate });
    }
    if (dueDate !== undefined && dueDate !== existing.due_date) {
      changes.push({ field: 'due_date', old: existing.due_date, new: dueDate });
    }
    if (timeEstimateMin !== undefined && timeEstimateMin !== existing.time_estimate_min) {
      changes.push({ field: 'time_estimate', old: String(existing.time_estimate_min), new: String(timeEstimateMin) });
    }
    if (dependsOn !== undefined && dependsOn !== existing.depends_on) {
      changes.push({ field: 'depends_on', old: String(existing.depends_on), new: String(dependsOn) });
    }

    // Aufgabe aktualisieren (ohne assigned_to)
    db.prepare(`
      UPDATE tasks SET
        title = COALESCE(?, title),
        description = ?,
        priority = COALESCE(?, priority),
        column_id = ?,
        start_date = ?,
        due_date = ?,
        time_estimate_min = ?,
        depends_on = ?,
        updated_at = CURRENT_TIMESTAMP
      WHERE id = ?
    `).run(
      title || null,
      description !== undefined ? description : existing.description,
      priority || null,
      columnId !== undefined ? columnId : existing.column_id,
      startDate !== undefined ? startDate : existing.start_date,
      dueDate !== undefined ? dueDate : existing.due_date,
      timeEstimateMin !== undefined ? timeEstimateMin : existing.time_estimate_min,
      dependsOn !== undefined ? dependsOn : existing.depends_on,
      taskId
    );

    // Mitarbeiter aktualisieren (Mehrfachzuweisung)
    if (assignees !== undefined && Array.isArray(assignees)) {
      // Alte Zuweisungen entfernen
      db.prepare('DELETE FROM task_assignees WHERE task_id = ?').run(taskId);
      // Neue Zuweisungen hinzufügen
      const insertAssignee = db.prepare('INSERT INTO task_assignees (task_id, user_id) VALUES (?, ?)');
      assignees.forEach(userId => {
        try {
          insertAssignee.run(taskId, userId);
        } catch (e) {
          // User existiert nicht oder bereits zugewiesen
        }
      });
      changes.push({ field: 'assignees', old: 'changed', new: 'changed' });
    } else if (assignedTo !== undefined) {
      // Rückwärtskompatibilität: einzelne Zuweisung
      db.prepare('DELETE FROM task_assignees WHERE task_id = ?').run(taskId);
      if (assignedTo) {
        try {
          db.prepare('INSERT INTO task_assignees (task_id, user_id) VALUES (?, ?)').run(taskId, assignedTo);
        } catch (e) {
          // Ignorieren
        }
      }
      changes.push({ field: 'assignees', old: 'changed', new: 'changed' });
    }

    // Labels aktualisieren
    if (labels !== undefined && Array.isArray(labels)) {
      // Alte Labels entfernen
      db.prepare('DELETE FROM task_labels WHERE task_id = ?').run(taskId);
      // Neue Labels zuweisen
      const insertLabel = db.prepare('INSERT INTO task_labels (task_id, label_id) VALUES (?, ?)');
      labels.forEach(labelId => {
        try {
          insertLabel.run(taskId, labelId);
        } catch (e) {
          // Label existiert nicht
        }
      });
      changes.push({ field: 'labels', old: 'changed', new: 'changed' });
    }

    // Historie-Einträge
    changes.forEach(change => {
      addHistory(db, taskId, req.user.id, 'updated', change.field, change.old, change.new);
    });

    const task = getFullTask(db, taskId);

    logger.info(`Aufgabe aktualisiert: ${task.title} (ID: ${taskId})`);

    // WebSocket
    const io = req.app.get('io');
    io.to(`project:${existing.project_id}`).emit('task:updated', task);

    // Benachrichtigungen für Änderungen senden
    const taskTitle = title || existing.title;

    // Zuweisung geändert - neue Mitarbeiter benachrichtigen
    if (assignees !== undefined && Array.isArray(assignees)) {
      // Alte Mitarbeiter ermitteln
      const oldAssignees = db.prepare('SELECT user_id FROM task_assignees WHERE task_id = ?').all(taskId);
      const oldAssigneeIds = oldAssignees.map(a => a.user_id);

      // Neue Mitarbeiter (die vorher nicht zugewiesen waren)
      const newAssigneeIds = assignees.filter(id => !oldAssigneeIds.includes(id));
      newAssigneeIds.forEach(assigneeId => {
        if (assigneeId !== req.user.id) {
          notificationService.create(assigneeId, 'task:assigned', {
            taskId: parseInt(taskId),
            taskTitle: taskTitle,
            projectId: existing.project_id,
            actorId: req.user.id,
            actorName: req.user.display_name || req.user.username
          }, io);
        }
      });

      // Entfernte Mitarbeiter
      const removedAssigneeIds = oldAssigneeIds.filter(id => !assignees.includes(id));
      removedAssigneeIds.forEach(assigneeId => {
        if (assigneeId !== req.user.id) {
          notificationService.create(assigneeId, 'task:unassigned', {
            taskId: parseInt(taskId),
            taskTitle: taskTitle,
            projectId: existing.project_id,
            actorId: req.user.id,
            actorName: req.user.display_name || req.user.username
          }, io);
        }
      });
    }

    // Priorität auf hoch gesetzt
    if (priority === 'high' && existing.priority !== 'high') {
      // Alle Assignees benachrichtigen
      const currentAssignees = db.prepare('SELECT user_id FROM task_assignees WHERE task_id = ?').all(taskId);
      currentAssignees.forEach(a => {
        if (a.user_id !== req.user.id) {
          notificationService.create(a.user_id, 'task:priority_up', {
            taskId: parseInt(taskId),
            taskTitle: taskTitle,
            projectId: existing.project_id,
            actorId: req.user.id,
            actorName: req.user.display_name || req.user.username
          }, io);
        }
      });
    }

    // Fälligkeitsdatum geändert
    if (dueDate !== undefined && dueDate !== existing.due_date) {
      const currentAssignees = db.prepare('SELECT user_id FROM task_assignees WHERE task_id = ?').all(taskId);
      currentAssignees.forEach(a => {
        if (a.user_id !== req.user.id) {
          notificationService.create(a.user_id, 'task:due_changed', {
            taskId: parseInt(taskId),
            taskTitle: taskTitle,
            projectId: existing.project_id,
            actorId: req.user.id,
            actorName: req.user.display_name || req.user.username
          }, io);
        }
      });
    }

    res.json(task);
  } catch (error) {
    logger.error('Fehler beim Aktualisieren der Aufgabe:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * PUT /api/tasks/:id/move
 * Aufgabe verschieben (Spalte/Position)
 */
router.put('/:id/move', (req, res) => {
  try {
    const taskId = req.params.id;
    const { columnId, position } = req.body;

    const db = getDb();

    const task = db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId);
    if (!task) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    const oldColumnId = task.column_id;
    const oldPosition = task.position;
    const newColumnId = columnId || oldColumnId;
    const newPosition = position !== undefined ? position : oldPosition;

    // Spaltenname für Historie
    const oldColumn = db.prepare('SELECT name FROM columns WHERE id = ?').get(oldColumnId);
    const newColumn = db.prepare('SELECT name FROM columns WHERE id = ?').get(newColumnId);

    if (oldColumnId !== newColumnId) {
      // In andere Spalte verschoben
      // Positionen in alter Spalte anpassen
      db.prepare(`
        UPDATE tasks SET position = position - 1
        WHERE column_id = ? AND position > ?
      `).run(oldColumnId, oldPosition);

      // Positionen in neuer Spalte anpassen
      db.prepare(`
        UPDATE tasks SET position = position + 1
        WHERE column_id = ? AND position >= ?
      `).run(newColumnId, newPosition);

      // Task verschieben
      db.prepare(`
        UPDATE tasks SET column_id = ?, position = ?, updated_at = CURRENT_TIMESTAMP
        WHERE id = ?
      `).run(newColumnId, newPosition, taskId);

      addHistory(db, taskId, req.user.id, 'moved', 'column', oldColumn?.name, newColumn?.name);
    } else if (oldPosition !== newPosition) {
      // Innerhalb der Spalte verschoben
      if (newPosition > oldPosition) {
        db.prepare(`
          UPDATE tasks SET position = position - 1
          WHERE column_id = ? AND position > ? AND position <= ?
        `).run(newColumnId, oldPosition, newPosition);
      } else {
        db.prepare(`
          UPDATE tasks SET position = position + 1
          WHERE column_id = ? AND position >= ? AND position < ?
        `).run(newColumnId, newPosition, oldPosition);
      }

      db.prepare(`
        UPDATE tasks SET position = ?, updated_at = CURRENT_TIMESTAMP
        WHERE id = ?
      `).run(newPosition, taskId);
    }

    const updatedTask = getFullTask(db, taskId);

    logger.info(`Aufgabe verschoben: ${task.title} -> ${newColumn?.name || 'Position ' + newPosition}`);

    // WebSocket
    const io = req.app.get('io');
    io.to(`project:${task.project_id}`).emit('task:moved', {
      task: updatedTask,
      oldColumnId,
      newColumnId,
      oldPosition,
      newPosition
    });

    // Benachrichtigung wenn in Erledigt-Spalte verschoben
    if (oldColumnId !== newColumnId) {
      const newColumnFull = db.prepare('SELECT filter_category FROM columns WHERE id = ?').get(newColumnId);
      const oldColumnFull = db.prepare('SELECT filter_category FROM columns WHERE id = ?').get(oldColumnId);

      // Prüfen ob in Erledigt-Spalte verschoben (und vorher nicht dort war)
      if (newColumnFull?.filter_category === 'completed' && oldColumnFull?.filter_category !== 'completed') {
        // Alle Assignees benachrichtigen
        const assignees = db.prepare('SELECT user_id FROM task_assignees WHERE task_id = ?').all(taskId);
        assignees.forEach(a => {
          if (a.user_id !== req.user.id) {
            notificationService.create(a.user_id, 'task:completed', {
              taskId: parseInt(taskId),
              taskTitle: task.title,
              projectId: task.project_id,
              actorId: req.user.id,
              actorName: req.user.display_name || req.user.username
            }, io);
          }
        });
      }
    }

    res.json(updatedTask);
  } catch (error) {
    logger.error('Fehler beim Verschieben der Aufgabe:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * POST /api/tasks/:id/duplicate
 * Aufgabe duplizieren
 */
router.post('/:id/duplicate', (req, res) => {
  try {
    const taskId = req.params.id;
    const db = getDb();

    const task = db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId);
    if (!task) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    // Höchste Position ermitteln
    const maxPos = db.prepare(
      'SELECT COALESCE(MAX(position), -1) as max FROM tasks WHERE column_id = ?'
    ).get(task.column_id).max;

    // Aufgabe duplizieren
    const result = db.prepare(`
      INSERT INTO tasks (
        project_id, column_id, title, description, priority,
        due_date, assigned_to, time_estimate_min, position, created_by
      )
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(
      task.project_id, task.column_id, task.title + ' (Kopie)', task.description,
      task.priority, task.due_date, task.assigned_to, task.time_estimate_min,
      maxPos + 1, req.user.id
    );

    const newTaskId = result.lastInsertRowid;

    // Labels kopieren
    const taskLabels = db.prepare('SELECT label_id FROM task_labels WHERE task_id = ?').all(taskId);
    const insertLabel = db.prepare('INSERT INTO task_labels (task_id, label_id) VALUES (?, ?)');
    taskLabels.forEach(tl => insertLabel.run(newTaskId, tl.label_id));

    // Mehrfachzuweisungen kopieren
    const assignees = db.prepare('SELECT user_id FROM task_assignees WHERE task_id = ?').all(taskId);
    const insertAssignee = db.prepare('INSERT INTO task_assignees (task_id, user_id) VALUES (?, ?)');
    assignees.forEach(a => insertAssignee.run(newTaskId, a.user_id));

    // Subtasks inkl. Abhak-Status kopieren
    const subtasks = db.prepare('SELECT * FROM subtasks WHERE task_id = ? ORDER BY position').all(taskId);
    const insertSubtask = db.prepare('INSERT INTO subtasks (task_id, title, completed, position) VALUES (?, ?, ?, ?)');
    subtasks.forEach((st, idx) => insertSubtask.run(newTaskId, st.title, st.completed ? 1 : 0, idx));

    addHistory(db, newTaskId, req.user.id, 'created', null, null, `Kopie von #${taskId}`);

    const newTask = getFullTask(db, newTaskId);

    logger.info(`Aufgabe dupliziert: ${task.title} -> ${newTask.title}`);

    // WebSocket
    const io = req.app.get('io');
    io.to(`project:${task.project_id}`).emit('task:created', newTask);

    res.status(201).json(newTask);
  } catch (error) {
    logger.error('Fehler beim Duplizieren:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * PUT /api/tasks/:id/archive
 * Aufgabe archivieren
 */
router.put('/:id/archive', (req, res) => {
  try {
    const taskId = req.params.id;
    const { archived, columnId } = req.body;

    const db = getDb();

    const task = db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId);
    if (!task) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    // Bei Wiederherstellung: Prüfen ob Spalte vorhanden
    if (!archived && !task.column_id) {
      // Task hat keine Spalte (wurde mit gelöschter Spalte archiviert)
      if (!columnId) {
        return res.status(400).json({
          error: 'Spalte erforderlich',
          requiresColumn: true
        });
      }
      // Prüfen ob Spalte existiert und zum Projekt gehört
      const column = db.prepare('SELECT * FROM columns WHERE id = ? AND project_id = ?')
        .get(columnId, task.project_id);
      if (!column) {
        return res.status(400).json({ error: 'Ungültige Spalte' });
      }
      // Wiederherstellen mit neuer Spalte
      db.prepare('UPDATE tasks SET archived = 0, column_id = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
        .run(columnId, taskId);
    } else {
      // Normales Archivieren/Wiederherstellen
      db.prepare('UPDATE tasks SET archived = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
        .run(archived ? 1 : 0, taskId);
    }

    addHistory(db, taskId, req.user.id, archived ? 'archived' : 'restored');

    logger.info(`Aufgabe ${archived ? 'archiviert' : 'wiederhergestellt'}: ${task.title}`);

    // WebSocket - vollständigen Task mitschicken, damit Clients ihn wieder einpflegen können
    const io = req.app.get('io');
    const updatedTask = getFullTask(db, taskId);
    io.to(`project:${task.project_id}`).emit('task:archived', {
      id: taskId,
      archived: !!archived,
      columnId: updatedTask?.columnId,
      task: updatedTask,
      userId: req.user.id
    });

    res.json({ message: archived ? 'Aufgabe archiviert' : 'Aufgabe wiederhergestellt', task: updatedTask });
  } catch (error) {
    logger.error('Fehler beim Archivieren:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

/**
 * DELETE /api/tasks/:id
 * Aufgabe löschen
 */
router.delete('/:id', (req, res) => {
  try {
    const taskId = req.params.id;
    const db = getDb();

    const task = db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId);
    if (!task) {
      return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
    }

    db.prepare('DELETE FROM tasks WHERE id = ?').run(taskId);

    // Positionen neu nummerieren
    const remainingTasks = db.prepare(
      'SELECT id FROM tasks WHERE column_id = ? ORDER BY position'
    ).all(task.column_id);

    remainingTasks.forEach((t, idx) => {
      db.prepare('UPDATE tasks SET position = ? WHERE id = ?').run(idx, t.id);
    });

    logger.info(`Aufgabe gelöscht: ${task.title} (ID: ${taskId})`);

    // WebSocket
    const io = req.app.get('io');
    io.to(`project:${task.project_id}`).emit('task:deleted', {
      id: taskId,
      columnId: task.column_id
    });

    res.json({ message: 'Aufgabe gelöscht' });
  } catch (error) {
    logger.error('Fehler beim Löschen:', { error: error.message });
    res.status(500).json({ error: 'Interner Serverfehler' });
  }
});

module.exports = router;
