import select from '@inquirer/select';
import { Command, Flags } from '@oclif/core';
import chalk from 'chalk';
import ora from 'ora';
import { loadConfig } from '../../deploy/domain/config.js';
import { initializeSheetsApi } from '../../sheets/domain/auth.js';
import { pushBoundedContext } from '../../sheets/sync/yaml-to-sheet.js';
export default class Push extends Command {
    static description = 'Push Aurora YAML schemas to Google Sheets.';
    static examples = [
        '<%= config.bin %> sheets push',
        '<%= config.bin %> sheets push --bc iam',
        '<%= config.bin %> sheets push --all',
        '<%= config.bin %> sheets push --bc iam --dry-run',
    ];
    static flags = {
        all: Flags.boolean({
            description: 'Push all bounded contexts',
            exclusive: ['bc'],
        }),
        bc: Flags.string({
            description: 'Bounded context name',
        }),
        config: Flags.string({
            char: 'c',
            default: './aurora.yaml',
            description: 'Path to aurora.yaml config file',
        }),
        'dry-run': Flags.boolean({
            description: 'Preview without making changes',
        }),
        verbose: Flags.boolean({
            char: 'v',
            description: 'Show detailed output',
        }),
    };
    async run() {
        const { flags } = await this.parse(Push);
        const config = loadConfig(flags.config);
        if (!config.sheets) {
            this.error('No "sheets" section found in aurora.yaml.\n' +
                'Add a sheets.bounded_contexts block to your config.');
        }
        const allNames = Object.keys(config.sheets.boundedContexts);
        if (allNames.length === 0) {
            this.error('No bounded contexts configured in sheets section.');
        }
        let boundedContexts;
        if (flags.all) {
            boundedContexts = allNames;
        }
        else if (flags.bc) {
            if (!config.sheets.boundedContexts[flags.bc]) {
                this.error(`Bounded context "${flags.bc}" not found.\nAvailable: ${allNames.join(', ')}`);
            }
            boundedContexts = [flags.bc];
        }
        else {
            const selected = await select({
                choices: allNames.map((name) => ({
                    description: config.sheets.boundedContexts[name].description,
                    name,
                    value: name,
                })),
                message: 'Select a bounded context to push:',
            });
            boundedContexts = [selected];
        }
        const spinner = ora();
        const sheetsApi = await this.initAuth(spinner);
        let hasErrors = false;
        for (const bc of boundedContexts) {
            spinner.start(`Pushing: ${bc}`);
            const bcConfig = config.sheets.boundedContexts[bc];
            // eslint-disable-next-line no-await-in-loop
            const result = await pushBoundedContext({
                allBcConfigs: config.sheets.boundedContexts,
                boundedContextName: bc,
                cliterPath: './cliter',
                sheetsApi,
                spreadsheetId: bcConfig.spreadsheetId,
            }, {
                dryRun: flags['dry-run'],
                verbose: flags.verbose,
            });
            if (result.success) {
                spinner.succeed(`Pushed: ${bc} (${result.modulesProcessed} modules)`);
            }
            else {
                spinner.fail(`Push failed: ${bc}`);
                hasErrors = true;
            }
            for (const msg of result.messages) {
                this.log(`  ${msg}`);
            }
        }
        if (hasErrors) {
            this.error('Some bounded contexts failed to push.');
        }
        this.log(chalk.green('\nPush completed successfully!'));
    }
    async initAuth(spinner) {
        spinner.start('Authenticating with Google Sheets...');
        try {
            const api = await initializeSheetsApi();
            spinner.succeed('Authenticated with Google Sheets');
            return api;
        }
        catch (error) {
            spinner.fail('Authentication failed');
            throw error;
        }
    }
}
