import Database from 'better-sqlite3'
import path from 'path'
import { Employee, User, SkillDefinition } from '@skillmate/shared'
import bcrypt from 'bcryptjs'
import { v4 as uuidv4 } from 'uuid'
import { db as secureDb, encryptedDb, initializeSecureDatabase } from './secureDatabase'
export { initializeSecureDatabase } from './secureDatabase'

// Export the secure database instance
export const db = secureDb

// IMPORTANT: secureDatabase.ts owns all security‑sensitive base tables
// (users, employees, skills and their junctions, language_skills, specializations,
// controlled_vocabulary, system_settings, security_audit_log) including
// encrypted fields and indexes. This module defines only extended, non‑sensitive
// schemas (profiles, workspaces/bookings, organizational structure, reminders, analytics).

export function initializeDatabase() {
  // Lightweight schema guard (no mutations): warn if legacy/plain schemas are present
  try {
    const usersCols: any[] = db.prepare(`PRAGMA table_info(users)`).all() as any
    const hasEmailHash = usersCols.some(c => c.name === 'email_hash')
    if (!hasEmailHash) {
      console.warn('[DB-Guard] users.email_hash missing. Ensure initializeSecureDatabase() runs first and legacy data is migrated.')
    }
  } catch {}

  try {
    const empCols: any[] = db.prepare(`PRAGMA table_info(employees)`).all() as any
    const hasEmpEmailHash = empCols.some(c => c.name === 'email_hash')
    const hasEmpPhoneHash = empCols.some(c => c.name === 'phone_hash')
    if (!hasEmpEmailHash || !hasEmpPhoneHash) {
      console.warn('[DB-Guard] employees hash columns missing. Ensure secure schema initialized and data migrated.')
    }
  } catch {}

  // Profiles table (erweitert für Yellow Pages)
  db.exec(`
    CREATE TABLE IF NOT EXISTS profiles (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      department TEXT,
      location TEXT,
      role TEXT,
      email TEXT,
      phone TEXT,
      teams_link TEXT,
      job_category TEXT CHECK(job_category IN ('Technik', 'IT & Digitalisierung', 'Verwaltung', 'F&E', 'Kommunikation & HR', 'Produktion', 'Sonstiges')),
      job_title TEXT,
      job_desc TEXT,
      consent_public_profile INTEGER DEFAULT 0,
      consent_searchable INTEGER DEFAULT 0,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      updated_by TEXT NOT NULL,
      review_due_at TEXT,
      search_vector TEXT
    )
  `)
  
  // Volltext-Index für Suche
  db.exec(`
    CREATE INDEX IF NOT EXISTS idx_profiles_search 
    ON profiles(search_vector);
    
    CREATE INDEX IF NOT EXISTS idx_profiles_department 
    ON profiles(department);
    
    CREATE INDEX IF NOT EXISTS idx_profiles_location 
    ON profiles(location);
    
    CREATE INDEX IF NOT EXISTS idx_profiles_job_category 
    ON profiles(job_category);
    
    CREATE INDEX IF NOT EXISTS idx_profiles_review_due 
    ON profiles(review_due_at);
  `)

  // Employees/Skills tables are defined in secureDatabase (encrypted & indexed)

  // Profile Kompetenzen (Arrays als separate Tabellen)
  db.exec(`
    CREATE TABLE IF NOT EXISTS profile_domains (
      profile_id TEXT NOT NULL,
      domain TEXT NOT NULL,
      PRIMARY KEY (profile_id, domain),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_tools (
      profile_id TEXT NOT NULL,
      tool TEXT NOT NULL,
      PRIMARY KEY (profile_id, tool),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_methods (
      profile_id TEXT NOT NULL,
      method TEXT NOT NULL,
      PRIMARY KEY (profile_id, method),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_industry_knowledge (
      profile_id TEXT NOT NULL,
      knowledge TEXT NOT NULL,
      PRIMARY KEY (profile_id, knowledge),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_regulatory (
      profile_id TEXT NOT NULL,
      regulation TEXT NOT NULL,
      PRIMARY KEY (profile_id, regulation),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_networks (
      profile_id TEXT NOT NULL,
      network TEXT NOT NULL,
      PRIMARY KEY (profile_id, network),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_digital_skills (
      profile_id TEXT NOT NULL,
      skill TEXT NOT NULL,
      PRIMARY KEY (profile_id, skill),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS profile_social_skills (
      profile_id TEXT NOT NULL,
      skill TEXT NOT NULL,
      PRIMARY KEY (profile_id, skill),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
  `)
  
  // Profile Sprachen
  db.exec(`
    CREATE TABLE IF NOT EXISTS profile_languages (
      profile_id TEXT NOT NULL,
      code TEXT NOT NULL,
      level TEXT NOT NULL CHECK(level IN ('basic', 'fluent', 'native', 'business')),
      PRIMARY KEY (profile_id, code),
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
  `)
  
  // Profile Projekte
  db.exec(`
    CREATE TABLE IF NOT EXISTS profile_projects (
      id TEXT PRIMARY KEY,
      profile_id TEXT NOT NULL,
      title TEXT NOT NULL,
      role TEXT,
      summary TEXT,
      created_at TEXT NOT NULL,
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE TABLE IF NOT EXISTS project_links (
      project_id TEXT NOT NULL,
      link TEXT NOT NULL,
      PRIMARY KEY (project_id, link),
      FOREIGN KEY (project_id) REFERENCES profile_projects(id) ON DELETE CASCADE
    );
  `)
  
  // Language skills / Specializations are defined in secureDatabase

  // Sync tables are owned by SyncService initializer (avoid duplicate legacy schema)

  // Workspace Management Tables
  
  // Workspaces (Desks, Meeting Rooms, etc.)
  db.exec(`
    CREATE TABLE IF NOT EXISTS workspaces (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      type TEXT NOT NULL CHECK(type IN ('desk', 'meeting_room', 'phone_booth', 'parking', 'locker')),
      floor TEXT NOT NULL,
      building TEXT,
      capacity INTEGER DEFAULT 1,
      equipment TEXT, -- JSON array of equipment
      position_x INTEGER, -- For floor plan visualization
      position_y INTEGER,
      is_active INTEGER DEFAULT 1,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    )
  `)

  // Bookings table
  db.exec(`
    CREATE TABLE IF NOT EXISTS bookings (
      id TEXT PRIMARY KEY,
      workspace_id TEXT NOT NULL,
      user_id TEXT NOT NULL,
      employee_id TEXT NOT NULL,
      start_time TEXT NOT NULL,
      end_time TEXT NOT NULL,
      status TEXT NOT NULL CHECK(status IN ('confirmed', 'cancelled', 'completed', 'no_show')),
      check_in_time TEXT,
      check_out_time TEXT,
      notes TEXT,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
      FOREIGN KEY (user_id) REFERENCES users(id),
      FOREIGN KEY (employee_id) REFERENCES employees(id)
    )
  `)

  // Recurring bookings
  db.exec(`
    CREATE TABLE IF NOT EXISTS recurring_bookings (
      id TEXT PRIMARY KEY,
      workspace_id TEXT NOT NULL,
      user_id TEXT NOT NULL,
      employee_id TEXT NOT NULL,
      start_date TEXT NOT NULL,
      end_date TEXT NOT NULL,
      time_start TEXT NOT NULL,
      time_end TEXT NOT NULL,
      days_of_week TEXT NOT NULL, -- JSON array of days [1,2,3,4,5] for Mon-Fri
      created_at TEXT NOT NULL,
      FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
      FOREIGN KEY (user_id) REFERENCES users(id),
      FOREIGN KEY (employee_id) REFERENCES employees(id)
    )
  `)

  // Booking rules and restrictions
  db.exec(`
    CREATE TABLE IF NOT EXISTS booking_rules (
      id TEXT PRIMARY KEY,
      workspace_type TEXT,
      max_duration_hours INTEGER,
      max_advance_days INTEGER,
      min_advance_hours INTEGER,
      max_bookings_per_user_per_day INTEGER,
      max_bookings_per_user_per_week INTEGER,
      auto_release_minutes INTEGER, -- Auto-release if not checked in
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    )
  `)

  // Analytics data
  db.exec(`
    CREATE TABLE IF NOT EXISTS workspace_analytics (
      id TEXT PRIMARY KEY,
      workspace_id TEXT NOT NULL,
      date TEXT NOT NULL,
      total_bookings INTEGER DEFAULT 0,
      total_hours_booked REAL DEFAULT 0,
      utilization_rate REAL DEFAULT 0,
      no_show_count INTEGER DEFAULT 0,
      unique_users INTEGER DEFAULT 0,
      peak_hour INTEGER,
      FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
      UNIQUE(workspace_id, date)
    )
  `)

  // Floor plans
  db.exec(`
    CREATE TABLE IF NOT EXISTS floor_plans (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      floor TEXT NOT NULL,
      building TEXT,
      image_url TEXT,
      svg_data TEXT, -- SVG data for interactive floor plan
      width INTEGER,
      height INTEGER,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    )
  `)

  // Organizational Structure Tables
  db.exec(`
    CREATE TABLE IF NOT EXISTS organizational_units (
      id TEXT PRIMARY KEY,
      code TEXT NOT NULL UNIQUE,
      name TEXT NOT NULL,
      type TEXT NOT NULL CHECK(type IN ('direktion', 'abteilung', 'dezernat', 'sachgebiet', 'teildezernat', 'fuehrungsstelle', 'stabsstelle', 'sondereinheit')),
      level INTEGER NOT NULL,
      parent_id TEXT,
      position_x INTEGER,
      position_y INTEGER,
      color TEXT,
      order_index INTEGER DEFAULT 0,
      description TEXT,
      has_fuehrungsstelle INTEGER DEFAULT 0,
      fuehrungsstelle_name TEXT,
      is_active INTEGER DEFAULT 1,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      FOREIGN KEY (parent_id) REFERENCES organizational_units(id)
    );
    
    CREATE INDEX IF NOT EXISTS idx_org_units_parent ON organizational_units(parent_id);
    CREATE INDEX IF NOT EXISTS idx_org_units_type ON organizational_units(type);
    CREATE INDEX IF NOT EXISTS idx_org_units_level ON organizational_units(level);
  `)

  // Import rules for organization parsing (persist admin overrides)
  db.exec(`
    CREATE TABLE IF NOT EXISTS organization_import_rules (
      id TEXT PRIMARY KEY,
      target_code TEXT UNIQUE NOT NULL,
      parent_code TEXT,
      type_override TEXT,
      name_override TEXT,
      created_at TEXT NOT NULL
    );
    CREATE INDEX IF NOT EXISTS idx_org_rules_target ON organization_import_rules(target_code);
  `)

  // Employee Unit Assignments
  db.exec(`
    CREATE TABLE IF NOT EXISTS employee_unit_assignments (
      id TEXT PRIMARY KEY,
      employee_id TEXT NOT NULL,
      unit_id TEXT NOT NULL,
      role TEXT NOT NULL CHECK(role IN ('leiter', 'stellvertreter', 'mitarbeiter', 'beauftragter')),
      start_date TEXT NOT NULL,
      end_date TEXT,
      is_primary INTEGER DEFAULT 1,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      FOREIGN KEY (employee_id) REFERENCES employees(id) ON DELETE CASCADE,
      FOREIGN KEY (unit_id) REFERENCES organizational_units(id) ON DELETE CASCADE,
      UNIQUE(employee_id, unit_id, role)
    );

    CREATE INDEX IF NOT EXISTS idx_emp_units_employee ON employee_unit_assignments(employee_id);
    CREATE INDEX IF NOT EXISTS idx_emp_units_unit ON employee_unit_assignments(unit_id);
    CREATE UNIQUE INDEX IF NOT EXISTS idx_emp_units_primary_unique 
      ON employee_unit_assignments(employee_id) 
      WHERE is_primary = 1;
  `)

  // Special Positions (Personalrat, Beauftragte, etc.)
  db.exec(`
    CREATE TABLE IF NOT EXISTS special_positions (
      id TEXT PRIMARY KEY,
      employee_id TEXT NOT NULL,
      position_type TEXT NOT NULL CHECK(position_type IN ('personalrat', 'schwerbehindertenvertretung', 'datenschutzbeauftragter', 'gleichstellungsbeauftragter', 'inklusionsbeauftragter', 'informationssicherheitsbeauftragter', 'geheimschutzbeauftragter', 'extremismusbeauftragter')),
      unit_id TEXT,
      start_date TEXT NOT NULL,
      end_date TEXT,
      is_active INTEGER DEFAULT 1,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      FOREIGN KEY (employee_id) REFERENCES employees(id) ON DELETE CASCADE,
      FOREIGN KEY (unit_id) REFERENCES organizational_units(id)
    );
    
    CREATE INDEX IF NOT EXISTS idx_special_pos_employee ON special_positions(employee_id);
    CREATE INDEX IF NOT EXISTS idx_special_pos_type ON special_positions(position_type);
  `)

  // Deputy Assignments (Vertretungen)
  db.exec(`
    CREATE TABLE IF NOT EXISTS deputy_assignments (
      id TEXT PRIMARY KEY,
      principal_id TEXT NOT NULL,
      deputy_id TEXT NOT NULL,
      unit_id TEXT,
      valid_from TEXT NOT NULL,
      valid_until TEXT NOT NULL,
      reason TEXT,
      can_delegate INTEGER DEFAULT 1,
      created_by TEXT NOT NULL,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      FOREIGN KEY (principal_id) REFERENCES employees(id),
      FOREIGN KEY (deputy_id) REFERENCES employees(id),
      FOREIGN KEY (unit_id) REFERENCES organizational_units(id),
      FOREIGN KEY (created_by) REFERENCES users(id)
    );
    
    CREATE INDEX IF NOT EXISTS idx_deputy_principal ON deputy_assignments(principal_id);
    CREATE INDEX IF NOT EXISTS idx_deputy_deputy ON deputy_assignments(deputy_id);
    CREATE INDEX IF NOT EXISTS idx_deputy_dates ON deputy_assignments(valid_from, valid_until);
  `)

  // Deputy Delegations (Vertretungs-Weitergaben)
  db.exec(`
    CREATE TABLE IF NOT EXISTS deputy_delegations (
      id TEXT PRIMARY KEY,
      original_assignment_id TEXT NOT NULL,
      from_deputy_id TEXT NOT NULL,
      to_deputy_id TEXT NOT NULL,
      reason TEXT,
      delegated_at TEXT NOT NULL,
      created_at TEXT NOT NULL,
      FOREIGN KEY (original_assignment_id) REFERENCES deputy_assignments(id),
      FOREIGN KEY (from_deputy_id) REFERENCES employees(id),
      FOREIGN KEY (to_deputy_id) REFERENCES employees(id)
    );
    
    CREATE INDEX IF NOT EXISTS idx_delegation_assignment ON deputy_delegations(original_assignment_id);
    CREATE INDEX IF NOT EXISTS idx_delegation_from ON deputy_delegations(from_deputy_id);
    CREATE INDEX IF NOT EXISTS idx_delegation_to ON deputy_delegations(to_deputy_id);
  `)

  // Audit Log für Änderungsverfolgung
  db.exec(`
    CREATE TABLE IF NOT EXISTS audit_log (
      id TEXT PRIMARY KEY,
      entity_type TEXT NOT NULL,
      entity_id TEXT NOT NULL,
      action TEXT NOT NULL CHECK(action IN ('create', 'update', 'delete')),
      user_id TEXT NOT NULL,
      changes TEXT, -- JSON mit Änderungen
      timestamp TEXT NOT NULL,
      ip_address TEXT,
      user_agent TEXT
    );
    
    CREATE INDEX IF NOT EXISTS idx_audit_entity ON audit_log(entity_type, entity_id);
    CREATE INDEX IF NOT EXISTS idx_audit_user ON audit_log(user_id);
    CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
  `)
  
  // Reminder-System
  db.exec(`
    CREATE TABLE IF NOT EXISTS reminders (
      id TEXT PRIMARY KEY,
      profile_id TEXT NOT NULL,
      type TEXT NOT NULL CHECK(type IN ('annual_update', 'overdue', 'custom')),
      message TEXT,
      sent_at TEXT,
      acknowledged_at TEXT,
      created_at TEXT NOT NULL,
      FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
    );
    
    CREATE INDEX IF NOT EXISTS idx_reminders_profile ON reminders(profile_id);
    CREATE INDEX IF NOT EXISTS idx_reminders_sent ON reminders(sent_at);
  `)
  
  // Create indexes for better performance (only for tables defined here)
  db.exec(`
    CREATE INDEX IF NOT EXISTS idx_bookings_workspace ON bookings(workspace_id);
    CREATE INDEX IF NOT EXISTS idx_bookings_user ON bookings(user_id);
    CREATE INDEX IF NOT EXISTS idx_bookings_start_time ON bookings(start_time);
    CREATE INDEX IF NOT EXISTS idx_bookings_status ON bookings(status);
    CREATE INDEX IF NOT EXISTS idx_workspace_analytics_date ON workspace_analytics(date);
  `)
}
