import { mkdtemp, rm, mkdir } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { ErrorCode } from "@pocketcoder/shared/constants";
import { openDatabase, closeDatabase } from "../../db/database.js";
import { createProject } from "../../db/repositories/projects.js";
import { handleAgentSessionsList } from "../agent-sessions-list.js";
// Suppress logger output in tests
vi.mock("../../utils/logger.js", () => ({
    logger: {
        debug: vi.fn(),
        info: vi.fn(),
        warn: vi.fn(),
        error: vi.fn(),
    },
}));
// Mock the OpenCode proxy
vi.mock("../../opencode/proxy.js", () => ({
    proxyToOpenCode: vi.fn(),
}));
import { proxyToOpenCode } from "../../opencode/proxy.js";
const mockProxyToOpenCode = vi.mocked(proxyToOpenCode);
describe("agent_sessions_list handler", () => {
    let tempDir;
    let projectDir;
    let dbPath;
    let projectId;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-agent-sessions-list-test-"));
        projectDir = join(tempDir, "project");
        dbPath = join(tempDir, "daemon.db");
        await mkdir(projectDir);
        closeDatabase();
        openDatabase(dbPath);
        const project = createProject("test-project", projectDir);
        projectId = project.project_id;
        mockProxyToOpenCode.mockReset();
    });
    afterEach(async () => {
        closeDatabase();
        await rm(tempDir, { recursive: true, force: true });
    });
    function createRequest() {
        return {
            type: "agent_sessions_list",
            requestId: "req-1",
            sessionId: projectId,
            payload: {},
        };
    }
    function createSendCollector() {
        const responses = [];
        const send = (msg) => {
            responses.push(msg);
        };
        return { responses, send };
    }
    it("should return sessions from OpenCode API filtered by project path", async () => {
        mockProxyToOpenCode.mockResolvedValue({
            status: 200,
            headers: {},
            body: JSON.stringify([
                {
                    id: "session-aaa",
                    directory: projectDir,
                    title: "Test Session 1",
                    time: { created: 1705312800000, updated: 1705316400000 },
                },
                {
                    id: "session-bbb",
                    directory: projectDir,
                    title: "Test Session 2",
                    time: { created: 1705399200000, updated: 1705402800000 },
                },
                {
                    id: "session-other",
                    directory: "/other/project",
                    title: "Other Session",
                    time: { created: 1705485600000, updated: 1705489200000 },
                },
            ]),
        });
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(responses).toHaveLength(1);
        const resp = responses[0];
        expect(resp.type).toBe("agent_sessions_list_response");
        expect(resp.error).toBeUndefined();
        expect(resp.payload).toBeDefined();
        // Should filter out session-other from /other/project
        expect(resp.payload.sessions).toHaveLength(2);
        expect(resp.payload.sessions[0].agentSessionId).toBe("session-bbb"); // Most recent first
        expect(resp.payload.sessions[1].agentSessionId).toBe("session-aaa");
    });
    it("should return empty list when no sessions match project path", async () => {
        mockProxyToOpenCode.mockResolvedValue({
            status: 200,
            headers: {},
            body: JSON.stringify([
                {
                    id: "session-other",
                    directory: "/other/project",
                    title: "Other Session",
                    time: { created: 1705485600000, updated: 1705489200000 },
                },
            ]),
        });
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeUndefined();
        expect(responses[0].payload.sessions).toEqual([]);
    });
    it("should return empty list when OpenCode returns empty array", async () => {
        mockProxyToOpenCode.mockResolvedValue({
            status: 200,
            headers: {},
            body: JSON.stringify([]),
        });
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(mockProxyToOpenCode).toHaveBeenCalledWith({
            method: "GET",
            path: "/session",
        });
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeUndefined();
        expect(responses[0].payload.sessions).toEqual([]);
    });
    it("should error for non-existent project", async () => {
        const msg = {
            type: "agent_sessions_list",
            requestId: "req-2",
            sessionId: "non-existent-project",
            payload: {},
        };
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(msg, send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeDefined();
        expect(responses[0].error.code).toBe(ErrorCode.INVALID_REQUEST);
        expect(mockProxyToOpenCode).not.toHaveBeenCalled();
    });
    it("should handle OpenCode unreachable error", async () => {
        mockProxyToOpenCode.mockRejectedValue(new Error("OPENCODE_UNREACHABLE"));
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeDefined();
        expect(responses[0].error.code).toBe(ErrorCode.OPENCODE_UNREACHABLE);
    });
    it("should handle timeout error", async () => {
        mockProxyToOpenCode.mockRejectedValue(new Error("TIMEOUT"));
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeDefined();
        expect(responses[0].error.code).toBe(ErrorCode.TIMEOUT);
    });
    it("should handle other errors gracefully", async () => {
        mockProxyToOpenCode.mockRejectedValue(new Error("Connection refused"));
        const { responses, send } = createSendCollector();
        await handleAgentSessionsList(createRequest(), send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error).toBeDefined();
        expect(responses[0].error.code).toBe(ErrorCode.UNKNOWN_ERROR);
        expect(responses[0].error.message).toBe("Connection refused");
    });
});
//# sourceMappingURL=agent-sessions-list.test.js.map