"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 nest_app_1 = require("../../lib/nest-app");
const cli_observability_cluster_service_1 = require("../../services/cli-observability-cluster.service");
const cli_ssh_service_1 = require("../../services/cli-ssh.service");
const context_banner_1 = require("../../lib/context-banner");
class EnvInspect extends core_1.Command {
    async run() {
        const { flags } = await this.parse(EnvInspect);
        (0, context_banner_1.printContextBanner)();
        let spinner = (0, ora_1.default)('Loading cluster information...').start();
        try {
            const app = await (0, nest_app_1.getNestApp)();
            const observabilityService = app.get(cli_observability_cluster_service_1.CliObservabilityClusterService);
            const sshService = app.get(cli_ssh_service_1.CliSshService);
            // Get 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');
            // Get node IP
            let nodeIp;
            let nodeName;
            if (flags.node === 'master') {
                nodeIp = cluster.masterIpAddress;
                nodeName = 'Master Node';
            }
            else {
                // Find worker node
                const workerIndex = Number.parseInt(flags.node.replace('worker-', ''));
                if (Number.isNaN(workerIndex)) {
                    console.log(chalk_1.default.red(`\n❌ Invalid node name: ${flags.node}\n`));
                    console.log(chalk_1.default.dim('Valid options: master, worker-1, worker-2, etc.\n'));
                    return;
                }
                const workerNode = cluster.nodes?.find((n) => n.nodeType === 'worker' &&
                    n.serverName.includes(`worker-${workerIndex}`));
                if (!workerNode) {
                    console.log(chalk_1.default.red(`\n❌ Worker node ${flags.node} not found\n`));
                    return;
                }
                nodeIp = workerNode.ipAddress;
                nodeName = `Worker Node ${workerIndex}`;
            }
            if (!nodeIp) {
                console.log(chalk_1.default.red(`\n❌ Node ${flags.node} does not have an IP address yet\n`));
                console.log(chalk_1.default.dim('The node may still be provisioning. Check status with:'));
                console.log(`   ${chalk_1.default.cyan('flui env status')}\n`);
                return;
            }
            // Determine log file path
            const logPaths = {
                'cloud-init': '/var/log/cloud-init.log',
                'cloud-init-output': '/var/log/cloud-init-output.log',
                k3s: '/var/log/k3s.log',
                syslog: '/var/log/syslog',
            };
            const logPath = logPaths[flags.log];
            // Handle follow mode vs one-time fetch
            if (flags.follow) {
                // FOLLOW MODE: Stream logs in real-time
                spinner.succeed(`Cluster found - streaming logs from ${nodeName}`);
                // Display header
                console.log(chalk_1.default.cyan(`\n📋 ${nodeName} - ${flags.log} (following)\n`));
                console.log(chalk_1.default.dim(`   Node: ${flags.node} (${nodeIp})`));
                console.log(chalk_1.default.dim(`   Log: ${logPath}`));
                console.log(chalk_1.default.dim(`   Press Ctrl+C to stop\n`));
                console.log(chalk_1.default.dim('─'.repeat(80)));
                let cleanup = null;
                // Setup signal handler for graceful exit
                const exitHandler = () => {
                    console.log(chalk_1.default.dim('\n\n─'.repeat(80)));
                    console.log(chalk_1.default.yellow('\n⏹  Stopping log stream...\n'));
                    if (cleanup) {
                        cleanup();
                    }
                    process.exit(0);
                };
                process.on('SIGINT', exitHandler);
                process.on('SIGTERM', exitHandler);
                try {
                    // Start streaming logs
                    const stream = await sshService.streamRemoteLog(nodeIp, logPath);
                    cleanup = stream.cleanup;
                    // Keep process alive while streaming
                    await new Promise(() => {
                        // This promise never resolves - keeps process running until SIGINT
                    });
                }
                catch (error) {
                    console.log(chalk_1.default.red('\n❌ SSH Stream Error:\n'));
                    console.log(`   ${error.message}\n`);
                    console.log(chalk_1.default.yellow('Troubleshooting:'));
                    console.log('   - Ensure the node is fully provisioned');
                    console.log('   - Check firewall rules allow SSH');
                    console.log('   - Verify SSH keys are correctly configured\n');
                    this.exit(1);
                }
            }
            else {
                // ONE-TIME MODE: Fetch logs once (original behavior)
                spinner = (0, ora_1.default)(`Fetching ${flags.log} logs from ${nodeName}...`).start();
                try {
                    const logs = await sshService.tailRemoteLog(nodeIp, logPath, flags.tail);
                    spinner.succeed(`Logs fetched from ${nodeName}`);
                    // Display logs
                    console.log(chalk_1.default.cyan(`\n📋 ${nodeName} - ${flags.log}\n`));
                    console.log(chalk_1.default.dim(`   Node: ${flags.node} (${nodeIp})`));
                    console.log(chalk_1.default.dim(`   Log: ${logPath}`));
                    console.log(chalk_1.default.dim(`   Lines: ${flags.tail}\n`));
                    console.log(chalk_1.default.dim('─'.repeat(80)));
                    console.log(logs);
                    console.log(chalk_1.default.dim('─'.repeat(80)));
                    console.log('');
                    // Show SSH hint
                    console.log(chalk_1.default.dim('💡 For interactive SSH access:'));
                    const sshCmd = chalk_1.default.cyan(`flui ssh ${flags.node}`);
                    console.log(`   ${sshCmd}\n`);
                    console.log(chalk_1.default.dim('💡 For real-time log streaming:'));
                    const followCmd = chalk_1.default.cyan('flui env inspect --follow');
                    console.log(`   ${followCmd}\n`);
                }
                catch (error) {
                    spinner.fail('Failed to fetch logs');
                    console.log(chalk_1.default.red('\n❌ SSH Error:\n'));
                    console.log(`   ${error.message}\n`);
                    console.log(chalk_1.default.yellow('Troubleshooting:'));
                    console.log('   - Ensure the node is fully provisioned');
                    console.log('   - Check firewall rules allow SSH');
                    console.log('   - Verify SSH keys are correctly configured\n');
                }
            }
        }
        catch (error) {
            spinner.fail('Failed to inspect cluster');
            console.log(chalk_1.default.red('\n❌ Error:\n'));
            if (error instanceof Error) {
                console.log(`   ${error.message}\n`);
            }
            else {
                console.log(`   ${String(error)}\n`);
            }
            this.exit(1);
        }
        finally {
            await (0, nest_app_1.closeNestApp)();
        }
    }
}
EnvInspect.description = 'Inspect remote cluster logs via SSH';
EnvInspect.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --node master',
    '<%= config.bin %> <%= command.id %> --node worker-1 --log cloud-init',
    '<%= config.bin %> <%= command.id %> --follow',
    '<%= config.bin %> <%= command.id %> -f --log k3s',
];
EnvInspect.flags = {
    node: core_1.Flags.string({
        char: 'n',
        description: 'Node to inspect (master, worker-1, worker-2, etc.)',
        default: 'master',
    }),
    log: core_1.Flags.string({
        char: 'l',
        description: 'Log file to view',
        options: ['cloud-init', 'cloud-init-output', 'k3s', 'syslog'],
        default: 'cloud-init-output',
    }),
    tail: core_1.Flags.integer({
        char: 't',
        description: 'Number of lines to show',
        default: 100,
    }),
    follow: core_1.Flags.boolean({
        char: 'f',
        description: 'Follow log output in real-time (like tail -f)',
        default: false,
    }),
};
exports.default = EnvInspect;
