import select from '@inquirer/select';
import { Command } from '@oclif/core';
import chalk from 'chalk';
import { execFileSync } from 'node:child_process';
import path from 'node:path';
import { acceptOrigin, ignoreOrigin, rejectOrigin, } from '../../origin/domain/actions.js';
import { discoverOrigins, } from '../../origin/domain/origin-file.js';
export default class OriginReview extends Command {
    static description = 'Interactive walk-through of pending `.origin` files (inquirer + VS Code diff).';
    static examples = ['<%= config.bin %> origin review'];
    async run() {
        let remaining = discoverOrigins();
        if (remaining.length === 0) {
            this.log('No origin files to review.');
            return;
        }
        while (remaining.length > 0) {
            // eslint-disable-next-line no-await-in-loop
            const selected = await selectFile(remaining);
            if (!selected)
                return;
            openDiffInVsCode(selected);
            // eslint-disable-next-line no-await-in-loop
            const action = await selectAction();
            switch (action) {
                case 'accept': {
                    const result = acceptOrigin(selected.current);
                    this.log(`${chalk.green('[ACCEPTED]')} ${result.path}${result.status === 'noop' ? chalk.dim(' (noop)') : ''}`);
                    break;
                }
                case 'finish': {
                    return;
                }
                case 'go-back': {
                    // Loop again to refresh the file picker.
                    break;
                }
                case 'ignore': {
                    const result = ignoreOrigin(selected.current);
                    this.log(`${chalk.cyan('[IGNORED]')} ${result.path}${result.status === 'noop' ? chalk.dim(' (noop)') : ''}`);
                    break;
                }
                case 'reject': {
                    const result = rejectOrigin(selected.current);
                    this.log(`${chalk.yellow('[REJECTED]')} ${result.path}${result.status === 'noop' ? chalk.dim(' (noop)') : ''}`);
                    break;
                }
            }
            // Refresh the list — the action just removed an entry (or kept it on
            // 'go-back'). Re-scanning is cheap and avoids manual list bookkeeping.
            remaining = discoverOrigins();
        }
        this.log('All origin files processed.');
    }
}
async function selectFile(entries) {
    if (entries.length === 0)
        return undefined;
    return select({
        choices: entries.map((entry) => ({ name: entry.current, value: entry })),
        message: 'Select file to review:',
    });
}
async function selectAction() {
    return select({
        choices: [
            { name: 'Reject (keep my current file as-is)', value: 'reject' },
            { name: 'Accept (adopt the codegen proposal)', value: 'accept' },
            {
                name: 'Ignore (keep mine + mark file as ignored on future regens)',
                value: 'ignore',
            },
            { name: 'Go back to file selection', value: 'go-back' },
            { name: 'Finish review', value: 'finish' },
        ],
        message: 'Select an action:',
    });
}
function openDiffInVsCode(entry) {
    const absCurrent = path.resolve(entry.current);
    const absOrigin = path.resolve(entry.origin);
    try {
        // Order matters: `code --diff <left> <right>` puts the first path on the
        // left (source of changes) and the second on the right (editable
        // destination). Reviewing means importing pieces of the codegen proposal
        // (`.origin`) into the user's file, so `.origin` goes left and the
        // current file goes right — that way the inline arrows move chunks from
        // proposal → current file, not the other way around.
        execFileSync('code', ['--diff', absOrigin, absCurrent], {
            stdio: 'ignore',
        });
    }
    catch {
        // VS Code not on PATH — silently continue. The user can still pick an
        // action without the side-by-side diff.
    }
}
