import { intro, outro, spinner, note, confirm, isCancel } from '@clack/prompts';
import pc from 'picocolors';
import { readdir, readFile } from 'node:fs/promises';
import { resolve, join } from 'node:path';
import { createPr } from '@ew53/seo-patch';
import { loadConfig } from '../lib/config-loader.js';
export async function runPr(opts = {}) {
    console.log();
    intro(pc.bgCyan(pc.black(' seo-toolkit pr ')));
    const config = await loadConfig();
    const patchDir = resolve(process.cwd(), config.output.patches);
    // Discover patches.
    let patchFilenames;
    try {
        patchFilenames = (await readdir(patchDir)).filter((f) => f.endsWith('.diff'));
    }
    catch {
        throw new Error(`No patches directory at ${patchDir}. Run \`seo-toolkit apply\` first.`);
    }
    if (patchFilenames.length === 0) {
        note(`No .diff files in ${pc.cyan(config.output.patches)}. Run ${pc.cyan('seo-toolkit apply')} first.`, 'Nothing to push');
        outro('Done');
        return;
    }
    // We need PatchFile objects but the patches directory only has the .diff content.
    // Rebuild minimal PatchFile records from the diff filenames + load suggestions for metadata.
    const suggestions = JSON.parse(await readFile(resolve(process.cwd(), config.output.suggestions), 'utf8'));
    const accepted = suggestions.changes.filter((c) => c.status === 'accepted');
    const patches = patchFilenames.map((name) => {
        // Best-effort reconstruction.
        const change = accepted.find((c) => name.includes(c.issueId)) ?? accepted[0];
        return {
            path: join(config.output.patches, name),
            change,
            target: { file: 'unknown', line: 0, needle: '', replacement: '' },
            diff: '',
        };
    });
    const branch = opts.branch ?? `seo/auto-fixes-${shortDate()}`;
    note(`Branch: ${pc.cyan(branch)}\n` +
        `Patches: ${patches.length}\n` +
        `Mode: ${opts.dryRun ? pc.yellow('DRY RUN') : pc.green('LIVE')}`, 'Plan');
    if (!opts.dryRun) {
        const ok = await confirm({
            message: 'Push branch + open PR?',
            initialValue: true,
        });
        if (isCancel(ok) || !ok) {
            outro('Cancelled.');
            return;
        }
    }
    const s = spinner();
    s.start(opts.dryRun ? 'Planning...' : 'Creating branch + PR...');
    try {
        const result = await createPr({
            projectRoot: process.cwd(),
            patches,
            branch,
            dryRun: opts.dryRun,
        });
        s.stop(opts.dryRun ? 'Dry run complete' : 'PR created');
        if (opts.dryRun) {
            note(result.commands.map((c) => `${pc.dim('$')} ${c}`).join('\n'), 'Would run');
        }
        else if (result.prUrl) {
            note(`${pc.green('✓')} ${pc.cyan(result.prUrl)}`, 'PR');
        }
    }
    catch (err) {
        s.stop('Failed');
        throw err;
    }
    outro(pc.green('Done.'));
}
function shortDate() {
    const d = new Date();
    return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
}
//# sourceMappingURL=pr.js.map