"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_app_service_1 = require("../../lib/services/cli-app.service");
const resolve_cluster_1 = require("../../lib/resolve-cluster");
const prompts_1 = require("../../lib/prompts");
const POLL_INTERVAL_MS = 5000;
const MAX_WAIT_MS = 300_000; // 5 min
class AppDelete extends core_1.Command {
    async run() {
        const { args, flags } = await this.parse(AppDelete);
        const spinner = (0, ora_1.default)(`Looking up "${args.name}"…`).start();
        let service;
        try {
            const { id: clusterId } = await (0, resolve_cluster_1.resolveCluster)(flags.cluster);
            service = await cli_app_service_1.CliAppService.create(clusterId);
        }
        catch (error) {
            spinner.fail('Setup failed');
            console.log(chalk_1.default.red(`\n  Error: ${error.message}\n`));
            this.exit(1);
        }
        let app;
        try {
            app = await service.getAppByName(args.name);
        }
        catch (error) {
            spinner.fail('App not found');
            console.log(chalk_1.default.red(`\n  Error: ${error.message}\n`));
            this.exit(1);
        }
        const detail = await service.getAppDetail(app.id);
        spinner.stop();
        const isCatalog = !!detail.catalogInstallId;
        const isSystemProtected = detail.systemProtected === true;
        if (isSystemProtected && !flags.force) {
            console.log(chalk_1.default.red(`\n  "${app.name}" is a system-protected application.\n`));
            console.log(chalk_1.default.yellow('  Re-run with --force to delete it anyway.\n'));
            this.exit(1);
        }
        console.log(chalk_1.default.red(`\n  ${isCatalog ? 'UNINSTALL' : 'DELETE'} Application\n`));
        console.log(`  ${chalk_1.default.bold('Name:')}   ${app.name}`);
        console.log(`  ${chalk_1.default.bold('Slug:')}   ${app.slug}`);
        console.log(`  ${chalk_1.default.bold('Kind:')}   ${isCatalog ? 'catalog' : 'source-deploy'}${isSystemProtected ? chalk_1.default.yellow(' (system-protected)') : ''}`);
        console.log(`  ${chalk_1.default.bold('Status:')} ${app.status}`);
        console.log(chalk_1.default.red('\n  ALL DATA AND VOLUMES WILL BE PERMANENTLY DELETED!\n'));
        if (!flags.force) {
            console.log(chalk_1.default.yellow(`  To confirm, type the app name exactly: ${chalk_1.default.bold(app.name)}`));
            const confirmed = await (0, prompts_1.confirmByTypingPrompt)(chalk_1.default.yellow('  App name'), app.name);
            if (!confirmed) {
                console.log(chalk_1.default.green('\n  Deletion cancelled (name did not match)\n'));
                return;
            }
        }
        const queueSpinner = (0, ora_1.default)(isCatalog ? 'Queuing uninstall…' : 'Queuing delete…').start();
        try {
            if (isCatalog) {
                await service.uninstall(detail.catalogInstallId);
            }
            else {
                await service.deleteApp(app.id);
            }
            queueSpinner.succeed(isCatalog ? 'Uninstall queued' : 'Delete queued');
            console.log('');
        }
        catch (error) {
            queueSpinner.fail(isCatalog ? 'Failed to queue uninstall' : 'Failed to queue delete');
            const msg = error.response?.data?.message ?? error.message;
            console.log(chalk_1.default.red(`\n  Error: ${msg}\n`));
            this.exit(1);
        }
        if (flags['no-wait'] || !isCatalog) {
            console.log(chalk_1.default.dim('  Use `flui app list` to verify the app is removed.\n'));
            return;
        }
        await this.waitForUninstall(service, detail.catalogInstallId, app.name);
    }
    async waitForUninstall(service, catalogInstallId, appName) {
        console.log(chalk_1.default.dim(`  Waiting for uninstall to complete (up to ${MAX_WAIT_MS / 60000} min)…`));
        const waitSpinner = (0, ora_1.default)(`Uninstalling ${appName}…`).start();
        const started = Date.now();
        while (Date.now() - started < MAX_WAIT_MS) {
            await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
            const done = await this.pollUninstall(service, catalogInstallId, appName, waitSpinner);
            if (done)
                return;
        }
        waitSpinner.warn('Timed out waiting for uninstall');
        console.log(chalk_1.default.yellow(`\n  Uninstall is still running. Check with:`));
        console.log(chalk_1.default.dim(`    flui app list\n`));
    }
    async pollUninstall(service, catalogInstallId, appName, waitSpinner) {
        try {
            const current = await service.getInstallStatus(catalogInstallId);
            if (current.status === 'UNINSTALLED') {
                waitSpinner.succeed(chalk_1.default.green(`"${appName}" uninstalled successfully`));
                console.log('');
                console.log(chalk_1.default.dim('  All resources and volumes have been removed.\n'));
                return true;
            }
            if (current.status === 'FAILED') {
                waitSpinner.fail('Uninstall failed');
                const msg = current.errorMessage ?? 'Unknown error';
                console.log(chalk_1.default.red(`\n  Error: ${msg}\n`));
                this.exit(1);
            }
            waitSpinner.text = `Uninstalling ${appName}… (${current.status.toLowerCase()})`;
        }
        catch {
            /* polling error — keep trying */
        }
        return false;
    }
}
AppDelete.description = 'Delete an application and remove all its resources from the cluster. ' +
    'Works for both catalog installs and source-deploy (flui.yaml) apps. ' +
    'System-protected apps require --force.';
AppDelete.examples = [
    '<%= config.bin %> <%= command.id %> uptime-kuma',
    '<%= config.bin %> <%= command.id %> uptime-kuma --force',
    '<%= config.bin %> <%= command.id %> uptime-kuma --no-wait',
];
AppDelete.args = {
    name: core_1.Args.string({
        description: 'Application name or slug',
        required: true,
    }),
};
AppDelete.flags = {
    cluster: core_1.Flags.string({
        char: 'c',
        description: 'Cluster name or ID (default: auto-detect when only one cluster exists)',
    }),
    force: core_1.Flags.boolean({
        char: 'f',
        description: 'Skip confirmation prompt',
        default: false,
    }),
    'no-wait': core_1.Flags.boolean({
        description: 'Return immediately after queuing the uninstall',
        default: false,
    }),
};
exports.default = AppDelete;
