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 { openDatabase, closeDatabase } from "../../database.js";
import { createProject } from "../projects.js";
import { createCommandRun, updateCommandRun, getCommandRun, cleanupOldRuns, } from "../command-runs.js";
describe("command-runs repository", () => {
    let tempDir;
    let dbPath;
    let projectId;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-cmdruns-test-"));
        dbPath = join(tempDir, "daemon.db");
        closeDatabase();
        openDatabase(dbPath);
        const project = createProject("test-project", "/tmp/test-project");
        projectId = project.project_id;
    });
    afterEach(async () => {
        closeDatabase();
        await rm(tempDir, { recursive: true, force: true });
    });
    it("should create command run record", () => {
        createCommandRun("req-1", projectId, "echo hello");
        const run = getCommandRun("req-1");
        expect(run).not.toBeNull();
        expect(run.request_id).toBe("req-1");
        expect(run.project_id).toBe(projectId);
        expect(run.command).toBe("echo hello");
        expect(run.started_at).toBeDefined();
        expect(run.ended_at).toBeNull();
        expect(run.exit_code).toBeNull();
    });
    it("should update command run with exit code", () => {
        createCommandRun("req-2", projectId, "ls -la");
        updateCommandRun("req-2", 0, "total 42\ndrwxr-xr-x", false);
        const run = getCommandRun("req-2");
        expect(run).not.toBeNull();
        expect(run.exit_code).toBe(0);
        expect(run.output_preview).toBe("total 42\ndrwxr-xr-x");
        expect(run.truncated).toBe(0);
        expect(run.ended_at).not.toBeNull();
    });
    it("should update command run with truncated flag", () => {
        createCommandRun("req-3", projectId, "cat bigfile");
        updateCommandRun("req-3", 0, "partial output...", true);
        const run = getCommandRun("req-3");
        expect(run.truncated).toBe(1);
    });
    it("should get command run by request ID", () => {
        createCommandRun("req-4", projectId, "pwd");
        const run = getCommandRun("req-4");
        expect(run).not.toBeNull();
        expect(run.command).toBe("pwd");
    });
    it("should return null for non-existent request ID", () => {
        const run = getCommandRun("non-existent");
        expect(run).toBeNull();
    });
    it("should cleanup runs older than 7 days", () => {
        const db = openDatabase();
        // Insert a run with an old timestamp
        db.prepare("INSERT INTO command_runs (request_id, project_id, command, started_at) VALUES (?, ?, ?, datetime('now', '-8 days'))").run("old-req", projectId, "echo old");
        // Insert a recent run
        createCommandRun("new-req", projectId, "echo new");
        const deleted = cleanupOldRuns();
        expect(deleted).toBeGreaterThanOrEqual(1);
        expect(getCommandRun("old-req")).toBeNull();
        expect(getCommandRun("new-req")).not.toBeNull();
    });
    it("should keep only last 10000 runs when limit exceeded", () => {
        const db = openDatabase();
        // Use a transaction for bulk insert performance
        const insert = db.prepare("INSERT INTO command_runs (request_id, project_id, command) VALUES (?, ?, ?)");
        const insertMany = db.transaction((count) => {
            for (let i = 0; i < count; i++) {
                insert.run(`req-batch-${i}`, projectId, `echo ${i}`);
            }
        });
        // Insert 10,005 rows
        insertMany(10005);
        const countBefore = db.prepare("SELECT COUNT(*) as count FROM command_runs").get().count;
        expect(countBefore).toBe(10005);
        cleanupOldRuns();
        const countAfter = db.prepare("SELECT COUNT(*) as count FROM command_runs").get().count;
        expect(countAfter).toBe(10000);
    });
});
//# sourceMappingURL=command-runs.test.js.map