// biome-ignore-all lint/suspicious/noExplicitAny: Allow any
import assert from "node:assert";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { after, afterEach, before, beforeEach, describe, it } from "node:test";
import { cleanupTestDir, createTempTestDir, createTestFastifyInstance, } from "../test-utils/setup.js";
import { createEditorRoutes } from "./editor.js";
describe("Editor Routes", () => {
    let app;
    let testDir;
    let configDir;
    let configPath;
    before(async () => {
        // Create a unique temporary config directory for testing
        const testRoot = path.join(tmpdir(), `zuplo-test-root-${Date.now()}`);
        configDir = path.join(testRoot, "zuplo");
        configPath = path.join(configDir, "editor.json");
        // Set XDG_CONFIG_HOME to our test root so config files go to the right place
        process.env.XDG_CONFIG_HOME = testRoot;
    });
    beforeEach(async () => {
        // Create fresh test directory for each test
        testDir = await createTempTestDir("editor-test-");
        // Create fresh app instance
        app = await createTestFastifyInstance();
        await app.register(createEditorRoutes, {
            prefix: "/editor",
            sourceDirectory: testDir,
        });
        await app.ready();
        // Clean up any existing config
        try {
            await rm(configPath, { force: true });
        }
        catch {
            // Ignore
        }
    });
    after(async () => {
        await cleanupTestDir(configDir);
    });
    describe("GET /editor/detect", () => {
        it("should return null when no editor preference is saved", async () => {
            const response = await app.inject({
                method: "GET",
                url: "/editor/detect",
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.strictEqual(body.editor, null);
            assert.strictEqual(body.name, null);
        });
        it("should return saved editor preference", async () => {
            // Setup: save an editor preference
            await mkdir(path.dirname(configPath), { recursive: true });
            const config = { editor: "vscode" };
            await writeFile(configPath, JSON.stringify(config), "utf-8");
            const response = await app.inject({
                method: "GET",
                url: "/editor/detect",
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.strictEqual(body.editor, "vscode");
            assert.strictEqual(body.name, "Visual Studio Code");
        });
        it("should return null for invalid saved editor", async () => {
            // Setup: save an invalid editor
            await mkdir(path.dirname(configPath), { recursive: true });
            const config = { editor: "invalid-editor" };
            await writeFile(configPath, JSON.stringify(config), "utf-8");
            const response = await app.inject({
                method: "GET",
                url: "/editor/detect",
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.strictEqual(body.editor, null);
            assert.strictEqual(body.name, null);
        });
    });
    describe("GET /editor/list", () => {
        it("should return list of available editors", async () => {
            const response = await app.inject({
                method: "GET",
                url: "/editor/list",
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.ok(Array.isArray(body.editors));
            assert.ok(body.editors.length > 0);
            // Verify structure of editor entries
            const vscodeEditor = body.editors.find((e) => e.id === "vscode");
            assert.ok(vscodeEditor);
            assert.strictEqual(vscodeEditor.name, "Visual Studio Code");
        });
        it("should include all known editors", async () => {
            const response = await app.inject({
                method: "GET",
                url: "/editor/list",
            });
            const body = JSON.parse(response.body);
            const editorIds = body.editors.map((e) => e.id);
            // Check for some expected editors
            assert.ok(editorIds.includes("vscode"));
            assert.ok(editorIds.includes("cursor"));
            assert.ok(editorIds.includes("webstorm"));
        });
    });
    describe("POST /editor/preference", () => {
        it("should save valid editor preference", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/preference",
                payload: { editor: "vscode" },
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.strictEqual(body.success, true);
        });
        it("should reject invalid editor", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/preference",
                payload: { editor: "invalid-editor" },
            });
            assert.strictEqual(response.statusCode, 400);
            const body = JSON.parse(response.body);
            // Check for error message in detail, message, or title field
            const errorMsg = body.detail || body.message || body.title || "";
            assert.ok(errorMsg.toLowerCase().includes("unknown") ||
                errorMsg.toLowerCase().includes("invalid") ||
                errorMsg.toLowerCase().includes("bad"), `Expected error message about invalid editor, got: ${JSON.stringify(body)}`);
        });
        it("should reject missing editor field", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/preference",
                payload: {},
            });
            assert.strictEqual(response.statusCode, 400);
        });
    });
    describe("POST /editor/open", () => {
        beforeEach(async () => {
            // Save a valid editor preference for open tests
            const config = { editor: "vscode" };
            await writeFile(configPath, JSON.stringify(config), "utf-8");
        });
        it("should generate URL to open file", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/open",
                payload: {
                    file: "config/routes.json",
                    line: 10,
                    column: 5,
                },
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.ok(body.url);
            assert.ok(body.url.startsWith("vscode://file"));
            assert.ok(body.url.includes("config/routes.json"));
            assert.ok(body.url.includes(":10:5"));
        });
        it("should use default line and column when not provided", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/open",
                payload: {
                    file: "config/routes.json",
                },
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.ok(body.url);
            assert.ok(body.url.includes(":1:1"));
        });
        it("should handle file paths with leading slash", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/open",
                payload: {
                    file: "/config/routes.json",
                },
            });
            assert.strictEqual(response.statusCode, 200);
            const body = JSON.parse(response.body);
            assert.ok(body.url);
            assert.ok(body.url.includes("config/routes.json"));
        });
        it("should fail when no editor preference is set", async () => {
            // Remove editor preference
            await rm(configPath, { force: true });
            const response = await app.inject({
                method: "POST",
                url: "/editor/open",
                payload: {
                    file: "config/routes.json",
                },
            });
            assert.strictEqual(response.statusCode, 400);
            const body = JSON.parse(response.body);
            // Check for error message in detail, message, or title field
            const errorMsg = body.detail || body.message || body.title || "";
            assert.ok(errorMsg.toLowerCase().includes("editor") ||
                errorMsg.toLowerCase().includes("preference") ||
                errorMsg.toLowerCase().includes("bad"), `Expected error message about missing editor preference, got: ${JSON.stringify(body)}`);
        });
        it("should require file path", async () => {
            const response = await app.inject({
                method: "POST",
                url: "/editor/open",
                payload: {},
            });
            assert.strictEqual(response.statusCode, 400);
        });
    });
    // Cleanup after each test
    afterEach(async () => {
        await app.close();
        await cleanupTestDir(testDir);
    });
});
//# sourceMappingURL=editor.spec.js.map