import { execFile } from 'node:child_process';
import { mkdir, readFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { promisify } from 'node:util';
import { parseV17GoldenGraphFixtureManifestJson } from "./V17GoldenGraphFixtureManifestJsonAdapter.js";
const execFileAsync = promisify(execFile);
/** Restores and validates a v17 golden graph-history fixture into an explicit repository. */
export async function restoreV17GoldenGraphFixture(options) {
    const manifestPath = requireNonEmptyString(options.manifestPath, 'manifestPath');
    const targetDirectory = requireNonEmptyString(options.targetDirectory, 'targetDirectory');
    const manifest = await readManifest(manifestPath);
    const repositoryPath = resolve(targetDirectory);
    const bundlePath = resolve(dirname(manifestPath), manifest.bundlePath);
    await mkdir(repositoryPath, { recursive: true });
    await runGit(repositoryPath, ['init', '-q']);
    for (const chain of manifest.writerChains) {
        await runGit(repositoryPath, ['fetch', '-q', bundlePath, `${chain.refName}:${chain.refName}`]);
    }
    const restoredRefs = await verifyRestoredRefs(repositoryPath, manifest);
    return Object.freeze({
        repositoryPath,
        manifest,
        restoredRefs,
    });
}
async function readManifest(path) {
    const raw = await readFile(path, 'utf8');
    return parseV17GoldenGraphFixtureManifestJson(raw);
}
function requireNonEmptyString(value, name) {
    if (typeof value !== 'string' || value.length === 0) {
        throw new Error(`${name} must be a non-empty string`);
    }
    return value;
}
async function verifyRestoredRefs(repositoryPath, manifest) {
    const restoredRefs = [];
    for (const chain of manifest.writerChains) {
        const head = await gitText(repositoryPath, ['rev-parse', '--verify', chain.refName]);
        if (head !== chain.expectedHead) {
            throw new Error(`Restored ref ${chain.refName} expected ${chain.expectedHead}, got ${head}`);
        }
        const patchCountText = await gitText(repositoryPath, ['rev-list', '--count', chain.refName]);
        const patchCount = Number(patchCountText);
        if (patchCount !== chain.patchCount) {
            throw new Error(`Restored ref ${chain.refName} expected ${chain.patchCount} patches, got ${patchCount}`);
        }
        restoredRefs.push(Object.freeze({
            refName: chain.refName,
            head,
            patchCount,
        }));
    }
    return Object.freeze(restoredRefs);
}
async function gitText(cwd, args) {
    const result = await runGit(cwd, args);
    return result.stdout.trim();
}
async function runGit(cwd, args) {
    return await execFileAsync('git', args, { cwd });
}
