"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const reconciliation_service_1 = require("../lib/services/reconciliation.service");
const config_storage_1 = require("../lib/config-storage");
const nip_base_domain_util_1 = require("../lib/nip-base-domain.util");
const cli_cluster_repository_1 = require("../lib/repositories/cli-cluster.repository");
class Reconcile extends core_1.Command {
    async run() {
        const { flags } = await this.parse(Reconcile);
        let spinner = (0, ora_1.default)('Initializing reconciliation...').start();
        try {
            const configStorage = new config_storage_1.ConfigStorage();
            let apiUrl = flags['api-url'] || configStorage.getApiUrl();
            if (!flags['api-url'] && !apiUrl) {
                const clusterRepo = new cli_cluster_repository_1.CliClusterRepository();
                const cluster = await clusterRepo.findOne({
                    where: { metadata: { isObservabilityCluster: true } },
                });
                if (cluster?.masterIpAddress) {
                    const base = (0, nip_base_domain_util_1.buildNipBaseDomain)(cluster.masterIpAddress, cluster.nipHostnameToken);
                    apiUrl = `https://api.${base}/api/v1`;
                    configStorage.saveApiUrl(apiUrl);
                    spinner.text = `Auto-detected API URL: ${apiUrl}`;
                }
            }
            if (!apiUrl) {
                spinner.fail('API URL is not configured for this context');
                console.log(chalk_1.default.yellow('\nRun `flui env create` to provision a cluster, or set it manually:\n  flui config set api-url https://api.example.com/api/v1\n'));
                this.exit(1);
            }
            spinner.text = 'Connecting to API...';
            // Parse reconciliation types
            const types = flags.type.map((t) => t.toLowerCase());
            // Dry run mode
            if (flags['dry-run']) {
                spinner.succeed('Connected to API');
                console.log(chalk_1.default.cyan('\n🔍 Dry Run Mode - No changes will be made\n'));
                console.log(chalk_1.default.dim(`   API URL: ${apiUrl}`));
                console.log(chalk_1.default.dim(`   Types: ${types.includes(reconciliation_service_1.ReconciliationType.ALL) ? 'all (dns)' : types.join(', ')}`));
                console.log('');
            }
            spinner.text = 'Starting reconciliation...';
            // Execute reconciliation
            const reconciliationService = new reconciliation_service_1.ReconciliationService(apiUrl);
            const { results, allSuccess } = await reconciliationService.reconcile({
                types,
                dryRun: flags['dry-run'],
                apiUrl,
            });
            spinner.stop();
            // Save reconciliation state to cluster metadata (skip for dry-run)
            if (!flags['dry-run']) {
                try {
                    const clusterRepo = new cli_cluster_repository_1.CliClusterRepository();
                    const cluster = await clusterRepo.findOne({
                        where: { metadata: { isObservabilityCluster: true } },
                    });
                    if (cluster) {
                        cluster.metadata = {
                            ...cluster.metadata,
                            reconciliation: {
                                status: allSuccess ? 'completed' : 'partial',
                                completedAt: new Date().toISOString(),
                                results: results.map((r) => ({
                                    type: r.type,
                                    success: r.success,
                                    message: r.message,
                                })),
                            },
                        };
                        await clusterRepo.save(cluster);
                    }
                }
                catch {
                    // Ignore metadata save errors
                }
            }
            // Display results
            this.displayResults(results, flags['dry-run']);
            // Exit with appropriate code
            if (allSuccess) {
                console.log(chalk_1.default.green(`\n✓ All reconciliations ${flags['dry-run'] ? 'would complete' : 'completed'} successfully!\n`));
            }
            else {
                console.log(chalk_1.default.yellow(`\n⚠ Some reconciliations ${flags['dry-run'] ? 'would fail' : 'failed'}. See details above.\n`));
                this.exit(1);
            }
        }
        catch (error) {
            spinner.fail('Reconciliation failed');
            console.log(chalk_1.default.red(`\n✗ Error: ${error.message}\n`));
            if (error.stack) {
                console.log(chalk_1.default.dim(error.stack));
            }
            this.exit(1);
        }
    }
    /**
     * Display reconciliation results
     */
    displayResults(results, dryRun) {
        console.log(chalk_1.default.bold(`\n${dryRun ? '🔍 Reconciliation Preview' : '📊 Reconciliation Results'}`));
        console.log(chalk_1.default.dim('─'.repeat(60)));
        for (const result of results) {
            const icon = result.success ? '✓' : '✗';
            const color = result.success ? chalk_1.default.green : chalk_1.default.red;
            const typeLabel = this.formatTypeLabel(result.type);
            console.log(color(`\n${icon} ${typeLabel}`));
            console.log(chalk_1.default.dim(`   ${result.message}`));
            if (result.details) {
                console.log(chalk_1.default.dim('   Details:'));
                if (Array.isArray(result.details)) {
                    for (const detail of result.details) {
                        const detailIcon = detail.success ? '  ✓' : '  ✗';
                        const detailColor = detail.success ? chalk_1.default.green : chalk_1.default.yellow;
                        console.log(detailColor(`   ${detailIcon} ${detail.message}`));
                    }
                }
                else {
                    for (const [key, value] of Object.entries(result.details)) {
                        console.log(chalk_1.default.dim(`     ${key}: ${value}`));
                    }
                }
            }
            if (result.error && !result.success) {
                console.log(chalk_1.default.red(`   Error: ${result.error}`));
            }
        }
        console.log(chalk_1.default.dim('\n' + '─'.repeat(60)));
    }
    /**
     * Format reconciliation type label
     */
    formatTypeLabel(type) {
        const labels = {
            [reconciliation_service_1.ReconciliationType.DNS]: 'DNS Configuration',
            [reconciliation_service_1.ReconciliationType.ALL]: 'All Resources',
        };
        return labels[type] || type;
    }
}
Reconcile.description = 'Reconcile CLI state with API (DNS configuration)';
Reconcile.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --type dns',
    '<%= config.bin %> <%= command.id %> --dry-run',
];
Reconcile.flags = {
    type: core_1.Flags.string({
        char: 't',
        description: 'Reconciliation type(s) to execute (default: all)',
        options: ['dns', 'all'],
        multiple: true,
        default: ['all'],
    }),
    'api-url': core_1.Flags.string({
        description: 'Flui API URL (default: from config or http://localhost:3000/api/v1)',
        required: false,
    }),
    'dry-run': core_1.Flags.boolean({
        description: 'Show what would be reconciled without making changes',
        default: false,
    }),
};
exports.default = Reconcile;
