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, MAX_QUEUE_PER_PROJECT } from "@pocketcoder/shared/constants";
import { openDatabase, closeDatabase } from "../../db/database.js";
import { createProject } from "../../db/repositories/projects.js";
import { handleAgentMessage } from "../../handlers/agent-message.js";
import { clearAllQueues } from "../message-queue.js";
vi.mock("../../utils/logger.js", () => ({
    logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
}));
vi.mock("../../opencode/proxy.js", () => ({
    proxyToOpenCode: vi.fn(),
}));
import { proxyToOpenCode } from "../../opencode/proxy.js";
const mockProxyToOpenCode = vi.mocked(proxyToOpenCode);
describe("queue overflow handling", () => {
    let tempDir;
    let projectDir;
    let dbPath;
    let projectId;
    const agentSessionId = "overflow-test-session";
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-queue-overflow-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();
        clearAllQueues();
    });
    afterEach(async () => {
        closeDatabase();
        clearAllQueues();
        await rm(tempDir, { recursive: true, force: true });
    });
    function createSendCollector() {
        const messages = [];
        return { messages, send: (msg) => messages.push(msg) };
    }
    async function fillQueue(send) {
        // Block first call so all subsequent messages queue
        mockProxyToOpenCode.mockImplementation(async () => new Promise(() => {
            /* never resolves */
        }));
        // Send first message — starts processing (occupies the processor)
        const first = {
            type: "agent_message",
            requestId: "req-first",
            sessionId: projectId,
            payload: { agentSessionId, content: "First" },
        };
        await handleAgentMessage(first, send);
        // Fill queue to the limit
        for (let i = 0; i < MAX_QUEUE_PER_PROJECT; i++) {
            const msg = {
                type: "agent_message",
                requestId: `req-fill-${i}`,
                sessionId: projectId,
                payload: { agentSessionId, content: `Fill ${i}` },
            };
            await handleAgentMessage(msg, send);
        }
    }
    it("should reject when queue full", async () => {
        const { messages, send } = createSendCollector();
        await fillQueue(send);
        // Try to add one more — should be rejected
        const overflow = {
            type: "agent_message",
            requestId: "req-overflow",
            sessionId: projectId,
            payload: { agentSessionId, content: "Overflow" },
        };
        await handleAgentMessage(overflow, send);
        const resp = messages.find((m) => m.requestId === "req-overflow");
        expect(resp).toBeDefined();
        expect(resp.error).toBeDefined();
        expect(resp.payload).toBeUndefined();
    });
    it("should return DAEMON_BUSY code", async () => {
        const { messages, send } = createSendCollector();
        await fillQueue(send);
        const overflow = {
            type: "agent_message",
            requestId: "req-overflow-code",
            sessionId: projectId,
            payload: { agentSessionId, content: "Overflow" },
        };
        await handleAgentMessage(overflow, send);
        const resp = messages.find((m) => m.requestId === "req-overflow-code");
        expect(resp.error.code).toBe(ErrorCode.DAEMON_BUSY);
        expect(resp.error.message).toBe("Message queue is full");
    });
    it("should include retry hint", async () => {
        const { messages, send } = createSendCollector();
        await fillQueue(send);
        const overflow = {
            type: "agent_message",
            requestId: "req-overflow-hint",
            sessionId: projectId,
            payload: { agentSessionId, content: "Overflow" },
        };
        await handleAgentMessage(overflow, send);
        const resp = messages.find((m) => m.requestId === "req-overflow-hint");
        expect(resp.error.details).toBeDefined();
        expect(resp.error.details.queueSize).toBe(MAX_QUEUE_PER_PROJECT);
        expect(resp.error.details.retryAfterMs).toBe(5000);
    });
});
//# sourceMappingURL=queue-overflow.test.js.map