import fs from "node:fs/promises";
import { homedir } from "node:os";
import path from "node:path";
import { Type } from "@sinclair/typebox";
import { ApiError, Problems } from "@zuplo/errors";
import { normalizeRelativePath } from "../utils/path.js";
// XDG config directory helpers
function getXdgConfigHome() {
    return process.env.XDG_CONFIG_HOME ?? path.join(homedir(), ".config");
}
function getZuploConfigDir() {
    return path.join(getXdgConfigHome(), "zuplo");
}
function getEditorConfigPath() {
    return path.join(getZuploConfigDir(), "editor.json");
}
const EDITORS = {
    vscode: {
        name: "Visual Studio Code",
        protocol: "vscode",
        urlTemplate: "vscode://file{file}:{line}:{column}",
        detectFiles: [".vscode/settings.json"],
    },
    cursor: {
        name: "Cursor",
        protocol: "cursor",
        urlTemplate: "cursor://file{file}:{line}:{column}",
        detectFiles: [".cursor"],
    },
    webstorm: {
        name: "WebStorm",
        protocol: "webstorm",
        urlTemplate: "webstorm://open?file={file}&line={line}",
        detectFiles: [".idea"],
    },
    phpstorm: {
        name: "PhpStorm",
        protocol: "phpstorm",
        urlTemplate: "phpstorm://open?file={file}&line={line}",
        detectFiles: [".idea"],
    },
    intellij: {
        name: "IntelliJ IDEA",
        protocol: "idea",
        urlTemplate: "idea://open?file={file}&line={line}",
        detectFiles: [".idea"],
    },
    sublimetext: {
        name: "Sublime Text",
        protocol: "subl",
        urlTemplate: "subl://open?url=file://{file}&line={line}&column={column}",
    },
};
const EditorPreferenceBody = Type.Object({
    editor: Type.String(),
});
const OpenEditorBody = Type.Object({
    file: Type.String(),
    line: Type.Optional(Type.Number()),
    column: Type.Optional(Type.Number()),
});
async function loadEditorPreference() {
    try {
        const configPath = getEditorConfigPath();
        const data = await fs.readFile(configPath, "utf-8");
        const config = JSON.parse(data);
        return config.editor ?? null;
    }
    catch {
        return null;
    }
}
async function saveEditorPreference(editor) {
    const configDir = getZuploConfigDir();
    await fs.mkdir(configDir, { recursive: true });
    const configPath = getEditorConfigPath();
    await fs.writeFile(configPath, JSON.stringify({ editor }, null, 2), "utf-8");
}
export async function createEditorRoutes(fastify, options) {
    const { sourceDirectory } = options;
    // Detect editor: GET /editor/detect
    fastify.get("/detect", async (_request, reply) => {
        // Check saved preference
        const savedEditor = await loadEditorPreference();
        if (savedEditor && EDITORS[savedEditor]) {
            return reply.status(200).send({
                editor: savedEditor,
                name: EDITORS[savedEditor].name,
            });
        }
        // No editor found
        return reply.status(200).send({
            editor: null,
            name: null,
        });
    });
    // Get available editors: GET /editor/list
    fastify.get("/list", async (_request, reply) => {
        const editors = Object.entries(EDITORS).map(([id, info]) => ({
            id,
            name: info.name,
        }));
        return reply.status(200).send({ editors });
    });
    // Save editor preference: POST /editor/preference
    fastify.post("/preference", {
        schema: {
            body: EditorPreferenceBody,
        },
    }, async (request, reply) => {
        const { editor } = request.body;
        if (!EDITORS[editor]) {
            throw new ApiError({
                ...Problems.BAD_REQUEST,
                detail: `Unknown editor: ${editor}`,
            });
        }
        await saveEditorPreference(editor);
        return reply.status(200).send({ success: true });
    });
    // Get URL to open file in editor: POST /editor/open
    fastify.post("/open", {
        schema: {
            body: OpenEditorBody,
        },
    }, async (request, reply) => {
        const { file, line = 1, column = 1 } = request.body;
        if (!file) {
            throw new ApiError({
                ...Problems.BAD_REQUEST,
                detail: "File path is required",
            });
        }
        // Get editor preference
        const savedEditor = await loadEditorPreference();
        if (!savedEditor || !EDITORS[savedEditor]) {
            throw new ApiError({
                ...Problems.BAD_REQUEST,
                detail: "No editor preference set",
            });
        }
        const editor = EDITORS[savedEditor];
        // Build file path
        const relativePath = normalizeRelativePath(file);
        const fullPath = path.join(sourceDirectory, relativePath);
        // Build URL from template
        const url = editor.urlTemplate
            .replace("{file}", fullPath)
            .replace("{line}", String(line))
            .replace("{column}", String(column));
        return reply.status(200).send({ url });
    });
}
//# sourceMappingURL=editor.js.map