import { describe, it, expect, beforeEach, vi } from "vitest";
import { ErrorCode } from "@pocketcoder/shared/constants";
import { handleProjectDelete, setProjectDeleteGatewayClient, setProjectDeleteStopWatcher, } from "../project-delete.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 project repository
vi.mock("../../db/repositories/projects.js", () => ({
    getProject: vi.fn(),
    deleteProject: vi.fn(),
}));
// Mock project sync
vi.mock("../../gateway/messages/project-sync.js", () => ({
    sendProjectRemoved: vi.fn(),
}));
import { getProject, deleteProject } from "../../db/repositories/projects.js";
import { sendProjectRemoved } from "../../gateway/messages/project-sync.js";
const mockGetProject = vi.mocked(getProject);
const mockDeleteProject = vi.mocked(deleteProject);
const mockSendProjectRemoved = vi.mocked(sendProjectRemoved);
describe("project_delete handler", () => {
    beforeEach(() => {
        vi.clearAllMocks();
        // Reset providers
        setProjectDeleteGatewayClient(null);
        setProjectDeleteStopWatcher(null);
    });
    function createRequest(projectId = "proj-123", requestId = "req-1") {
        return {
            type: "project_delete",
            requestId,
            payload: { projectId },
        };
    }
    function createSendCollector() {
        const responses = [];
        const send = (msg) => {
            responses.push(msg);
        };
        return { responses, send };
    }
    it("should unregister an existing project", async () => {
        mockGetProject.mockReturnValue({
            project_id: "proj-123",
            name: "my-app",
            path: "/home/dev/my-app",
            created_at: "2026-02-20T10:00:00Z",
            last_opened_at: null,
        });
        const { responses, send } = createSendCollector();
        await handleProjectDelete(createRequest(), send);
        expect(responses).toHaveLength(1);
        const resp = responses[0];
        expect(resp.type).toBe("project_delete_response");
        expect(resp.requestId).toBe("req-1");
        expect(resp.error).toBeUndefined();
        expect(resp.payload).toBeDefined();
        expect(resp.payload.success).toBe(true);
        expect(mockDeleteProject).toHaveBeenCalledWith("proj-123");
    });
    it("should return error for non-existent project", async () => {
        mockGetProject.mockReturnValue(null);
        const { responses, send } = createSendCollector();
        await handleProjectDelete(createRequest("proj-nonexistent"), send);
        expect(responses).toHaveLength(1);
        const resp = responses[0];
        expect(resp.type).toBe("project_delete_response");
        expect(resp.error).toBeDefined();
        expect(resp.error.code).toBe(ErrorCode.PROJECT_NOT_FOUND);
        expect(resp.error.message).toContain("proj-nonexistent");
        expect(mockDeleteProject).not.toHaveBeenCalled();
    });
    it("should stop file watcher for the project", async () => {
        mockGetProject.mockReturnValue({
            project_id: "proj-123",
            name: "my-app",
            path: "/home/dev/my-app",
            created_at: "2026-02-20T10:00:00Z",
            last_opened_at: null,
        });
        const mockStopWatcher = vi.fn().mockResolvedValue(undefined);
        setProjectDeleteStopWatcher(mockStopWatcher);
        const { send } = createSendCollector();
        await handleProjectDelete(createRequest(), send);
        expect(mockStopWatcher).toHaveBeenCalledWith("proj-123");
    });
    it("should not delete files on disk", async () => {
        // This test verifies that only deleteProject (DB operation) is called,
        // NOT any filesystem delete operations
        mockGetProject.mockReturnValue({
            project_id: "proj-123",
            name: "my-app",
            path: "/home/dev/my-app",
            created_at: "2026-02-20T10:00:00Z",
            last_opened_at: null,
        });
        const { responses, send } = createSendCollector();
        await handleProjectDelete(createRequest(), send);
        // Only DB delete is called — no fs operations
        expect(mockDeleteProject).toHaveBeenCalledWith("proj-123");
        expect(responses[0].payload.success).toBe(true);
    });
    it("should send project_removed to gateway when client is set", async () => {
        mockGetProject.mockReturnValue({
            project_id: "proj-123",
            name: "my-app",
            path: "/home/dev/my-app",
            created_at: "2026-02-20T10:00:00Z",
            last_opened_at: null,
        });
        const fakeClient = {};
        setProjectDeleteGatewayClient(fakeClient);
        const { send } = createSendCollector();
        await handleProjectDelete(createRequest(), send);
        expect(mockSendProjectRemoved).toHaveBeenCalledWith(fakeClient, "proj-123");
    });
    it("should not send project_removed when no gateway client", async () => {
        mockGetProject.mockReturnValue({
            project_id: "proj-123",
            name: "my-app",
            path: "/home/dev/my-app",
            created_at: "2026-02-20T10:00:00Z",
            last_opened_at: null,
        });
        const { send } = createSendCollector();
        await handleProjectDelete(createRequest(), send);
        expect(mockSendProjectRemoved).not.toHaveBeenCalled();
    });
    it("should reject request with missing projectId", async () => {
        const msg = {
            type: "project_delete",
            requestId: "req-1",
            payload: {},
        };
        const { responses, send } = createSendCollector();
        await handleProjectDelete(msg, send);
        expect(responses).toHaveLength(1);
        const resp = responses[0];
        expect(resp.error).toBeDefined();
        expect(resp.error.code).toBe(ErrorCode.INVALID_REQUEST);
        expect(resp.error.message).toContain("projectId");
    });
});
//# sourceMappingURL=project-delete.test.js.map