import path from "node:path";
import { pathExists } from "@poe-code/config-mutations";
import { hasOwnErrorCode } from "./errors.js";
import { assertConfigPathSafe } from "./store.js";
export function collectEnvOverrides(scopes, env) {
    const document = {};
    const entries = [];
    for (const definition of scopes) {
        const scopeResult = collectScopeEnvOverrides(definition, env);
        if (Object.keys(scopeResult.values).length === 0) {
            continue;
        }
        defineDataProperty(document, definition.scope, scopeResult.values);
        entries.push(...scopeResult.entries);
    }
    return { entries, document };
}
export async function resolveEditTarget(fs, configPath, projectConfigPath, options) {
    if (options.global && options.project) {
        throw new Error("Choose either --global or --project, not both.");
    }
    if (options.global) {
        return configPath;
    }
    if (options.project) {
        return projectConfigPath;
    }
    if (await pathExists(fs, projectConfigPath)) {
        return projectConfigPath;
    }
    return configPath;
}
export async function initProjectConfig(fs, targetPath) {
    await assertConfigPathSafe(fs, targetPath);
    if (await pathExists(fs, targetPath)) {
        return "already-exists";
    }
    await fs.mkdir(path.dirname(targetPath), { recursive: true });
    await assertConfigPathSafe(fs, targetPath);
    try {
        await fs.writeFile(targetPath, EMPTY_DOCUMENT, { encoding: "utf8", flag: "wx" });
        return "created";
    }
    catch (error) {
        if (isAlreadyExists(error)) {
            return "already-exists";
        }
        await fs.unlink(targetPath).catch(() => undefined);
        throw error;
    }
}
function isAlreadyExists(error) {
    return hasOwnErrorCode(error, "EEXIST");
}
function collectScopeEnvOverrides(definition, env) {
    const entries = [];
    const values = {};
    for (const [key, field] of Object.entries(definition.schema)) {
        if (!field.env) {
            continue;
        }
        const value = coerceEnvValue(field.type, env[field.env]);
        if (value === undefined) {
            continue;
        }
        defineDataProperty(values, key, value);
        entries.push(`  ${field.env} = ${String(value)}`);
    }
    return { entries, values };
}
function defineDataProperty(object, key, value) {
    Object.defineProperty(object, key, {
        configurable: true,
        enumerable: true,
        value,
        writable: true
    });
}
function coerceEnvValue(type, raw) {
    if (raw === undefined) {
        return undefined;
    }
    if (type === "string") {
        return raw;
    }
    if (type === "number") {
        if (raw.length === 0) {
            return undefined;
        }
        const parsed = Number(raw);
        return Number.isFinite(parsed) ? parsed : undefined;
    }
    if (type === "json") {
        try {
            return JSON.parse(raw);
        }
        catch {
            return undefined;
        }
    }
    if (raw === "true" || raw === "1") {
        return true;
    }
    if (raw === "false" || raw === "0") {
        return false;
    }
    return undefined;
}
const EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}\n`;
