import { mkdtemp, rm } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { openDatabase, closeDatabase } from "../../../db/database.js";
import { createProject } from "../../../db/repositories/projects.js";
import { createControlPlane } from "../../server.js";
import { setStatusProviders } from "../status.js";
describe("/status endpoint", () => {
    let server;
    let address;
    let tempDir;
    let dbPath;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-status-test-"));
        dbPath = join(tempDir, "daemon.db");
        closeDatabase();
        openDatabase(dbPath);
        // Reset providers to defaults
        setStatusProviders({});
        server = createControlPlane({ host: "127.0.0.1", port: 0 });
        address = await server.start();
    });
    afterEach(async () => {
        await server.stop();
        closeDatabase();
        await rm(tempDir, { recursive: true, force: true });
    });
    it("should return daemon version", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(response.status).toBe(200);
        // Check version is a valid semver string (e.g., "1.2.3")
        expect(body.version).toMatch(/^\d+\.\d+\.\d+$/);
    });
    it("should return gateway connection state", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.gateway).toEqual({
            connected: false,
            lastConnectedAt: null,
            lastHeartbeatAt: null,
        });
    });
    it("should return gateway state from provider", async () => {
        setStatusProviders({
            getGatewayState: () => ({
                connected: true,
                lastConnectedAt: "2026-02-10T21:14:00Z",
                lastHeartbeatAt: "2026-02-10T21:15:00Z",
            }),
        });
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.gateway.connected).toBe(true);
        expect(body.gateway.lastConnectedAt).toBe("2026-02-10T21:14:00Z");
        expect(body.gateway.lastHeartbeatAt).toBe("2026-02-10T21:15:00Z");
    });
    it("should support async getGatewayState provider", async () => {
        setStatusProviders({
            getGatewayState: async () => {
                // Simulate async operation (like active ping)
                await new Promise((resolve) => setTimeout(resolve, 10));
                return {
                    connected: true,
                    lastConnectedAt: "2026-02-10T21:14:00Z",
                    lastHeartbeatAt: "2026-02-10T21:15:00Z",
                };
            },
        });
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.gateway.connected).toBe(true);
    });
    it("should detect git availability", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        // Git should be available in the test environment
        expect(typeof body.capabilities.hasGit).toBe("boolean");
        expect(Array.isArray(body.capabilities.warnings)).toBe(true);
    });
    it("should detect opencode availability", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(typeof body.capabilities.hasOpenCode).toBe("boolean");
    });
    it("should list registered projects", async () => {
        createProject("test-project", "/tmp/test-project");
        createProject("another-project", "/tmp/another-project");
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.projects).toHaveLength(2);
        const names = body.projects.map((p) => p.name);
        expect(names).toContain("test-project");
        expect(names).toContain("another-project");
        for (const project of body.projects) {
            expect(project.projectId).toBeDefined();
            expect(project.path).toBeDefined();
            expect(project.watcherRunning).toBe(false);
            expect(project.lastFsSeq).toBe(0);
        }
    });
    it("should return machineKey from provider", async () => {
        setStatusProviders({
            getMachineKey: () => "550e8400-e29b-41d4-a716-446655440000",
            getLoggedIn: () => true,
        });
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.machineKey).toBe("550e8400-e29b-41d4-a716-446655440000");
        expect(body.loggedIn).toBe(true);
    });
    it("should return null machineKey when not authenticated", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.machineKey).toBeNull();
        expect(body.loggedIn).toBe(false);
    });
    it("should return lastFsSeq from database", async () => {
        const project = createProject("seq-test", "/tmp/seq-test");
        const db = openDatabase();
        db.prepare("INSERT INTO fs_state (project_id, last_seq) VALUES (?, ?)").run(project.project_id, 42);
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        const seqProject = body.projects.find((p) => p.name === "seq-test");
        expect(seqProject?.lastFsSeq).toBe(42);
    });
    it("should return watcher status from provider", async () => {
        const project = createProject("watcher-test", "/tmp/watcher-test");
        setStatusProviders({
            isWatcherRunning: (projectId) => projectId === project.project_id,
        });
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        const watcherProject = body.projects.find((p) => p.name === "watcher-test");
        expect(watcherProject?.watcherRunning).toBe(true);
    });
    it("should return lastError from provider", async () => {
        setStatusProviders({
            getLastError: () => ({ code: "CONNECTION_FAILED", message: "Gateway unreachable" }),
        });
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.lastError).toEqual({ code: "CONNECTION_FAILED", message: "Gateway unreachable" });
    });
    it("should return null lastError by default", async () => {
        const response = await fetch(`${address}/status`);
        const body = (await response.json());
        expect(body.lastError).toBeNull();
    });
});
//# sourceMappingURL=status.test.js.map