/**
 * TASKMATE - Notification Service
 * ================================
 * Zentrale Logik für das Benachrichtigungssystem
 */

const { getDb } = require('../database');
const logger = require('../utils/logger');

/**
 * Benachrichtigungstypen mit Titeln und Icons
 */
const NOTIFICATION_TYPES = {
  'task:assigned': {
    title: (data) => 'Neue Aufgabe zugewiesen',
    message: (data) => `Du wurdest der Aufgabe "${data.taskTitle}" zugewiesen`
  },
  'task:unassigned': {
    title: (data) => 'Zuweisung entfernt',
    message: (data) => `Du wurdest von der Aufgabe "${data.taskTitle}" entfernt`
  },
  'task:due_soon': {
    title: (data) => 'Aufgabe bald fällig',
    message: (data) => `Die Aufgabe "${data.taskTitle}" ist morgen fällig`
  },
  'task:completed': {
    title: (data) => 'Aufgabe erledigt',
    message: (data) => `Die Aufgabe "${data.taskTitle}" wurde erledigt`
  },
  'task:due_changed': {
    title: (data) => 'Fälligkeitsdatum geändert',
    message: (data) => `Das Fälligkeitsdatum von "${data.taskTitle}" wurde geändert`
  },
  'task:priority_up': {
    title: (data) => 'Priorität erhöht',
    message: (data) => `Die Priorität von "${data.taskTitle}" wurde auf "Hoch" gesetzt`
  },
  'comment:created': {
    title: (data) => 'Neuer Kommentar',
    message: (data) => `${data.actorName} hat "${data.taskTitle}" kommentiert`
  },
  'comment:mention': {
    title: (data) => 'Du wurdest erwähnt',
    message: (data) => `${data.actorName} hat dich in "${data.taskTitle}" erwähnt`
  },
  'approval:pending': {
    title: (data) => 'Genehmigung erforderlich',
    message: (data) => `Neue Genehmigung: "${data.proposalTitle}"`
  },
  'reminder:due': {
    title: (data) => 'Erinnerung',
    message: (data) => `${data.reminderTitle} - ${data.daysAdvance === '0' ? 'Heute' : `in ${data.daysAdvance} Tag${data.daysAdvance > 1 ? 'en' : ''}`}`
  },
  'approval:granted': {
    title: (data) => 'Genehmigung erteilt',
    message: (data) => `"${data.proposalTitle}" wurde genehmigt`
  },
  'approval:rejected': {
    title: (data) => 'Genehmigung abgelehnt',
    message: (data) => `"${data.proposalTitle}" wurde abgelehnt`
  },
  'knowledge:new_entry': {
    title: (data) => 'Neuer Wissenseintrag',
    message: (data) => `Neuer Eintrag: "${data.entryTitle}" in ${data.categoryName}`
  }
};

