/**
 * TASKMATE - Datenbank
 * ====================
 * SQLite-Datenbank mit better-sqlite3
 */

const Database = require('better-sqlite3');
const path = require('path');
const bcrypt = require('bcryptjs');
const logger = require('./utils/logger');

// Datenbank-Pfad
const DB_PATH = process.env.DB_PATH || path.join(__dirname, 'data', 'taskmate.db');

let db = null;

/**
 * Datenbank initialisieren
 */
async function initialize() {
  try {
    // Datenbank öffnen/erstellen
    db = new Database(DB_PATH);

    // WAL-Modus für bessere Performance
    db.pragma('journal_mode = WAL');
    db.pragma('foreign_keys = ON');

    // Tabellen erstellen
    createTables();

    // Standard-Benutzer erstellen (falls nicht vorhanden)
    await createDefaultUsers();

    logger.info('Datenbank initialisiert');
    return db;
  } catch (error) {
    logger.error('Datenbank-Fehler:', error);
    throw error;
  }
}

/**
 * Tabellen erstellen
 */
function createTables() {
  // Benutzer
  db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT UNIQUE NOT NULL,
      password_hash TEXT NOT NULL,
      display_name TEXT NOT NULL,
      color TEXT NOT NULL DEFAULT '#00D4FF',
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      last_login DATETIME,
      failed_attempts INTEGER DEFAULT 0,
      locked_until DATETIME
    )
  `);

  // Login-Audit
  db.exec(`
    CREATE TABLE IF NOT EXISTS login_audit (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
      ip_address TEXT,
      success INTEGER NOT NULL,
      user_agent TEXT,
      FOREIGN KEY (user_id) REFERENCES users(id)
    )
  `);

  // Projekte
  db.exec(`
    CREATE TABLE IF NOT EXISTS projects (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      description TEXT,
      archived INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      created_by INTEGER,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Spalten
  db.exec(`
    CREATE TABLE IF NOT EXISTS columns (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      position INTEGER NOT NULL,
      color TEXT,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
    )
  `);

  // Labels
  db.exec(`
    CREATE TABLE IF NOT EXISTS labels (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      color TEXT NOT NULL,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
    )
  `);

  // Aufgaben
  db.exec(`
    CREATE TABLE IF NOT EXISTS tasks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      column_id INTEGER,
      title TEXT NOT NULL,
      description TEXT,
      priority TEXT DEFAULT 'medium',
      start_date DATE,
      due_date DATE,
      assigned_to INTEGER,
      time_estimate_min INTEGER,
      depends_on INTEGER,
      position INTEGER NOT NULL,
      archived INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      created_by INTEGER,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      FOREIGN KEY (column_id) REFERENCES columns(id) ON DELETE SET NULL,
      FOREIGN KEY (assigned_to) REFERENCES users(id),
      FOREIGN KEY (depends_on) REFERENCES tasks(id) ON DELETE SET NULL,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Migration: Add start_date column if it doesn't exist
  const columns = db.prepare("PRAGMA table_info(tasks)").all();
  const hasStartDate = columns.some(col => col.name === 'start_date');
  if (!hasStartDate) {
    db.exec('ALTER TABLE tasks ADD COLUMN start_date DATE');
    logger.info('Migration: start_date Spalte zu tasks hinzugefuegt');
  }

  // Migration: Add role and permissions columns to users
  const userColumns = db.prepare("PRAGMA table_info(users)").all();
  const hasRole = userColumns.some(col => col.name === 'role');
  if (!hasRole) {
    db.exec("ALTER TABLE users ADD COLUMN role TEXT DEFAULT 'user'");
    logger.info('Migration: role Spalte zu users hinzugefuegt');
  }
  const hasPermissions = userColumns.some(col => col.name === 'permissions');
  if (!hasPermissions) {
    db.exec("ALTER TABLE users ADD COLUMN permissions TEXT DEFAULT '[]'");
    logger.info('Migration: permissions Spalte zu users hinzugefuegt');
  }

  // Migration: Add email column to users
  const hasEmail = userColumns.some(col => col.name === 'email');
  if (!hasEmail) {
    db.exec("ALTER TABLE users ADD COLUMN email TEXT");
    logger.info('Migration: email Spalte zu users hinzugefuegt');
  }

  // Migration: Add repositories_base_path column to users
  const hasRepoBasePath = userColumns.some(col => col.name === 'repositories_base_path');
  if (!hasRepoBasePath) {
    db.exec("ALTER TABLE users ADD COLUMN repositories_base_path TEXT");
    logger.info('Migration: repositories_base_path Spalte zu users hinzugefuegt');
  }

  // Migration: Add custom_initials column to users
  const hasCustomInitials = userColumns.some(col => col.name === 'custom_initials');
  if (!hasCustomInitials) {
    db.exec("ALTER TABLE users ADD COLUMN custom_initials TEXT");
    logger.info('Migration: custom_initials Spalte zu users hinzugefuegt');
  }

  // Migration: Add initials column and prepare email
  const hasInitials = userColumns.some(col => col.name === 'initials');
  if (!hasInitials && userColumns.some(col => col.name === 'username')) {
    logger.info('Migration: Füge initials Spalte hinzu und bereite E-Mail vor');
    
    // Zuerst Daten vorbereiten
    const users = db.prepare('SELECT id, username, email, custom_initials FROM users').all();
    for (const user of users) {
      // Stelle sicher dass jeder Benutzer eine E-Mail hat
      if (!user.email || user.email === '') {
        if (user.username === 'admin') {
          // Admin bekommt eine spezielle E-Mail
          db.prepare('UPDATE users SET email = ? WHERE id = ?').run('admin@taskmate.local', user.id);
        } else if (user.username.includes('@')) {
          // Username enthält bereits E-Mail (wie bei bestehenden Benutzern)
          db.prepare('UPDATE users SET email = ? WHERE id = ?').run(user.username, user.id);
        }
      }
      
      // Initialen setzen (aus custom_initials oder generieren)
      if (!user.custom_initials || user.custom_initials === '') {
        let initials = 'XX';
        if (user.username === 'admin') {
          initials = 'AD';
        } else if (user.email || user.username.includes('@')) {
          // Generiere Initialen aus E-Mail
          const emailPart = (user.email || user.username).split('@')[0];
          if (emailPart.includes('_')) {
            const parts = emailPart.split('_');
            initials = (parts[0][0] + parts[1][0]).toUpperCase();
          } else if (emailPart.includes('.')) {
            const parts = emailPart.split('.');
            initials = (parts[0][0] + parts[1][0]).toUpperCase();
          } else {
            initials = emailPart.substring(0, 2).toUpperCase();
          }
        }
        db.prepare('UPDATE users SET custom_initials = ? WHERE id = ?').run(initials, user.id);
      }
    }
    
    // Neue initials Spalte hinzufügen
    db.exec("ALTER TABLE users ADD COLUMN initials TEXT");
    
    // Daten von custom_initials nach initials kopieren
    db.exec("UPDATE users SET initials = custom_initials");
    
    logger.info('Migration: initials Spalte hinzugefügt und E-Mail-Daten vorbereitet');
  }

  // Proposals (Vorschlaege)
  db.exec(`
    CREATE TABLE IF NOT EXISTS proposals (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      title TEXT NOT NULL,
      description TEXT,
      created_by INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      approved INTEGER DEFAULT 0,
      approved_by INTEGER,
      approved_at DATETIME,
      FOREIGN KEY (created_by) REFERENCES users(id),
      FOREIGN KEY (approved_by) REFERENCES users(id)
    )
  `);

  // Proposal Votes
  db.exec(`
    CREATE TABLE IF NOT EXISTS proposal_votes (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      proposal_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (proposal_id) REFERENCES proposals(id) ON DELETE CASCADE,
      FOREIGN KEY (user_id) REFERENCES users(id)
    )
  `);

  // Unique constraint for proposal votes (one vote per user per proposal)
  db.exec(`
    CREATE UNIQUE INDEX IF NOT EXISTS idx_proposal_votes_unique
    ON proposal_votes(proposal_id, user_id)
  `);

  // Index for proposal votes
  db.exec(`
    CREATE INDEX IF NOT EXISTS idx_proposal_votes_proposal
    ON proposal_votes(proposal_id)
  `);

  // Migration: Add archived, task_id, and project_id columns to proposals
  const proposalColumns = db.prepare("PRAGMA table_info(proposals)").all();
  const hasProposalArchived = proposalColumns.some(col => col.name === 'archived');
  if (!hasProposalArchived) {
    db.exec('ALTER TABLE proposals ADD COLUMN archived INTEGER DEFAULT 0');
    logger.info('Migration: archived Spalte zu proposals hinzugefuegt');
  }
  const hasProposalTaskId = proposalColumns.some(col => col.name === 'task_id');
  if (!hasProposalTaskId) {
    db.exec('ALTER TABLE proposals ADD COLUMN task_id INTEGER REFERENCES tasks(id) ON DELETE SET NULL');
    logger.info('Migration: task_id Spalte zu proposals hinzugefuegt');
  }
  const hasProposalProjectId = proposalColumns.some(col => col.name === 'project_id');
  if (!hasProposalProjectId) {
    db.exec('ALTER TABLE proposals ADD COLUMN project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE');
    logger.info('Migration: project_id Spalte zu proposals hinzugefuegt');
  }

  // Migration: Add filter_category column to columns
  const columnColumns = db.prepare("PRAGMA table_info(columns)").all();
  const hasFilterCategory = columnColumns.some(col => col.name === 'filter_category');
  if (!hasFilterCategory) {
    db.exec("ALTER TABLE columns ADD COLUMN filter_category TEXT DEFAULT 'in_progress'");
    logger.info('Migration: filter_category Spalte zu columns hinzugefuegt');

    // Set default values for existing columns based on position
    const projects = db.prepare('SELECT id FROM projects').all();
    for (const project of projects) {
      const cols = db.prepare('SELECT id, position FROM columns WHERE project_id = ? ORDER BY position').all(project.id);
      if (cols.length > 0) {
        // First column = open
        db.prepare("UPDATE columns SET filter_category = 'open' WHERE id = ?").run(cols[0].id);
        // Last column = completed
        if (cols.length > 1) {
          db.prepare("UPDATE columns SET filter_category = 'completed' WHERE id = ?").run(cols[cols.length - 1].id);
        }
      }
    }
    logger.info('Migration: Standard-Filterkategorien fuer bestehende Spalten gesetzt');
  }

  // Task-Labels (Verknüpfung)
  db.exec(`
    CREATE TABLE IF NOT EXISTS task_labels (
      task_id INTEGER NOT NULL,
      label_id INTEGER NOT NULL,
      PRIMARY KEY (task_id, label_id),
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE
    )
  `);

  // Task-Assignees (Mehrfachzuweisung von Mitarbeitern)
  db.exec(`
    CREATE TABLE IF NOT EXISTS task_assignees (
      task_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      PRIMARY KEY (task_id, user_id),
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    )
  `);

  // Unteraufgaben
  db.exec(`
    CREATE TABLE IF NOT EXISTS subtasks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER NOT NULL,
      title TEXT NOT NULL,
      completed INTEGER DEFAULT 0,
      position INTEGER NOT NULL,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
    )
  `);

  // Kommentare
  db.exec(`
    CREATE TABLE IF NOT EXISTS comments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      content TEXT NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (user_id) REFERENCES users(id)
    )
  `);

  // Anhänge
  db.exec(`
    CREATE TABLE IF NOT EXISTS attachments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER NOT NULL,
      filename TEXT NOT NULL,
      original_name TEXT NOT NULL,
      mime_type TEXT NOT NULL,
      size_bytes INTEGER NOT NULL,
      uploaded_by INTEGER,
      uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (uploaded_by) REFERENCES users(id)
    )
  `);

  // Links
  db.exec(`
    CREATE TABLE IF NOT EXISTS links (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER NOT NULL,
      title TEXT,
      url TEXT NOT NULL,
      created_by INTEGER,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Aufgaben-Vorlagen
  db.exec(`
    CREATE TABLE IF NOT EXISTS task_templates (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      title_template TEXT,
      description TEXT,
      priority TEXT,
      labels TEXT,
      subtasks TEXT,
      time_estimate_min INTEGER,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
    )
  `);

  // Historie
  db.exec(`
    CREATE TABLE IF NOT EXISTS history (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      action TEXT NOT NULL,
      field_changed TEXT,
      old_value TEXT,
      new_value TEXT,
      timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (user_id) REFERENCES users(id)
    )
  `);

  // Einstellungen
  db.exec(`
    CREATE TABLE IF NOT EXISTS settings (
      key TEXT PRIMARY KEY,
      value TEXT
    )
  `);

  // Refresh Tokens für sichere Token-Rotation
  db.exec(`
    CREATE TABLE IF NOT EXISTS refresh_tokens (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      token TEXT NOT NULL UNIQUE,
      expires_at DATETIME NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      last_used DATETIME,
      user_agent TEXT,
      ip_address TEXT,
      FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    )
  `);

  // Index für Token-Lookup
  db.exec(`CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON refresh_tokens(token)`);
  db.exec(`CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires ON refresh_tokens(expires_at)`);

  // Anwendungen (Git-Repositories pro Projekt)
  db.exec(`
    CREATE TABLE IF NOT EXISTS applications (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL UNIQUE,
      local_path TEXT NOT NULL,
      gitea_repo_url TEXT,
      gitea_repo_owner TEXT,
      gitea_repo_name TEXT,
      default_branch TEXT DEFAULT 'main',
      last_sync DATETIME,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      created_by INTEGER,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Benachrichtigungen (Inbox)
  db.exec(`
    CREATE TABLE IF NOT EXISTS notifications (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      type TEXT NOT NULL,
      title TEXT NOT NULL,
      message TEXT,
      task_id INTEGER,
      project_id INTEGER,
      proposal_id INTEGER,
      actor_id INTEGER,
      is_read INTEGER DEFAULT 0,
      is_persistent INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
      FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      FOREIGN KEY (proposal_id) REFERENCES proposals(id) ON DELETE CASCADE,
      FOREIGN KEY (actor_id) REFERENCES users(id) ON DELETE SET NULL
    )
  `);

  // Erinnerungen
  db.exec(`
    CREATE TABLE IF NOT EXISTS reminders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      title TEXT NOT NULL,
      description TEXT,
      reminder_date DATE NOT NULL,
      reminder_time TIME DEFAULT '09:00',
      color TEXT DEFAULT '#F59E0B',
      advance_days TEXT DEFAULT '1',
      repeat_type TEXT DEFAULT 'none',
      repeat_interval INTEGER DEFAULT 1,
      is_active INTEGER DEFAULT 1,
      created_by INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Erinnerungs-Benachrichtigungen (für Tracking welche bereits gesendet wurden)
  db.exec(`
    CREATE TABLE IF NOT EXISTS reminder_notifications (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      reminder_id INTEGER NOT NULL,
      notification_date DATE NOT NULL,
      sent INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (reminder_id) REFERENCES reminders(id) ON DELETE CASCADE,
      UNIQUE(reminder_id, notification_date)
    )
  `);

  // Wissensmanagement - Kategorien
  db.exec(`
    CREATE TABLE IF NOT EXISTS knowledge_categories (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      description TEXT,
      color TEXT DEFAULT '#3B82F6',
      icon TEXT,
      position INTEGER NOT NULL DEFAULT 0,
      created_by INTEGER,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Wissensmanagement - Einträge
  db.exec(`
    CREATE TABLE IF NOT EXISTS knowledge_entries (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      category_id INTEGER NOT NULL,
      title TEXT NOT NULL,
      url TEXT,
      notes TEXT,
      position INTEGER NOT NULL DEFAULT 0,
      created_by INTEGER,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (category_id) REFERENCES knowledge_categories(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Wissensmanagement - FTS5 Volltextsuche
  try {
    db.exec(`
      CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_fts USING fts5(
        title, notes, content=knowledge_entries, content_rowid=id
      )
    `);

    // Trigger: INSERT synchronisieren
    db.exec(`
      CREATE TRIGGER IF NOT EXISTS knowledge_fts_insert AFTER INSERT ON knowledge_entries BEGIN
        INSERT INTO knowledge_fts(rowid, title, notes) VALUES (NEW.id, NEW.title, NEW.notes);
      END
    `);

    // Trigger: DELETE synchronisieren
    db.exec(`
      CREATE TRIGGER IF NOT EXISTS knowledge_fts_delete AFTER DELETE ON knowledge_entries BEGIN
        INSERT INTO knowledge_fts(knowledge_fts, rowid, title, notes) VALUES('delete', OLD.id, OLD.title, OLD.notes);
      END
    `);

    // Trigger: UPDATE synchronisieren
    db.exec(`
      CREATE TRIGGER IF NOT EXISTS knowledge_fts_update AFTER UPDATE ON knowledge_entries BEGIN
        INSERT INTO knowledge_fts(knowledge_fts, rowid, title, notes) VALUES('delete', OLD.id, OLD.title, OLD.notes);
        INSERT INTO knowledge_fts(rowid, title, notes) VALUES (NEW.id, NEW.title, NEW.notes);
      END
    `);

    // Initiales Befuellen der FTS-Tabelle
    db.exec(`INSERT INTO knowledge_fts(knowledge_fts) VALUES('rebuild')`);
    logger.info('Knowledge FTS5 Volltextindex erstellt/aktualisiert');
  } catch (ftsError) {
    logger.warn('FTS5 konnte nicht erstellt werden (evtl. nicht unterstuetzt):', ftsError.message);
  }

  // Wissensmanagement - Anhänge
  db.exec(`
    CREATE TABLE IF NOT EXISTS knowledge_attachments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      entry_id INTEGER NOT NULL,
      filename TEXT NOT NULL,
      original_name TEXT NOT NULL,
      mime_type TEXT NOT NULL,
      size_bytes INTEGER NOT NULL,
      uploaded_by INTEGER,
      uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (entry_id) REFERENCES knowledge_entries(id) ON DELETE CASCADE,
      FOREIGN KEY (uploaded_by) REFERENCES users(id)
    )
  `);

  // Coding-Verzeichnisse (projektübergreifend)
  db.exec(`
    CREATE TABLE IF NOT EXISTS coding_directories (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      local_path TEXT NOT NULL UNIQUE,
      description TEXT,
      color TEXT DEFAULT '#4F46E5',
      gitea_repo_url TEXT,
      gitea_repo_owner TEXT,
      gitea_repo_name TEXT,
      default_branch TEXT DEFAULT 'main',
      last_sync DATETIME,
      position INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      created_by INTEGER,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Migration: Add claude_instructions column to coding_directories
  const codingDirColumns = db.prepare("PRAGMA table_info(coding_directories)").all();
  const hasClaudeInstructions = codingDirColumns.some(col => col.name === 'claude_instructions');
  if (!hasClaudeInstructions) {
    db.exec('ALTER TABLE coding_directories ADD COLUMN claude_instructions TEXT');
    logger.info('Migration: claude_instructions Spalte zu coding_directories hinzugefuegt');
  }

  // Coding Verbrauchsdaten
  db.exec(`
    CREATE TABLE IF NOT EXISTS coding_usage (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      directory_id INTEGER NOT NULL,
      timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
      cpu_percent REAL,
      memory_mb REAL,
      disk_read_mb REAL,
      disk_write_mb REAL,
      network_recv_mb REAL,
      network_sent_mb REAL,
      process_count INTEGER,
      FOREIGN KEY (directory_id) REFERENCES coding_directories(id) ON DELETE CASCADE
    )
  `);

  // Neues optimiertes Kontakt-Schema
  db.exec(`
    CREATE TABLE IF NOT EXISTS contacts (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      type TEXT NOT NULL CHECK(type IN ('person', 'company')),
      
      -- Gemeinsame Felder
      display_name TEXT NOT NULL,
      status TEXT DEFAULT 'active' CHECK(status IN ('active', 'inactive', 'archived')),
      tags TEXT,
      notes TEXT,
      avatar_url TEXT,
      
      -- Person-spezifische Felder
      salutation TEXT,
      first_name TEXT,
      last_name TEXT,
      position TEXT,
      department TEXT,
      parent_company_id INTEGER,
      
      -- Firma-spezifische Felder
      company_name TEXT,
      company_type TEXT,
      industry TEXT,
      website TEXT,

      -- Meta
      project_id INTEGER NOT NULL,
      created_by INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      
      FOREIGN KEY (parent_company_id) REFERENCES contacts(id) ON DELETE SET NULL,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Kontaktdetails (E-Mails, Telefone, Adressen)
  db.exec(`
    CREATE TABLE IF NOT EXISTS contact_details (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      contact_id INTEGER NOT NULL,
      type TEXT NOT NULL CHECK(type IN ('email', 'phone', 'mobile', 'fax', 'address', 'social')),
      label TEXT DEFAULT 'Arbeit',
      value TEXT NOT NULL,
      is_primary BOOLEAN DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE
    )
  `);

  // Kontakt-Kategorien
  db.exec(`
    CREATE TABLE IF NOT EXISTS contact_categories (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      color TEXT DEFAULT '#6B7280',
      icon TEXT,
      project_id INTEGER,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
    )
  `);

  // Kontakt-Kategorie Zuordnungen
  db.exec(`
    CREATE TABLE IF NOT EXISTS contact_to_categories (
      contact_id INTEGER NOT NULL,
      category_id INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (contact_id, category_id),
      FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE,
      FOREIGN KEY (category_id) REFERENCES contact_categories(id) ON DELETE CASCADE
    )
  `);

  // Interaktionen/Historie
  db.exec(`
    CREATE TABLE IF NOT EXISTS contact_interactions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      contact_id INTEGER NOT NULL,
      type TEXT NOT NULL CHECK(type IN ('call', 'email', 'meeting', 'note', 'task')),
      subject TEXT,
      content TEXT,
      interaction_date DATETIME DEFAULT CURRENT_TIMESTAMP,
      created_by INTEGER NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE,
      FOREIGN KEY (created_by) REFERENCES users(id)
    )
  `);

  // Trigger für updated_at auf Kontakte-Tabelle
  db.exec(`
    CREATE TRIGGER IF NOT EXISTS update_contacts_timestamp 
    AFTER UPDATE ON contacts
    BEGIN
      UPDATE contacts SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
    END
  `);

  // Assistant Sessions (Claude-Assistent)
  db.exec(`
    CREATE TABLE IF NOT EXISTS assistant_sessions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      title TEXT DEFAULT 'Neue Session',
      status TEXT DEFAULT 'active',
      task_context TEXT,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      ended_at DATETIME,
      FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    )
  `);

  // Assistant Messages
  db.exec(`
    CREATE TABLE IF NOT EXISTS assistant_messages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id INTEGER NOT NULL,
      role TEXT NOT NULL,
      content TEXT NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (session_id) REFERENCES assistant_sessions(id) ON DELETE CASCADE
    )
  `);

  // Indizes für Performance
  db.exec(`
    CREATE INDEX IF NOT EXISTS idx_tasks_project ON tasks(project_id);
    CREATE INDEX IF NOT EXISTS idx_tasks_column ON tasks(column_id);
    CREATE INDEX IF NOT EXISTS idx_tasks_assigned ON tasks(assigned_to);
    CREATE INDEX IF NOT EXISTS idx_tasks_due_date ON tasks(due_date);
    CREATE INDEX IF NOT EXISTS idx_subtasks_task ON subtasks(task_id);
    CREATE INDEX IF NOT EXISTS idx_comments_task ON comments(task_id);
    CREATE INDEX IF NOT EXISTS idx_history_task ON history(task_id);
    CREATE INDEX IF NOT EXISTS idx_attachments_task ON attachments(task_id);
    CREATE INDEX IF NOT EXISTS idx_links_task ON links(task_id);
    CREATE INDEX IF NOT EXISTS idx_task_labels_task ON task_labels(task_id);
    CREATE INDEX IF NOT EXISTS idx_task_labels_label ON task_labels(label_id);
    CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id);
    CREATE INDEX IF NOT EXISTS idx_notifications_user_read ON notifications(user_id, is_read);
    CREATE INDEX IF NOT EXISTS idx_notifications_created ON notifications(created_at);
    CREATE INDEX IF NOT EXISTS idx_applications_project ON applications(project_id);
    CREATE INDEX IF NOT EXISTS idx_knowledge_entries_category ON knowledge_entries(category_id);
    CREATE INDEX IF NOT EXISTS idx_knowledge_attachments_entry ON knowledge_attachments(entry_id);
    CREATE INDEX IF NOT EXISTS idx_coding_directories_position ON coding_directories(position);
    CREATE INDEX IF NOT EXISTS idx_coding_usage_directory ON coding_usage(directory_id);
    CREATE INDEX IF NOT EXISTS idx_coding_usage_timestamp ON coding_usage(timestamp);
    -- Kontakt-Indizes für Performance
    CREATE INDEX IF NOT EXISTS idx_contacts_type ON contacts(type);
    CREATE INDEX IF NOT EXISTS idx_contacts_status ON contacts(status);
    CREATE INDEX IF NOT EXISTS idx_contacts_project ON contacts(project_id);
    CREATE INDEX IF NOT EXISTS idx_contacts_parent ON contacts(parent_company_id);
    CREATE INDEX IF NOT EXISTS idx_contacts_display_name ON contacts(display_name);
    CREATE INDEX IF NOT EXISTS idx_details_contact ON contact_details(contact_id);
    CREATE INDEX IF NOT EXISTS idx_details_type ON contact_details(type);
    CREATE INDEX IF NOT EXISTS idx_interactions_contact ON contact_interactions(contact_id);
    CREATE INDEX IF NOT EXISTS idx_interactions_date ON contact_interactions(interaction_date);
    -- Assistant-Indizes
    CREATE INDEX IF NOT EXISTS idx_assistant_messages_session ON assistant_messages(session_id);
    CREATE INDEX IF NOT EXISTS idx_assistant_sessions_user ON assistant_sessions(user_id);
  `);

  logger.info('Datenbank-Tabellen erstellt');
}

/**
 * Standard-Benutzer erstellen und Admin-Passwort korrigieren
 */
async function createDefaultUsers() {
  const existingUsers = db.prepare('SELECT COUNT(*) as count FROM users').get();

  // Admin-Passwort korrigieren (falls aus .env verschieden)
  const adminExists = db.prepare('SELECT id, password_hash FROM users WHERE email = ? AND role = ?').get('admin@taskmate.local', 'admin');
  if (adminExists) {
    const correctAdminPassword = process.env.ADMIN_PASSWORD || 'admin123';

    // Prüfen ob das Passwort bereits korrekt ist
    const isCorrect = await bcrypt.compare(correctAdminPassword, adminExists.password_hash);
    if (!isCorrect) {
      logger.info('Admin-Passwort wird aus .env aktualisiert');
      const correctHash = await bcrypt.hash(correctAdminPassword, 12);
      db.prepare('UPDATE users SET password_hash = ? WHERE id = ?').run(correctHash, adminExists.id);
      logger.info('Admin-Passwort erfolgreich aktualisiert');
    } else {
      logger.info('Admin-Passwort bereits korrekt');
    }
  }

  if (existingUsers.count === 0) {
    // Benutzer aus Umgebungsvariablen
    const user1 = {
      username: process.env.USER1_USERNAME || 'user1',
      password: process.env.USER1_PASSWORD || 'changeme123',
      displayName: process.env.USER1_DISPLAYNAME || 'Benutzer 1',
      color: process.env.USER1_COLOR || '#00D4FF'
    };

    const user2 = {
      username: process.env.USER2_USERNAME || 'user2',
      password: process.env.USER2_PASSWORD || 'changeme456',
      displayName: process.env.USER2_DISPLAYNAME || 'Benutzer 2',
      color: process.env.USER2_COLOR || '#FF9500'
    };

    const insertUser = db.prepare(`
      INSERT INTO users (username, password_hash, display_name, color, role, permissions)
      VALUES (?, ?, ?, ?, ?, ?)
    `);

    // Admin-Benutzer
    const adminUser = {
      username: process.env.ADMIN_USERNAME || 'admin',
      password: process.env.ADMIN_PASSWORD || 'admin123',
      displayName: process.env.ADMIN_DISPLAYNAME || 'Administrator',
      color: process.env.ADMIN_COLOR || '#8B5CF6'
    };

    // Passwoerter hashen und Benutzer erstellen
    const hash1 = await bcrypt.hash(user1.password, 12);
    const hash2 = await bcrypt.hash(user2.password, 12);
    const hashAdmin = await bcrypt.hash(adminUser.password, 12);

    insertUser.run(user1.username, hash1, user1.displayName, user1.color, 'user', '[]');
    insertUser.run(user2.username, hash2, user2.displayName, user2.color, 'user', '[]');
    insertUser.run(adminUser.username, hashAdmin, adminUser.displayName, adminUser.color, 'admin', '[]');

    logger.info('Standard-Benutzer und Admin erstellt');

    // Standard-Projekt erstellen
    const projectResult = db.prepare(`
      INSERT INTO projects (name, description, created_by)
      VALUES (?, ?, ?)
    `).run('Mein erstes Projekt', 'Willkommen bei TaskMate!', 1);

    const projectId = projectResult.lastInsertRowid;

    // Standard-Spalten erstellen
    const insertColumn = db.prepare(`
      INSERT INTO columns (project_id, name, position, color)
      VALUES (?, ?, ?, ?)
    `);

    insertColumn.run(projectId, 'Offen', 0, null);
    insertColumn.run(projectId, 'In Arbeit', 1, null);
    insertColumn.run(projectId, 'Erledigt', 2, null);

    // Standard-Labels erstellen
    const insertLabel = db.prepare(`
      INSERT INTO labels (project_id, name, color)
      VALUES (?, ?, ?)
    `);

    insertLabel.run(projectId, 'Bug', '#DC2626');
    insertLabel.run(projectId, 'Feature', '#059669');
    insertLabel.run(projectId, 'Dokumentation', '#3182CE');

    logger.info('Standard-Projekt mit Spalten und Labels erstellt');
  }
}

/**
 * Datenbank-Instanz abrufen
 */
function getDb() {
  if (!db) {
    throw new Error('Datenbank nicht initialisiert');
  }
  return db;
}

/**
 * Datenbank schließen
 */
function close() {
  if (db) {
    db.close();
    logger.info('Datenbank geschlossen');
  }
}

module.exports = {
  initialize,
  getDb,
  close
};
