"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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 nest_app_1 = require("../../lib/nest-app");
const nip_base_domain_util_1 = require("../../lib/nip-base-domain.util");
const cli_observability_cluster_service_1 = require("../../services/cli-observability-cluster.service");
const cli_cluster_repository_1 = require("../../lib/repositories/cli-cluster.repository");
const cli_operation_repository_1 = require("../../lib/repositories/cli-operation.repository");
const cluster_entity_1 = require("../../../../src/modules/infrastructure/clusters/entities/cluster.entity");
const infrastructure_operations_entity_1 = require("../../../../src/modules/infrastructure/servers/entities/infrastructure-operations.entity");
const readline = __importStar(require("node:readline"));
const context_banner_1 = require("../../lib/context-banner");
class EnvForceReady extends core_1.Command {
    async run() {
        const { flags } = await this.parse(EnvForceReady);
        (0, context_banner_1.printContextBanner)();
        let spinner = (0, ora_1.default)('Initializing...').start();
        try {
            // Bootstrap NestJS and get services
            const app = await (0, nest_app_1.getNestApp)();
            spinner.stop();
            console.log(chalk_1.default.yellow('\n⚠️  Force Cluster Status to READY\n'));
            spinner = (0, ora_1.default)('Loading cluster...').start();
            const observabilityService = app.get(cli_observability_cluster_service_1.CliObservabilityClusterService);
            const clusterRepository = app.get(cli_cluster_repository_1.CliClusterRepository);
            const operationRepository = app.get(cli_operation_repository_1.CliOperationRepository);
            // Find observability cluster
            const cluster = await observabilityService.getObservabilityCluster();
            if (!cluster) {
                spinner.fail('No observability cluster found');
                console.log(chalk_1.default.yellow('\n⚠️  No observability cluster exists.\n'));
                console.log(chalk_1.default.dim('Create one with:'));
                console.log(`   ${chalk_1.default.cyan('flui env create')}\n`);
                return;
            }
            spinner.succeed('Cluster found');
            // Verify cluster is in ERROR or CREATING state
            const allowedStates = [cluster_entity_1.ClusterStatus.ERROR, cluster_entity_1.ClusterStatus.CREATING];
            if (!allowedStates.includes(cluster.status)) {
                spinner.fail(`Cluster is not in ERROR or CREATING state (current: ${cluster.status})`);
                console.log(chalk_1.default.yellow(`\n⚠️  This command only works on clusters in ERROR or CREATING state.\n`));
                console.log(chalk_1.default.dim(`   Current status: ${cluster.status}`));
                console.log(chalk_1.default.dim(`\nCheck cluster status with:`));
                console.log(`   ${chalk_1.default.cyan('flui env status')}\n`);
                return;
            }
            // Display cluster info
            console.log(chalk_1.default.cyan('\n📋 Cluster Information:\n'));
            console.log(`   ${chalk_1.default.bold('Name:')}       ${cluster.name}`);
            console.log(`   ${chalk_1.default.bold('ID:')}         ${cluster.id}`);
            const statusColor = cluster.status === cluster_entity_1.ClusterStatus.ERROR ? chalk_1.default.red : chalk_1.default.yellow;
            console.log(`   ${chalk_1.default.bold('Status:')}     ${statusColor(cluster.status)}`);
            console.log(`   ${chalk_1.default.bold('Master IP:')}  ${cluster.masterIpAddress}`);
            console.log(`   ${chalk_1.default.bold('Nodes:')}      ${cluster.nodeCount}`);
            // Health checks (unless skipped)
            let healthStatus = null;
            if (!flags['skip-health-checks']) {
                console.log(chalk_1.default.cyan('\n🔍 Checking cluster health...\n'));
                spinner = (0, ora_1.default)('Checking observability services...').start();
                try {
                    healthStatus = await observabilityService.checkObservabilityServices(cluster.masterIpAddress, cluster.nipHostnameToken);
                    spinner.succeed('Health checks completed');
                    // Display health status
                    console.log(chalk_1.default.cyan('\n📊 Service Health Status:\n'));
                    console.log(`   ${chalk_1.default.bold('Prometheus:')}  ${healthStatus.prometheus ? chalk_1.default.green('✅ Running') : chalk_1.default.red('❌ Down')}`);
                    console.log(`   ${chalk_1.default.bold('Grafana:')}     ${healthStatus.grafana ? chalk_1.default.green('✅ Running') : chalk_1.default.red('❌ Down')}`);
                    console.log(`   ${chalk_1.default.bold('Loki:')}        ${healthStatus.loki ? chalk_1.default.green('✅ Running') : chalk_1.default.red('❌ Down')}`);
                    console.log(`   ${chalk_1.default.bold('PostgreSQL:')}  ${healthStatus.postgres ? chalk_1.default.green('✅ Running') : chalk_1.default.red('❌ Down')}`);
                    console.log(`   ${chalk_1.default.bold('Redis:')}       ${healthStatus.redis ? chalk_1.default.green('✅ Running') : chalk_1.default.red('❌ Down')}`);
                    const allHealthy = healthStatus.prometheus &&
                        healthStatus.grafana &&
                        healthStatus.loki &&
                        healthStatus.postgres &&
                        healthStatus.redis;
                    if (!allHealthy) {
                        console.log(chalk_1.default.yellow('\n⚠️  Some services are not responding. Proceed with caution.'));
                    }
                }
                catch (error) {
                    spinner.warn('Health checks failed');
                    console.log(chalk_1.default.yellow(`\n⚠️  Could not perform health checks: ${error instanceof Error ? error.message : String(error)}`));
                    console.log(chalk_1.default.yellow('   You can use --skip-health-checks to bypass this check.\n'));
                    return;
                }
            }
            else {
                console.log(chalk_1.default.yellow('\n⚠️  Health checks skipped (--skip-health-checks)\n'));
            }
            // Confirmation prompt
            console.log(chalk_1.default.yellow(`\n⚠️  This will change the cluster status from ${cluster.status} to READY.\n`));
            if (!flags.force) {
                const rl = readline.createInterface({
                    input: process.stdin,
                    output: process.stdout,
                });
                const answer = await new Promise((resolve) => {
                    rl.question(chalk_1.default.yellow('Force cluster status to READY? (yes/no): '), (ans) => {
                        rl.close();
                        resolve(ans);
                    });
                });
                if (answer.toLowerCase() !== 'yes') {
                    console.log(chalk_1.default.green('\n✅ Operation cancelled\n'));
                    return;
                }
            }
            // Update cluster status
            spinner = (0, ora_1.default)('Updating cluster status...').start();
            cluster.status = cluster_entity_1.ClusterStatus.READY;
            await clusterRepository.save(cluster);
            spinner.succeed('Cluster status updated to READY');
            // Find and update associated failed operation (if exists)
            spinner = (0, ora_1.default)('Updating operation status...').start();
            const operations = await operationRepository.find({
                where: { resourceId: cluster.id },
            });
            const pendingOperation = operations.find((op) => op.status === infrastructure_operations_entity_1.OperationStatus.FAILED ||
                op.status === infrastructure_operations_entity_1.OperationStatus.IN_PROGRESS ||
                op.status === infrastructure_operations_entity_1.OperationStatus.PENDING);
            if (pendingOperation) {
                pendingOperation.status = infrastructure_operations_entity_1.OperationStatus.COMPLETED;
                pendingOperation.currentStepIndex = pendingOperation.totalSteps;
                pendingOperation.metadata = {
                    ...pendingOperation.metadata,
                    forcedReady: true,
                    forcedAt: new Date().toISOString(),
                    forcedReason: 'Manual override via env:force-ready command',
                };
                await operationRepository.save(pendingOperation);
                spinner.succeed('Operation status updated to COMPLETED');
            }
            else {
                spinner.info('No pending operation found to update');
            }
            // Success message
            console.log(chalk_1.default.green('\n✅ Cluster Status Successfully Updated\n'));
            console.log(chalk_1.default.dim(`   Cluster is now marked as ${chalk_1.default.green('READY')}`));
            console.log(chalk_1.default.dim('   You can verify with:'));
            console.log(`   ${chalk_1.default.cyan('flui env status')}\n`);
            // Show access info
            console.log(chalk_1.default.cyan('📌 Access Information:\n'));
            const baseDomain = (0, nip_base_domain_util_1.buildNipBaseDomain)(cluster.masterIpAddress, cluster.nipHostnameToken);
            console.log(`   ${chalk_1.default.bold('Flui Web:')}  https://app.${baseDomain}`);
            console.log(`   ${chalk_1.default.bold('Flui API:')}  https://api.${baseDomain}`);
            console.log('');
        }
        catch (error) {
            spinner.fail('Failed to force cluster status');
            console.log(chalk_1.default.red('\n❌ Error:\n'));
            if (error instanceof Error) {
                console.log(`   ${error.message}\n`);
                if (error.stack) {
                    console.log(chalk_1.default.dim('Stack trace:'));
                    console.log(chalk_1.default.dim(error.stack));
                }
            }
            else {
                console.log(`   ${String(error)}\n`);
            }
            this.exit(1);
        }
        finally {
            await (0, nest_app_1.closeNestApp)();
        }
    }
}
EnvForceReady.description = 'Force observability cluster status to READY (use when cluster is working but stuck in ERROR or CREATING state)';
EnvForceReady.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --force',
    '<%= config.bin %> <%= command.id %> --skip-health-checks',
];
EnvForceReady.flags = {
    force: core_1.Flags.boolean({
        char: 'f',
        description: 'Skip confirmation prompt',
        default: false,
    }),
    'skip-health-checks': core_1.Flags.boolean({
        description: 'Skip health validation checks (use with caution)',
        default: false,
    }),
};
exports.default = EnvForceReady;