const notificationService = {
  /**
   * Benachrichtigung erstellen und per WebSocket senden
   * @param {number} userId - Empfänger
   * @param {string} type - Benachrichtigungstyp
   * @param {object} data - Zusätzliche Daten
   * @param {object} io - Socket.io Instanz
   * @param {boolean} persistent - Ob die Benachrichtigung persistent ist
   */
  create(userId, type, data, io, persistent = false) {
    try {
      const db = getDb();
      const typeConfig = NOTIFICATION_TYPES[type];

      if (!typeConfig) {
        logger.warn(`Unbekannter Benachrichtigungstyp: ${type}`);
        return null;
      }

      const title = typeConfig.title(data);
      const message = typeConfig.message(data);

      const result = db.prepare(`
        INSERT INTO notifications (user_id, type, title, message, task_id, project_id, proposal_id, actor_id, is_persistent, data)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `).run(
        userId,
        type,
        title,
        message,
        data.taskId || null,
        data.projectId || null,
        data.proposalId || null,
        data.actorId || null,
        persistent ? 1 : 0,
        JSON.stringify(data) // Zusätzliche Daten als JSON speichern
      );

      const notification = db.prepare(`
        SELECT n.*, u.display_name as actor_name, u.color as actor_color
        FROM notifications n
        LEFT JOIN users u ON n.actor_id = u.id
        WHERE n.id = ?
      `).get(result.lastInsertRowid);

      // WebSocket-Event senden
      if (io) {
        io.to(`user:${userId}`).emit('notification:new', {
          notification: this.formatNotification(notification)
        });

        // Auch aktualisierte Zählung senden
        const count = this.getUnreadCount(userId);
        io.to(`user:${userId}`).emit('notification:count', { count });
      }

      logger.info(`Benachrichtigung erstellt: ${type} für User ${userId}`);
      return notification;
    } catch (error) {
      logger.error('Fehler beim Erstellen der Benachrichtigung:', error);
      return null;
    }
  },

  /**
   * Alle Benachrichtigungen für einen User abrufen
   */
  getForUser(userId, limit = 50) {
    const db = getDb();
    const notifications = db.prepare(`
      SELECT n.*, u.display_name as actor_name, u.color as actor_color
      FROM notifications n
      LEFT JOIN users u ON n.actor_id = u.id
      WHERE n.user_id = ?
      ORDER BY n.is_persistent DESC, n.created_at DESC
      LIMIT ?
    `).all(userId, limit);

    return notifications.map(n => this.formatNotification(n));
  },

  /**
   * Ungelesene Anzahl ermitteln
   */
  getUnreadCount(userId) {
    const db = getDb();
    const result = db.prepare(`
      SELECT COUNT(*) as count
      FROM notifications
      WHERE user_id = ? AND is_read = 0
    `).get(userId);
    return result.count;
  },

  /**
   * Als gelesen markieren
   */
  markAsRead(notificationId, userId) {
    const db = getDb();
    const result = db.prepare(`
      UPDATE notifications
      SET is_read = 1
      WHERE id = ? AND user_id = ?
    `).run(notificationId, userId);
    return result.changes > 0;
  },

  /**
   * Alle als gelesen markieren
   */
  markAllAsRead(userId) {
    const db = getDb();
    const result = db.prepare(`
      UPDATE notifications
      SET is_read = 1
      WHERE user_id = ? AND is_read = 0
    `).run(userId);
    return result.changes;
  },

  /**
   * Benachrichtigung löschen (nur nicht-persistente)
   */
  delete(notificationId, userId) {
    const db = getDb();
    const result = db.prepare(`
      DELETE FROM notifications
      WHERE id = ? AND user_id = ? AND is_persistent = 0
    `).run(notificationId, userId);
    return result.changes > 0;
  },

  /**
   * Persistente Benachrichtigungen auflösen (z.B. bei Genehmigung)
   */
  resolvePersistent(proposalId) {
    const db = getDb();
    const result = db.prepare(`
      DELETE FROM notifications
      WHERE proposal_id = ? AND is_persistent = 1
    `).run(proposalId);
    logger.info(`${result.changes} persistente Benachrichtigungen für Proposal ${proposalId} aufgelöst`);
    return result.changes;
  },

  /**
   * Fälligkeits-Check für Aufgaben (1 Tag vorher)
   */
  checkDueTasks(io) {
    try {
      const db = getDb();

      // Morgen berechnen
      const tomorrow = new Date();
      tomorrow.setDate(tomorrow.getDate() + 1);
      const tomorrowStr = tomorrow.toISOString().split('T')[0];

      // Aufgaben die morgen fällig sind
      const tasks = db.prepare(`
        SELECT t.id, t.title, t.project_id, ta.user_id as assignee_id
        FROM tasks t
        JOIN task_assignees ta ON t.id = ta.task_id
        LEFT JOIN columns c ON t.column_id = c.id
        WHERE t.due_date = ?
        AND t.archived = 0
        AND c.filter_category != 'completed'
        AND NOT EXISTS (
          SELECT 1 FROM notifications n
          WHERE n.task_id = t.id
          AND n.user_id = ta.user_id
          AND n.type = 'task:due_soon'
          AND DATE(n.created_at) = DATE('now')
        )
      `).all(tomorrowStr);

      let count = 0;
      tasks.forEach(task => {
        this.create(task.assignee_id, 'task:due_soon', {
          taskId: task.id,
          taskTitle: task.title,
          projectId: task.project_id
        }, io);
        count++;
      });

      if (count > 0) {
        logger.info(`${count} Fälligkeits-Benachrichtigungen erstellt`);
      }

      return count;
    } catch (error) {
      logger.error('Fehler beim Fälligkeits-Check:', error);
      return 0;
    }
  },

  /**
   * Benachrichtigung formatieren für Frontend
   */
  formatNotification(notification) {
    // Parse zusätzliche Daten wenn vorhanden
    let additionalData = {};
    if (notification.data) {
      try {
        additionalData = JSON.parse(notification.data);
      } catch (e) {
        // Ignore parse errors
      }
    }

    return {
      id: notification.id,
      userId: notification.user_id,
      type: notification.type,
      title: notification.title,
      message: notification.message,
      taskId: notification.task_id,
      projectId: notification.project_id,
      proposalId: notification.proposal_id,
      actorId: notification.actor_id,
      actorName: notification.actor_name,
      actorColor: notification.actor_color,
      isRead: notification.is_read === 1,
      isPersistent: notification.is_persistent === 1,
      createdAt: notification.created_at,
      // Zusätzliche Daten für Knowledge-Einträge
      entryId: additionalData.entryId || null,
      categoryId: additionalData.categoryId || null
    };
  },

  /**
   * Benachrichtigung an mehrere User senden
   */
  createForMultiple(userIds, type, data, io, persistent = false) {
    const results = [];
    userIds.forEach(userId => {
      const result = this.create(userId, type, data, io, persistent);
      if (result) results.push(result);
    });
    return results;
  },

  /**
   * Reminder-Benachrichtigung erstellen
   */
  createReminderNotification(reminder, daysAdvance, io) {
    return this.create(
      reminder.created_by, 
      'reminder:due', 
      {
        reminderTitle: reminder.title,
        daysAdvance: daysAdvance.toString(),
        projectId: reminder.project_id,
        reminderId: reminder.id
      }, 
      io, 
      false
    );
  }
};

module.exports = notificationService;
