import { DatabaseSync } from 'node:sqlite';
import { config } from './config.js';
import { hashPassword } from './crypto.js';

export const db = new DatabaseSync(config.databasePath);

export function migrate() {
  db.exec(`
    PRAGMA journal_mode = WAL;
    CREATE TABLE IF NOT EXISTS users (
      id TEXT PRIMARY KEY,
      username TEXT NOT NULL UNIQUE,
      password_hash TEXT NOT NULL,
      created_at TEXT NOT NULL
    );
    CREATE TABLE IF NOT EXISTS sessions (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL,
      expires_at TEXT NOT NULL,
      created_at TEXT NOT NULL,
      FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    );
    CREATE TABLE IF NOT EXISTS nodes (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      base_url TEXT NOT NULL,
      token TEXT NOT NULL,
      enabled INTEGER NOT NULL DEFAULT 1,
      last_health_status TEXT,
      last_health_at TEXT,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );
    CREATE TABLE IF NOT EXISTS schedules (
      id TEXT PRIMARY KEY,
      node_id TEXT NOT NULL,
      vm_name TEXT NOT NULL,
      enabled INTEGER NOT NULL DEFAULT 1,
      interval_hours INTEGER NOT NULL DEFAULT 24,
      time_of_day TEXT NOT NULL DEFAULT '02:00',
      next_run_at TEXT,
      last_run_at TEXT,
      last_error TEXT NOT NULL DEFAULT '',
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      UNIQUE (node_id, vm_name),
      FOREIGN KEY (node_id) REFERENCES nodes(id) ON DELETE CASCADE
    );
    CREATE TABLE IF NOT EXISTS audit_events (
      id TEXT PRIMARY KEY,
      user_id TEXT,
      username TEXT,
      action TEXT NOT NULL,
      target_type TEXT NOT NULL,
      target_id TEXT,
      details TEXT NOT NULL DEFAULT '{}',
      created_at TEXT NOT NULL
    );
    CREATE TABLE IF NOT EXISTS job_history (
      id TEXT PRIMARY KEY,
      node_id TEXT NOT NULL,
      node_name TEXT NOT NULL,
      vm_name TEXT NOT NULL,
      type TEXT NOT NULL,
      agent_job_id TEXT,
      status TEXT NOT NULL,
      error TEXT,
      current_step TEXT,
      snapshot_id TEXT,
      started_at TEXT NOT NULL,
      finished_at TEXT,
      duration_ms INTEGER,
      updated_at TEXT NOT NULL
    );
  `);
  addColumnIfMissing('job_history', 'current_step', 'TEXT');
  addColumnIfMissing('job_history', 'snapshot_id', 'TEXT');
  addColumnIfMissing('job_history', 'finished_at', 'TEXT');
  addColumnIfMissing('job_history', 'duration_ms', 'INTEGER');

  const existing = db.prepare('SELECT id FROM users LIMIT 1').get();
  if (!existing) {
    if (!config.authPassword) {
      throw new Error('AUTH_PASSWORD is required for initial admin user creation. Set AUTH_PASSWORD before starting management.');
    }
    const now = new Date().toISOString();
    db.prepare('INSERT INTO users (id, username, password_hash, created_at) VALUES (?, ?, ?, ?)')
      .run(`user_${cryptoId()}`, config.authUsername, hashPassword(config.authPassword), now);
  }
}

function cryptoId() {
  return Math.random().toString(16).slice(2) + Date.now().toString(16);
}

function addColumnIfMissing(table, column, definition) {
  const columns = db.prepare(`PRAGMA table_info(${table})`).all().map((row) => row.name);
  if (!columns.includes(column)) {
    db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
  }
}
