import { createHatchOrchestrator } from "./orchestrator.js";
const MAX_CONSENT_BYTES = 64 * 1024;
/**
 * Product-facing command surface. A product should expose a tiny wrapper which
 * directly imports its own pinned Hatch config and calls this function; Hatch
 * intentionally has no generic `--adapter-module` flag.
 */
export async function runHatchCli(options) {
    const writeStdout = options.writeStdout ?? ((value) => process.stdout.write(value));
    const writeStderr = options.writeStderr ?? ((value) => process.stderr.write(value));
    try {
        const [command, ...arguments_] = options.argv;
        const hatch = createHatchOrchestrator(options.product);
        if (command === "check") {
            assertNoArguments(arguments_, "check");
            writeStdout(`${JSON.stringify(await hatch.check())}\n`);
            return 0;
        }
        if (command === "apply") {
            const { planDigest } = parseApplyArguments(arguments_);
            const source = options.readStdin ? await options.readStdin() : await readProcessStdin();
            if (Buffer.byteLength(source, "utf8") > MAX_CONSENT_BYTES) {
                throw new Error("Native consent input exceeds the 64 KiB command bound.");
            }
            let consent;
            try {
                consent = JSON.parse(source);
            }
            catch {
                throw new Error("Native consent input must be one JSON object on standard input.");
            }
            writeStdout(`${JSON.stringify(await hatch.apply({ planDigest, consent }))}\n`);
            return 0;
        }
        if (command === "reconcile") {
            const transactionId = parseReconcileArguments(arguments_);
            writeStdout(`${JSON.stringify(await hatch.reconcile(transactionId))}\n`);
            return 0;
        }
        throw new Error("Usage: check | apply --plan-digest <sha256> < consent.json | reconcile --transaction-id <id>");
    }
    catch (error) {
        const message = error instanceof Error ? error.message : "Hatch command failed.";
        writeStderr(`${JSON.stringify({ ok: false, error: message })}\n`);
        return 1;
    }
}
function assertNoArguments(arguments_, command) {
    if (arguments_.length)
        throw new Error(`${command} does not accept command-line arguments.`);
}
function parseApplyArguments(arguments_) {
    if (arguments_.length !== 2 || arguments_[0] !== "--plan-digest" || !/^[a-f0-9]{64}$/u.test(arguments_[1] ?? "")) {
        throw new Error("Usage: apply --plan-digest <lowercase-sha256> < consent.json");
    }
    return { planDigest: arguments_[1] };
}
function parseReconcileArguments(arguments_) {
    if (arguments_.length !== 2 || arguments_[0] !== "--transaction-id" || !/^hatch_[0-9a-f-]{36}$/u.test(arguments_[1] ?? "")) {
        throw new Error("Usage: reconcile --transaction-id <hatch-transaction-id>");
    }
    return arguments_[1];
}
async function readProcessStdin() {
    let source = "";
    for await (const chunk of process.stdin) {
        source += String(chunk);
        if (Buffer.byteLength(source, "utf8") > MAX_CONSENT_BYTES) {
            throw new Error("Native consent input exceeds the 64 KiB command bound.");
        }
    }
    return source;
}
