import Database from "better-sqlite3";
import { mkdirSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const DATA_DIR = join(__dirname, "..", "data");
const DB_PATH = join(DATA_DIR, "notifications.db");

export interface Notification {
  id: string;
  title: string;
  description: string | null;
  source: string | null;
  level: string;
  created_at: string;
  read_at: string | null;
  dismissed_at: string | null;
}

let db: Database.Database | null = null;

function getDb(): Database.Database {
  if (!db) {
    mkdirSync(DATA_DIR, { recursive: true });
    db = new Database(DB_PATH);
    db.pragma("journal_mode = WAL");

    db.exec(`
      CREATE TABLE IF NOT EXISTS notifications (
        id TEXT PRIMARY KEY,
        title TEXT NOT NULL,
        description TEXT,
        source TEXT,
        level TEXT DEFAULT 'info',
        created_at TEXT NOT NULL,
        read_at TEXT,
        dismissed_at TEXT
      );
      CREATE INDEX IF NOT EXISTS idx_notifications_created ON notifications(created_at);
      CREATE INDEX IF NOT EXISTS idx_notifications_dismissed ON notifications(dismissed_at);
    `);

    const count = db.prepare("SELECT COUNT(*) as c FROM notifications").get() as { c: number };
    if (count.c === 0) {
      const insert = db.prepare(
        "INSERT INTO notifications (id, title, description, source, level, created_at) VALUES (?, ?, ?, ?, ?, ?)"
      );
      const now = new Date();
      insert.run(
        crypto.randomUUID(),
        "Welcome to Teletraan",
        "Your Teletraan system is ready.",
        "system",
        "info",
        now.toISOString()
      );
      const t2 = new Date(now.getTime() - 60 * 1000);
      insert.run(
        crypto.randomUUID(),
        "System initialized",
        "All services are running and healthy.",
        "system",
        "info",
        t2.toISOString()
      );
    }
  }
  return db;
}

export function createNotification(params: {
  title: string;
  description?: string;
  source?: string;
  level?: string;
}): Notification {
  const conn = getDb();
  purgeOld(conn);

  const id = crypto.randomUUID();
  const now = new Date().toISOString();

  conn.prepare(
    "INSERT INTO notifications (id, title, description, source, level, created_at) VALUES (?, ?, ?, ?, ?, ?)"
  ).run(id, params.title, params.description ?? null, params.source ?? null, params.level ?? "info", now);

  return conn.prepare("SELECT * FROM notifications WHERE id = ?").get(id) as Notification;
}

export function getNotifications(): Notification[] {
  return getDb()
    .prepare("SELECT * FROM notifications WHERE dismissed_at IS NULL ORDER BY created_at DESC")
    .all() as Notification[];
}

export function markRead(id: string): void {
  const now = new Date().toISOString();
  getDb().prepare("UPDATE notifications SET read_at = ? WHERE id = ? AND read_at IS NULL").run(now, id);
}

export function markDismissed(id: string): void {
  const now = new Date().toISOString();
  getDb().prepare("UPDATE notifications SET dismissed_at = ? WHERE id = ?").run(now, id);
}

export function markAllRead(): void {
  const now = new Date().toISOString();
  getDb().prepare("UPDATE notifications SET read_at = ? WHERE read_at IS NULL AND dismissed_at IS NULL").run(now);
}

function purgeOld(conn: Database.Database): void {
  const cutoff = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString();
  conn.prepare("DELETE FROM notifications WHERE created_at < ?").run(cutoff);
}
