"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 hetzner_provider_service_1 = require("../../../../src/modules/providers/services/hetzner-provider.service");
const cluster_entity_1 = require("../../../../src/modules/infrastructure/clusters/entities/cluster.entity");
const cli_cluster_repository_1 = require("../../lib/repositories/cli-cluster.repository");
const context_banner_1 = require("../../lib/context-banner");
class EnvStop extends core_1.Command {
    async run() {
        (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.succeed('Initialized');
            console.log(chalk_1.default.cyan('\n💤 Stopping Observability Cluster\n'));
            spinner = (0, ora_1.default)('Finding cluster...').start();
            const observabilityService = app.get(cli_observability_cluster_service_1.CliObservabilityClusterService);
            // Get 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(`Create one with: ${chalk_1.default.cyan('flui env create')}\n`);
                return;
            }
            if (!cluster.nodes || cluster.nodes.length === 0) {
                spinner.fail('No cluster nodes found');
                console.log(chalk_1.default.yellow('\n⚠️  Cluster has no nodes.\n'));
                return;
            }
            spinner.succeed(`Found cluster with ${cluster.nodes.length} node(s)`);
            // Get Hetzner provider (we need the concrete type for poweroff)
            const hetznerProvider = app.get(hetzner_provider_service_1.HetznerProviderService);
            // Check if all servers are already stopped
            let allStopped = true;
            const serverStates = [];
            spinner = (0, ora_1.default)('Checking server states...').start();
            for (const node of cluster.nodes) {
                try {
                    const serverDto = await hetznerProvider.getServerDetailsAsDto(node.providerResourceId);
                    if (serverDto) {
                        serverStates.push({
                            name: node.serverName,
                            id: node.providerResourceId,
                            status: serverDto.status,
                        });
                        if (serverDto.status !== 'off') {
                            allStopped = false;
                        }
                    }
                }
                catch {
                    spinner.warn(`Could not check status for ${node.serverName}`);
                }
            }
            spinner.succeed('Server states checked');
            if (allStopped) {
                console.log(chalk_1.default.yellow('\n⚠️  All cluster servers are already stopped.\n'));
                console.log(`   Current cost: ~${0.6 * cluster.nodes.length}€/month (storage only)`);
                // Update cluster status to STOPPED if not already
                if (cluster.status !== cluster_entity_1.ClusterStatus.STOPPED) {
                    spinner = (0, ora_1.default)('Updating cluster status...').start();
                    const clusterRepository = app.get(cli_cluster_repository_1.CliClusterRepository);
                    cluster.status = cluster_entity_1.ClusterStatus.STOPPED;
                    await clusterRepository.save(cluster);
                    spinner.succeed('Cluster status updated');
                }
                console.log(`\n   To restart them, run:`);
                console.log(`   ${chalk_1.default.cyan('flui env restart')}\n`);
                return;
            }
            // Show 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}`);
            console.log(`   ${chalk_1.default.bold('Nodes:')}  ${cluster.nodes.length}`);
            console.log(`   ${chalk_1.default.bold('Region:')} ${cluster.region}\n`);
            // Stop all running servers
            let stoppedCount = 0;
            for (const state of serverStates) {
                if (state.status === 'off') {
                    console.log(chalk_1.default.dim(`   ${state.name} - already stopped`));
                }
                else {
                    spinner = (0, ora_1.default)(`Powering off ${state.name}...`).start();
                    try {
                        await hetznerProvider.powerOffServer(state.id);
                        spinner.succeed(`${state.name} powered off`);
                        stoppedCount++;
                    }
                    catch (error) {
                        spinner.fail(`Failed to power off ${state.name}: ${error.message}`);
                    }
                }
            }
            if (stoppedCount > 0) {
                console.log(chalk_1.default.green(`\n✅ Successfully stopped ${stoppedCount} server(s)\n`));
                // Update cluster status to STOPPED
                spinner = (0, ora_1.default)('Updating cluster status...').start();
                const clusterRepository = app.get(cli_cluster_repository_1.CliClusterRepository);
                cluster.status = cluster_entity_1.ClusterStatus.STOPPED;
                await clusterRepository.save(cluster);
                spinner.succeed('Cluster status updated');
            }
            console.log(chalk_1.default.cyan('💰 Cost Savings:\n'));
            console.log(`   ${chalk_1.default.bold('Before:')} ~${7.5 * cluster.nodes.length}€/month (running)`);
            console.log(`   ${chalk_1.default.bold('After:')}  ~${0.6 * cluster.nodes.length}€/month (storage only)`);
            console.log(`   ${chalk_1.default.bold('Savings:')} ~92% (${(6.9 * cluster.nodes.length).toFixed(2)}€/month)\n`);
            console.log(chalk_1.default.cyan('📦 Data Persistence:\n'));
            console.log('   All data is preserved:');
            console.log('   ✓ PostgreSQL databases');
            console.log('   ✓ Redis data');
            console.log('   ✓ Prometheus metrics (last 7 days)');
            console.log('   ✓ Loki logs (last 7 days)');
            console.log('   ✓ Grafana dashboards and settings\n');
            console.log(chalk_1.default.cyan('🔄 Restart:\n'));
            console.log('   To start the servers again, run:');
            console.log(`   ${chalk_1.default.cyan('flui env restart')}`);
            console.log(`\n   Or check status with: ${chalk_1.default.cyan('flui env status')}\n`);
        }
        catch (error) {
            spinner.fail('Failed to stop environment');
            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)();
        }
    }
}
EnvStop.description = 'Shutdown observability cluster servers (saves costs while preserving data)';
EnvStop.examples = ['<%= config.bin %> <%= command.id %>'];
exports.default = EnvStop;
