import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
import { homedir } from "node:os";
import { dirname, join } from "node:path";
import JSON5 from "json5";
export function resolveRefreshFreeConfigPath(env) {
    const home = env.HOME?.trim() || homedir();
    if (!home)
        throw new Error("Missing HOME");
    return join(home, ".summarize", "config.json");
}
function assertNoComments(raw, path) {
    let inString = null;
    let escaped = false;
    let line = 1;
    let col = 1;
    for (let i = 0; i < raw.length; i += 1) {
        const ch = raw[i] ?? "";
        const next = raw[i + 1] ?? "";
        if (inString) {
            if (escaped) {
                escaped = false;
                col += 1;
                continue;
            }
            if (ch === "\\") {
                escaped = true;
                col += 1;
                continue;
            }
            if (ch === inString)
                inString = null;
            if (ch === "\n") {
                line += 1;
                col = 1;
            }
            else {
                col += 1;
            }
            continue;
        }
        if (ch === '"' || ch === "'") {
            inString = ch;
            escaped = false;
            col += 1;
            continue;
        }
        if (ch === "/" && next === "/") {
            throw new Error(`Invalid config file ${path}: comments are not allowed (found // at ${line}:${col}).`);
        }
        if (ch === "/" && next === "*") {
            throw new Error(`Invalid config file ${path}: comments are not allowed (found /* at ${line}:${col}).`);
        }
        if (ch === "\n") {
            line += 1;
            col = 1;
        }
        else {
            col += 1;
        }
    }
}
function isRecord(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
async function readConfigRoot(configPath) {
    try {
        const raw = await readFile(configPath, "utf8");
        assertNoComments(raw, configPath);
        const parsed = JSON5.parse(raw);
        if (!isRecord(parsed)) {
            throw new Error(`Invalid config file ${configPath}: expected an object at the top level`);
        }
        return parsed;
    }
    catch (error) {
        const code = error?.code;
        if (code === "ENOENT")
            return {};
        throw error;
    }
}
export async function writeFreeModelConfig({ env, candidates, setDefault, }) {
    const configPath = resolveRefreshFreeConfigPath(env);
    const root = await readConfigRoot(configPath);
    const configModelsRaw = root.models;
    const configModels = (() => {
        if (typeof configModelsRaw === "undefined")
            return {};
        if (!isRecord(configModelsRaw)) {
            throw new Error(`Invalid config file ${configPath}: "models" must be an object.`);
        }
        return { ...configModelsRaw };
    })();
    configModels.free = { rules: [{ candidates }] };
    root.models = configModels;
    if (setDefault)
        root.model = "free";
    const configDir = dirname(configPath);
    await mkdir(configDir, { recursive: true, mode: 0o700 });
    await chmod(configDir, 0o700).catch(() => { });
    const tmp = `${configPath}.tmp-${process.pid}-${Date.now()}`;
    await writeFile(tmp, `${JSON.stringify(root, null, 2)}\n`, {
        encoding: "utf8",
        mode: 0o600,
    });
    await rename(tmp, configPath);
    await chmod(configPath, 0o600).catch(() => { });
    return configPath;
}
//# sourceMappingURL=config.js.map