const Database = require('better-sqlite3');
const path = require('path');
const bcrypt = require('bcryptjs');

const DB_PATH = process.env.DB_PATH || path.join(__dirname, 'data', 'consulting.db');

let db;

function getDb() {
  if (!db) {
    const fs = require('fs');
    const dir = path.dirname(DB_PATH);
    if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });

    db = new Database(DB_PATH);
    db.pragma('journal_mode = WAL');
    db.pragma('foreign_keys = ON');
    initSchema();
    migrateSchema();
    seedDefaults();
  }
  return db;
}

function migrateSchema() {
  const existingColumns = db.prepare("PRAGMA table_info('users')").all().map(r => r.name);
  const newCols = { email: "TEXT DEFAULT ''", role: "TEXT DEFAULT 'admin'", reset_token: "TEXT DEFAULT ''", reset_expires: "TEXT DEFAULT ''" };
  for (const [col, def] of Object.entries(newCols)) {
    if (!existingColumns.includes(col)) {
      db.exec(`ALTER TABLE users ADD COLUMN ${col} ${def}`);
    }
  }

  db.exec(`
    CREATE TABLE IF NOT EXISTS ai_providers (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      provider_type TEXT NOT NULL DEFAULT 'openrouter',
      api_key TEXT DEFAULT '',
      base_url TEXT DEFAULT '',
      default_model TEXT DEFAULT '',
      is_active INTEGER DEFAULT 1,
      is_default INTEGER DEFAULT 0,
      extra_headers TEXT DEFAULT '{}',
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );
    CREATE TABLE IF NOT EXISTS integrations (
      id TEXT PRIMARY KEY,
      name TEXT DEFAULT '',
      api_key TEXT DEFAULT '',
      webhook_url TEXT DEFAULT '',
      config TEXT DEFAULT '{}',
      status TEXT DEFAULT 'inactive',
      created_at TEXT DEFAULT (datetime('now'))
    );
    CREATE TABLE IF NOT EXISTS reports (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      report_type TEXT DEFAULT 'client_summary',
      client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL,
      project_id INTEGER,
      config TEXT DEFAULT '{}',
      created_at TEXT DEFAULT (datetime('now'))
    );
    CREATE TABLE IF NOT EXISTS projects (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      description TEXT,
      client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL,
      start_date TEXT,
      end_date TEXT,
      status TEXT DEFAULT 'planning',
      priority TEXT DEFAULT 'medium',
      budget REAL,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );
  `);

  const diagramCols = db.prepare("PRAGMA table_info('data_diagrams')").all().map(r => r.name);
  if (!diagramCols.includes('engagement_id')) {
    db.exec('ALTER TABLE data_diagrams ADD COLUMN engagement_id INTEGER REFERENCES engagements(id) ON DELETE SET NULL');
  }
  if (!diagramCols.includes('rack_id')) {
    db.exec('ALTER TABLE data_diagrams ADD COLUMN rack_id INTEGER REFERENCES racks(id) ON DELETE SET NULL');
  }

  const tblRow = db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name='data_diagrams'").get();
  const tblSql = tblRow ? tblRow.sql : '';
  if (tblSql && tblSql.includes('CHECK') && !tblSql.includes('application_flow')) {
    const cols = db.prepare("PRAGMA table_info('data_diagrams')").all();
    const colNames = cols.map(c => c.name);
    const selectCols = colNames.join(', ');
    db.exec(`
      CREATE TABLE data_diagrams_v2 (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
        name TEXT NOT NULL,
        description TEXT,
        diagram_type TEXT DEFAULT 'data_architecture',
        nodes TEXT NOT NULL DEFAULT '[]',
        edges TEXT NOT NULL DEFAULT '[]',
        engagement_id INTEGER REFERENCES engagements(id) ON DELETE SET NULL,
        rack_id INTEGER REFERENCES racks(id) ON DELETE SET NULL,
        created_at TEXT DEFAULT (datetime('now')),
        updated_at TEXT DEFAULT (datetime('now'))
      );
      INSERT INTO data_diagrams_v2 (${selectCols}) SELECT ${selectCols} FROM data_diagrams;
      DROP TABLE data_diagrams;
      ALTER TABLE data_diagrams_v2 RENAME TO data_diagrams;
    `);
  }
}

