"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 cli_node_service_1 = require("../../lib/services/cli-node.service");
const resolve_cluster_1 = require("../../lib/resolve-cluster");
const POLL_INTERVAL_MS = 5000;
const MAX_WAIT_MS = 600_000; // 10 min
class NodeAdd extends core_1.Command {
    async run() {
        const { flags } = await this.parse(NodeAdd);
        const spinner = (0, ora_1.default)(`Queuing add-worker operation (count=${flags.count})...`).start();
        let service;
        try {
            const { id: clusterId } = await (0, resolve_cluster_1.resolveCluster)(flags.cluster);
            service = await cli_node_service_1.CliNodeService.create(clusterId);
        }
        catch (error) {
            spinner.fail('Setup failed');
            console.log(chalk_1.default.red(`\n  Error: ${error.message}\n`));
            this.exit(1);
        }
        let result;
        try {
            result = await service.addWorkers(flags.count);
        }
        catch (error) {
            spinner.fail('Failed to queue operation');
            const msg = error.response?.data?.message ?? error.message;
            console.log(chalk_1.default.red(`\n  Error: ${msg}\n`));
            this.exit(1);
        }
        spinner.succeed(`Operation queued`);
        console.log('');
        console.log(`  ${chalk_1.default.bold('Operation ID:')} ${result.operation_id}`);
        console.log(`  ${chalk_1.default.bold('Estimated:')}    ${result.estimated_duration}`);
        console.log('');
        if (flags['no-wait']) {
            console.log(chalk_1.default.dim('  Use `flui node list` to check when nodes are ready.\n'));
            return;
        }
        console.log(chalk_1.default.dim(`  Waiting for operation to complete (up to ${MAX_WAIT_MS / 60000} min)…`));
        console.log('');
        const waitSpinner = (0, ora_1.default)('Provisioning workers…').start();
        const started = Date.now();
        while (Date.now() - started < MAX_WAIT_MS) {
            await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
            try {
                const op = await service.getOperationStatus(result.operation_id);
                const pct = op.totalSteps > 0
                    ? Math.round((op.currentStepIndex / op.totalSteps) * 100)
                    : 0;
                waitSpinner.text = `Provisioning workers… ${pct}% (step ${op.currentStepIndex}/${op.totalSteps})`;
                if (op.status === 'COMPLETED') {
                    waitSpinner.succeed(chalk_1.default.green(`Workers added successfully`));
                    console.log('');
                    console.log(chalk_1.default.dim('  Run `flui node list` to see the updated node list.\n'));
                    return;
                }
                if (op.status === 'FAILED') {
                    waitSpinner.fail('Operation failed');
                    const errorMsg = op.metadata?.error ?? 'Unknown error';
                    console.log(chalk_1.default.red(`\n  Error: ${errorMsg}\n`));
                    this.exit(1);
                }
            }
            catch {
                // polling error — keep trying
            }
        }
        waitSpinner.warn('Timed out waiting for operation');
        console.log(chalk_1.default.yellow(`\n  Operation ${result.operation_id} is still running.`));
        console.log(chalk_1.default.dim('  Run `flui node list` to check status when it completes.\n'));
    }
}
NodeAdd.description = 'Add worker node(s) to the cluster. Provisions new servers and joins them to K3s.';
NodeAdd.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --count 2',
    '<%= config.bin %> <%= command.id %> --count 3 --no-wait',
];
NodeAdd.flags = {
    cluster: core_1.Flags.string({
        char: 'c',
        description: 'Cluster name or ID (default: auto-detect when only one cluster exists)',
    }),
    count: core_1.Flags.integer({
        char: 'n',
        description: 'Number of workers to add (1-5)',
        default: 1,
        min: 1,
        max: 5,
    }),
    'no-wait': core_1.Flags.boolean({
        description: 'Return immediately after queuing the operation',
        default: false,
    }),
};
exports.default = NodeAdd;
