import { mkdtemp, rm } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import Database from "better-sqlite3";
import { openDatabase, closeDatabase, getDatabaseVersion } from "../database.js";
describe("database", () => {
    let tempDir;
    let dbPath;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-db-test-"));
        dbPath = join(tempDir, "daemon.db");
        // Reset singleton between tests
        closeDatabase();
    });
    afterEach(async () => {
        closeDatabase();
        await rm(tempDir, { recursive: true, force: true });
    });
    it("should create database file on first open", () => {
        const db = openDatabase(dbPath);
        expect(db).toBeInstanceOf(Database);
    });
    it("should create all required tables", () => {
        const db = openDatabase(dbPath);
        const tables = db
            .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
            .all();
        const tableNames = tables.map((t) => t.name);
        expect(tableNames).toContain("projects");
        expect(tableNames).toContain("fs_state");
        expect(tableNames).toContain("command_runs");
        expect(tableNames).toContain("terminal_sessions");
    });
    it("should create required indexes", () => {
        const db = openDatabase(dbPath);
        const indexes = db
            .prepare("SELECT name FROM sqlite_master WHERE type='index' AND name NOT LIKE 'sqlite_%' ORDER BY name")
            .all();
        const indexNames = indexes.map((i) => i.name);
        expect(indexNames).toContain("idx_projects_path");
        expect(indexNames).toContain("idx_command_runs_project");
        expect(indexNames).toContain("idx_command_runs_started");
        expect(indexNames).toContain("idx_terminal_sessions_project");
        expect(indexNames).toContain("idx_terminal_sessions_created");
    });
    it("should track migration version", () => {
        const db = openDatabase(dbPath);
        const version = getDatabaseVersion(db);
        expect(version).toBe(2);
    });
    it("should create terminal_sessions table with correct schema", () => {
        const db = openDatabase(dbPath);
        const columns = db.prepare("PRAGMA table_info(terminal_sessions)").all();
        const colNames = columns.map((c) => c.name);
        expect(colNames).toContain("terminal_id");
        expect(colNames).toContain("project_id");
        expect(colNames).toContain("pid");
        expect(colNames).toContain("created_at");
        expect(colNames).toContain("closed_at");
        // terminal_id is primary key
        const pkCol = columns.find((c) => c.name === "terminal_id");
        expect(pkCol?.pk).toBe(1);
        // project_id is NOT NULL
        const projectIdCol = columns.find((c) => c.name === "project_id");
        expect(projectIdCol?.notnull).toBe(1);
    });
    it("should handle concurrent opens gracefully", () => {
        const db1 = openDatabase(dbPath);
        // Second call returns same singleton instance
        const db2 = openDatabase(dbPath);
        expect(db1).toBe(db2);
    });
    it("should enable WAL journal mode", () => {
        const db = openDatabase(dbPath);
        const mode = db.pragma("journal_mode", { simple: true });
        expect(mode).toBe("wal");
    });
    it("should enable foreign keys", () => {
        const db = openDatabase(dbPath);
        const fk = db.pragma("foreign_keys", { simple: true });
        expect(fk).toBe(1);
    });
    it("should not re-run migrations on second open", () => {
        openDatabase(dbPath);
        closeDatabase();
        // Reopen - should not error
        const db = openDatabase(dbPath);
        const version = getDatabaseVersion(db);
        expect(version).toBe(2);
    });
});
//# sourceMappingURL=database.test.js.map