function initSchema() {
  db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT UNIQUE NOT NULL,
      password_hash TEXT NOT NULL,
      email TEXT DEFAULT '',
      role TEXT DEFAULT 'admin' CHECK(role IN ('admin','consultant','viewer')),
      reset_token TEXT DEFAULT '',
      reset_expires TEXT DEFAULT '',
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS clients (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      industry TEXT,
      website TEXT,
      contact_name TEXT,
      contact_email TEXT,
      contact_phone TEXT,
      status TEXT DEFAULT 'lead' CHECK(status IN ('lead','active','paused','archived')),
      source TEXT,
      notes TEXT,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS engagements (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      type TEXT NOT NULL CHECK(type IN ('assessment','architecture','implementation','monitoring','consulting','training')),
      status TEXT DEFAULT 'planned' CHECK(status IN ('planned','in_progress','completed','on_hold')),
      title TEXT NOT NULL,
      description TEXT,
      start_date TEXT,
      end_date TEXT,
      outcome TEXT,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS assessments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      engagement_id INTEGER REFERENCES engagements(id) ON DELETE SET NULL,
      answers TEXT NOT NULL,
      report TEXT NOT NULL,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS tasks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      engagement_id INTEGER NOT NULL REFERENCES engagements(id) ON DELETE CASCADE,
      title TEXT NOT NULL,
      description TEXT,
      status TEXT DEFAULT 'todo' CHECK(status IN ('todo','in_progress','done','cancelled')),
      priority TEXT DEFAULT 'medium' CHECK(priority IN ('low','medium','high','critical')),
      due_date TEXT,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS advice_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      advice_type TEXT NOT NULL,
      advice_text TEXT NOT NULL,
      priority TEXT DEFAULT 'medium',
      dismissed INTEGER DEFAULT 0,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS racks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      name TEXT NOT NULL,
      location TEXT,
      datacenter TEXT,
      total_units INTEGER DEFAULT 42,
      notes TEXT,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS rack_devices (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      rack_id INTEGER NOT NULL REFERENCES racks(id) ON DELETE CASCADE,
      name TEXT NOT NULL,
      device_type TEXT DEFAULT 'server',
      model TEXT,
      manufacturer TEXT,
      position_u INTEGER NOT NULL,
      height_u INTEGER DEFAULT 1,
      specs TEXT,
      mgmt_ip TEXT,
      notes TEXT,
      serial TEXT DEFAULT '',
      asset_tag TEXT DEFAULT '',
      status TEXT DEFAULT 'active',
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS network_devices (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      name TEXT NOT NULL,
      device_type TEXT NOT NULL CHECK(device_type IN ('switch','router','firewall','loadbalancer','ap','other')),
      model TEXT,
      manufacturer TEXT,
      ip_address TEXT,
      mgmt_ip TEXT,
      ports_count INTEGER DEFAULT 24,
      os_version TEXT,
      notes TEXT,
      status TEXT DEFAULT 'active' CHECK(status IN ('active','standby','decommissioned')),
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS network_connections (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      name TEXT,
      from_type TEXT NOT NULL CHECK(from_type IN ('rack_device','network_device','external')),
      from_id INTEGER,
      from_port TEXT,
      to_type TEXT NOT NULL CHECK(to_type IN ('rack_device','network_device','external')),
      to_id INTEGER,
      to_port TEXT,
      media_type TEXT DEFAULT 'copper' CHECK(media_type IN ('copper','sfp','sfp+','qsfp','dac','fiber')),
      speed TEXT DEFAULT '1GbE',
      vlan TEXT,
      status TEXT DEFAULT 'active' CHECK(status IN ('active','inactive','planned')),
      notes TEXT,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS data_diagrams (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      name TEXT NOT NULL,
      description TEXT,
      diagram_type TEXT DEFAULT 'data_architecture' CHECK(diagram_type IN ('data_architecture','network_topology','system_architecture')),
      nodes TEXT NOT NULL DEFAULT '[]',
      edges TEXT NOT NULL DEFAULT '[]',
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS client_notes (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      content TEXT NOT NULL,
      created_by TEXT DEFAULT '',
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS app_settings (
      key TEXT PRIMARY KEY,
      value TEXT NOT NULL,
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS client_files (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      original_name TEXT NOT NULL,
      stored_name TEXT NOT NULL,
      mime_type TEXT DEFAULT '',
      file_size INTEGER DEFAULT 0,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS audit_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      username TEXT DEFAULT '',
      action TEXT NOT NULL,
      entity_type TEXT NOT NULL,
      entity_id INTEGER,
      details TEXT DEFAULT '',
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS time_entries (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL,
      engagement_id INTEGER REFERENCES engagements(id) ON DELETE SET NULL,
      date TEXT NOT NULL,
      hours REAL NOT NULL,
      description TEXT DEFAULT '',
      billable INTEGER DEFAULT 1,
      hourly_rate REAL DEFAULT 150.0,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS invoices (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
      number TEXT UNIQUE NOT NULL,
      status TEXT DEFAULT 'draft' CHECK(status IN ('draft','sent','paid','overdue','cancelled')),
      date TEXT NOT NULL,
      due_date TEXT NOT NULL,
      subtotal REAL DEFAULT 0,
      tax REAL DEFAULT 0,
      total REAL DEFAULT 0,
      notes TEXT DEFAULT '',
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS invoice_items (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
      description TEXT NOT NULL,
      quantity REAL DEFAULT 1,
      unit_price REAL DEFAULT 0,
      total REAL DEFAULT 0
    );

    CREATE TABLE IF NOT EXISTS notifications (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      type TEXT NOT NULL,
      title TEXT NOT NULL,
      message TEXT DEFAULT '',
      channel TEXT DEFAULT 'in-app' CHECK(channel IN ('in-app','email','slack','webhook')),
      read INTEGER DEFAULT 0,
      sent INTEGER DEFAULT 0,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS calendar_events (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL,
      engagement_id INTEGER REFERENCES engagements(id) ON DELETE SET NULL,
      title TEXT NOT NULL,
      description TEXT DEFAULT '',
      event_type TEXT DEFAULT 'meeting' CHECK(event_type IN ('meeting','call','deadline','workshop','review','other')),
      start_time TEXT NOT NULL,
      end_time TEXT NOT NULL,
      all_day INTEGER DEFAULT 0,
      color TEXT DEFAULT '#58a6ff',
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS user_settings (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL UNIQUE,
      notify_email INTEGER DEFAULT 1,
      notify_slack INTEGER DEFAULT 0,
      notify_webhook INTEGER DEFAULT 0,
      webhook_url TEXT DEFAULT '',
      slack_webhook TEXT DEFAULT '',
      language TEXT DEFAULT 'nl'
    );

    CREATE TABLE IF NOT EXISTS email_accounts (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      email TEXT NOT NULL,
      name TEXT DEFAULT '',
      imap_host TEXT NOT NULL,
      imap_port INTEGER DEFAULT 993,
      imap_secure INTEGER DEFAULT 1,
      imap_user TEXT NOT NULL,
      imap_pass TEXT NOT NULL,
      smtp_host TEXT NOT NULL,
      smtp_port INTEGER DEFAULT 587,
      smtp_secure INTEGER DEFAULT 0,
      smtp_user TEXT DEFAULT '',
      smtp_pass TEXT DEFAULT '',
      active INTEGER DEFAULT 1,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS email_messages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      account_id INTEGER NOT NULL REFERENCES email_accounts(id) ON DELETE CASCADE,
      uid INTEGER NOT NULL,
      folder TEXT DEFAULT 'INBOX',
      subject TEXT DEFAULT '',
      from_name TEXT DEFAULT '',
      from_addr TEXT DEFAULT '',
      to_addr TEXT DEFAULT '',
      cc TEXT DEFAULT '',
      bcc TEXT DEFAULT '',
      date TEXT DEFAULT '',
      body_text TEXT DEFAULT '',
      body_html TEXT DEFAULT '',
      attachments INTEGER DEFAULT 0,
      seen INTEGER DEFAULT 0,
      flagged INTEGER DEFAULT 0,
      replied INTEGER DEFAULT 0,
      size INTEGER DEFAULT 0,
      created_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS datacenters (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      address TEXT DEFAULT '',
      city TEXT DEFAULT '',
      region TEXT DEFAULT '',
      postal_code TEXT DEFAULT '',
      phone TEXT DEFAULT '',
      website TEXT DEFAULT '',
      type TEXT DEFAULT 'colo',
      operator TEXT DEFAULT '',
      tier TEXT DEFAULT 'III',
      power_mw REAL DEFAULT 0,
      size_sqm INTEGER DEFAULT 0,
      network_vendors TEXT DEFAULT '',
      server_vendors TEXT DEFAULT '',
      storage_vendors TEXT DEFAULT '',
      certifications TEXT DEFAULT '',
      notes TEXT DEFAULT ''
    );

    CREATE TABLE IF NOT EXISTS tech_companies (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      industry TEXT DEFAULT '',
      city TEXT DEFAULT '',
      address TEXT DEFAULT '',
      postal_code TEXT DEFAULT '',
      phone TEXT DEFAULT '',
      email TEXT DEFAULT '',
      website TEXT DEFAULT '',
      linkedin TEXT DEFAULT '',
      employees INTEGER DEFAULT 0,
      revenue_range TEXT DEFAULT '',
      data_warehouse TEXT DEFAULT '',
      bi_tools TEXT DEFAULT '',
      cloud_provider TEXT DEFAULT '',
      data_lake TEXT DEFAULT '',
      ai_ml TEXT DEFAULT '',
      database_vendor TEXT DEFAULT '',
      lead_score INTEGER DEFAULT 0,
      lead_status TEXT DEFAULT 'new',
      notes TEXT DEFAULT '',
      source TEXT DEFAULT ''
    );
  `);
}

function seedDefaults() {
  const existing = db.prepare('SELECT COUNT(*) as cnt FROM users').get();
  if (existing.cnt === 0) {
    const pw = process.env.ADMIN_PASSWORD || 'admin';
    const hash = bcrypt.hashSync(pw, 10);
    const result = db.prepare('INSERT INTO users (username, password_hash, role) VALUES (?, ?, ?)').run('admin', hash, 'admin');
    db.prepare('INSERT INTO user_settings (user_id, language) VALUES (?, ?)').run(result.lastInsertRowid, 'nl');
    console.log(`Default user created: admin / ${pw}`);
  }
}

const DEFAULTS = {
  brand_name: 'Mek-Tech Consulting',
  language: 'nl',
  theme: 'mek-neon-blue',
  default_page: '/',
  auto_refresh: '0',
  items_per_page: '50',
  debug_mode: '0',
  icon_colors: JSON.stringify({
    'layout-dashboard': '#58a6ff',
    users: '#3fb950',
    briefcase: '#d29922',
    server: '#bc8cff',
    'check-circle': '#3fb950',
    lightbulb: '#d29922',
    clock: '#79c0ff',
    eye: '#f778ba',
    phone: '#3fb950',
    'file-text': '#f778ba',
    'edit-3': '#79c0ff',
    folder: '#d29922',
    'clipboard-list': '#bc8cff'
  }),
  theme_colors: '{}',
  showcase_url: 'http://192.168.1.247:3010'
};

function getSettings() {
  const d = getDb();
  const rows = d.prepare('SELECT key, value FROM app_settings').all();
  const s = { ...DEFAULTS };
  // Ensure defaults exist in DB
  const upsert = d.prepare(`INSERT INTO app_settings (key, value, updated_at) VALUES (?, ?, datetime('now'))
    ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at`);
  for (const [k, v] of Object.entries(DEFAULTS)) {
    const row = rows.find(r => r.key === k);
    if (row) {
      s[k] = row.value;
    } else {
      upsert.run(k, v);
    }
  }
  // Also store icon_colors as parsed object
  if (typeof s.icon_colors === 'string') {
    try { s.icon_colors = JSON.parse(s.icon_colors); } catch (e) { s.icon_colors = JSON.parse(DEFAULTS.icon_colors); }
  }
  if (typeof s.theme_colors === 'string') {
    try { s.theme_colors = JSON.parse(s.theme_colors || '{}'); } catch (e) { s.theme_colors = {}; }
  }
  if (!s.theme_colors || typeof s.theme_colors !== 'object') s.theme_colors = {};
  return s;
}

function updateSetting(key, value) {
  const d = getDb();
  if (typeof value === 'object') value = JSON.stringify(value);
  d.prepare(`INSERT INTO app_settings (key, value, updated_at) VALUES (?, ?, datetime('now'))
    ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at`).run(key, value);
}

function logAudit(userId, username, action, entityType, entityId, details) {
  const d = getDb();
  d.prepare('INSERT INTO audit_log (user_id, username, action, entity_type, entity_id, details) VALUES (?, ?, ?, ?, ?, ?)')
    .run(userId || null, username || '', action, entityType, entityId || null, details || '');
}

function getUserSettings(userId) {
  const d = getDb();
  let s = d.prepare('SELECT * FROM user_settings WHERE user_id = ?').get(userId);
  if (!s) {
    d.prepare('INSERT INTO user_settings (user_id) VALUES (?)').run(userId);
    s = d.prepare('SELECT * FROM user_settings WHERE user_id = ?').get(userId);
  }
  return s;
}

module.exports = { getDb, getSettings, updateSetting, logAudit, getUserSettings, DEFAULTS };
