"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 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_ssh_service_1 = require("../../services/cli-ssh.service");
const context_banner_1 = require("../../lib/context-banner");
class EnvDiagCA extends core_1.Command {
    async run() {
        (0, context_banner_1.printContextBanner)();
        const spinner = (0, ora_1.default)('Connecting to cluster...').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);
            const cluster = await observabilityService.getObservabilityCluster();
            if (!this.assertClusterReady(cluster, spinner)) {
                return;
            }
            spinner.succeed('Connected to cluster');
            console.log(chalk_1.default.cyan('\n🔍 CA Diagnostic Report\n'));
            console.log(chalk_1.default.dim('─'.repeat(80)));
            this.checkLocalCaFiles();
            await this.checkKubernetesSecret(sshService, cluster.masterIpAddress, spinner);
            await this.checkApiPodEnvironment(sshService, cluster.masterIpAddress, spinner);
            await this.checkApiCaStatusEndpoint(sshService, cluster, spinner);
            this.printSummary();
            await (0, nest_app_1.closeNestApp)();
        }
        catch (error) {
            spinner.fail('Diagnostic failed');
            console.log(chalk_1.default.red(`\n❌ Error: ${error.message}\n`));
            await (0, nest_app_1.closeNestApp)();
            this.exit(1);
        }
    }
    assertClusterReady(cluster, spinner) {
        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 false;
        }
        if (!cluster.masterIpAddress) {
            spinner.fail('Master IP not available');
            console.log(chalk_1.default.red('\n❌ Master node does not have an IP address yet\n'));
            return false;
        }
        return true;
    }
    checkLocalCaFiles() {
        console.log(chalk_1.default.bold('\n1. CLI CA Files:'));
        const fs = require('node:fs');
        const path = require('node:path');
        const os = require('node:os');
        const caDir = path.join(os.homedir(), '.flui', 'ca');
        const caPrivateKeyPath = path.join(caDir, 'ca_key');
        const caPublicKeyPath = path.join(caDir, 'ca_key.pub');
        const hasPrivateKey = fs.existsSync(caPrivateKeyPath);
        const hasPublicKey = fs.existsSync(caPublicKeyPath);
        console.log(`   Private Key: ${hasPrivateKey ? chalk_1.default.green('✓ Found') : chalk_1.default.red('✗ Missing')} (${caPrivateKeyPath})`);
        console.log(`   Public Key:  ${hasPublicKey ? chalk_1.default.green('✓ Found') : chalk_1.default.red('✗ Missing')} (${caPublicKeyPath})`);
        if (hasPublicKey) {
            const publicKey = fs.readFileSync(caPublicKeyPath, 'utf-8').trim();
            console.log(chalk_1.default.dim(`   Preview: ${publicKey.substring(0, 50)}...`));
        }
    }
    async checkKubernetesSecret(sshService, masterIp, spinner) {
        console.log(chalk_1.default.bold('\n2. Kubernetes Secret (flui-secrets):'));
        spinner.start('Checking Kubernetes secret...');
        try {
            const secretCheckCmd = `kubectl get secret flui-secrets -n default -o jsonpath='{.data}' 2>&1`;
            const secretOutput = await sshService.sshExec(masterIp, secretCheckCmd);
            const hasPriv = secretOutput.includes('SSH_CA_PRIVATE_KEY');
            const hasPub = secretOutput.includes('SSH_CA_PUBLIC_KEY');
            spinner.succeed('Kubernetes secret checked');
            console.log(`   SSH_CA_PRIVATE_KEY: ${hasPriv ? chalk_1.default.green('✓ Present') : chalk_1.default.red('✗ Missing')}`);
            console.log(`   SSH_CA_PUBLIC_KEY:  ${hasPub ? chalk_1.default.green('✓ Present') : chalk_1.default.red('✗ Missing')}`);
            if (!hasPriv || !hasPub) {
                console.log(chalk_1.default.yellow('\n   ⚠️  CA keys missing from Kubernetes secret!'));
                console.log(chalk_1.default.dim('   This is required for the API to access SSH.'));
            }
        }
        catch (error) {
            spinner.fail('Failed to check Kubernetes secret');
            console.log(chalk_1.default.red(`   Error: ${error.message}`));
        }
    }
    async checkApiPodEnvironment(sshService, masterIp, spinner) {
        console.log(chalk_1.default.bold('\n3. API Pod Environment Variables:'));
        spinner.start('Checking API pod...');
        try {
            const getPodCmd = `kubectl get pods -n default -l app=flui-api -o jsonpath='{.items[0].metadata.name}' 2>&1`;
            const podName = (await sshService.sshExec(masterIp, getPodCmd)).trim();
            if (!podName ||
                podName.includes('error') ||
                podName.includes('No resources')) {
                spinner.warn('API pod not found');
                console.log(chalk_1.default.yellow('   API pod not found or not running'));
                return;
            }
            const checkEnvCmd = `kubectl exec -n default ${podName} -- env | grep SSH_CA 2>&1 || echo "NOT_FOUND"`;
            const envOutput = await sshService.sshExec(masterIp, checkEnvCmd);
            spinner.succeed(`API pod found: ${podName}`);
            this.reportApiPodEnv(envOutput);
        }
        catch (error) {
            spinner.fail('Failed to check API pod');
            console.log(chalk_1.default.red(`   Error: ${error.message}`));
        }
    }
    reportApiPodEnv(envOutput) {
        const hasPriv = envOutput.includes('SSH_CA_PRIVATE_KEY=');
        const hasPub = envOutput.includes('SSH_CA_PUBLIC_KEY=');
        console.log(`   SSH_CA_PRIVATE_KEY env: ${hasPriv ? chalk_1.default.green('✓ Set') : chalk_1.default.red('✗ Not Set')}`);
        console.log(`   SSH_CA_PUBLIC_KEY env:  ${hasPub ? chalk_1.default.green('✓ Set') : chalk_1.default.red('✗ Not Set')}`);
        if (hasPub) {
            const pubKeyMatch = /SSH_CA_PUBLIC_KEY=(\S+)/.exec(envOutput);
            if (pubKeyMatch) {
                console.log(chalk_1.default.dim(`   Preview: ${pubKeyMatch[1].substring(0, 50)}...`));
            }
        }
        if (!hasPriv || !hasPub) {
            console.log(chalk_1.default.yellow('\n   ⚠️  CA environment variables not set in API pod!'));
            console.log(chalk_1.default.dim('   The API pod may need to be restarted to pick up the secret.'));
            console.log(chalk_1.default.dim('   Restart command: kubectl rollout restart deployment flui-api -n default'));
        }
    }
    async checkApiCaStatusEndpoint(sshService, cluster, spinner) {
        console.log(chalk_1.default.bold('\n4. API CA Status Endpoint:'));
        spinner.start('Checking API CA status...');
        try {
            const baseDomain = (0, nip_base_domain_util_1.buildNipBaseDomain)(cluster.masterIpAddress, cluster.nipHostnameToken);
            const apiUrl = `https://api.${baseDomain}/api/v1/access/ca/status`;
            const apiResponse = await sshService.sshExec(cluster.masterIpAddress, `curl -s -f ${apiUrl} 2>&1`);
            this.reportApiCaResponse(apiResponse, spinner);
        }
        catch (error) {
            spinner.fail('Failed to check API CA status');
            console.log(chalk_1.default.red(`   Error: ${error.message}`));
        }
    }
    reportApiCaResponse(apiResponse, spinner) {
        if (apiResponse.includes('"accessible":true')) {
            spinner.succeed('API can access CA');
            console.log(chalk_1.default.green('   ✓ API reports CA is accessible'));
            try {
                const j = JSON.parse(apiResponse);
                console.log(chalk_1.default.dim(`   Source: ${j.source || 'unknown'}`));
                console.log(chalk_1.default.dim(`   Has Private Key: ${j.hasPrivateKey ? 'Yes' : 'No'}`));
                console.log(chalk_1.default.dim(`   Has Public Key: ${j.hasPublicKey ? 'Yes' : 'No'}`));
            }
            catch {
                /* */
            }
        }
        else if (apiResponse.includes('404')) {
            spinner.warn('API CA status endpoint not available');
            console.log(chalk_1.default.yellow('   ⚠️  The /access/ca/status endpoint is not available'));
            console.log(chalk_1.default.dim('   This endpoint may not exist in the current API version.'));
        }
        else {
            spinner.fail('API cannot access CA');
            console.log(chalk_1.default.red('   ✗ API reports CA is not accessible'));
            console.log(chalk_1.default.dim(`   Response: ${apiResponse.substring(0, 200)}`));
        }
    }
    printSummary() {
        console.log(chalk_1.default.dim('\n' + '─'.repeat(80)));
        console.log(chalk_1.default.bold('\n📋 Summary & Recommendations:\n'));
        console.log(chalk_1.default.dim('If CA keys are missing from the Kubernetes secret:'));
        console.log(chalk_1.default.cyan('   1. The cluster creation may have failed to patch the secret'));
        console.log(chalk_1.default.cyan('   2. Re-run cluster creation or manually patch the secret'));
        console.log(chalk_1.default.dim('\nIf secret has keys but API pod environment does not:'));
        console.log(chalk_1.default.cyan('   1. Restart the API pod to pick up the secret:'));
        console.log(chalk_1.default.cyan('      kubectl rollout restart deployment flui-api -n default'));
        console.log(chalk_1.default.dim('\nIf environment is set but API still cannot access CA:'));
        console.log(chalk_1.default.cyan('   1. Check API logs for errors:'));
        console.log(chalk_1.default.cyan('      kubectl logs -n default -l app=flui-api --tail=50'));
        console.log('');
    }
}
EnvDiagCA.description = 'Diagnose CA configuration on the cluster';
EnvDiagCA.examples = ['<%= config.bin %> <%= command.id %>'];
exports.default = EnvDiagCA;
