"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 provider_factory_1 = require("../../../../src/modules/providers/core/factories/provider.factory");
const cloud_provider_enum_1 = require("../../../../src/modules/providers/enums/cloud-provider.enum");
const cli_cluster_repository_1 = require("../../lib/repositories/cli-cluster.repository");
const prompts_1 = require("../../lib/prompts");
const context_banner_1 = require("../../lib/context-banner");
class EnvOrphanVolumes extends core_1.Command {
    async run() {
        const { flags } = await this.parse(EnvOrphanVolumes);
        (0, context_banner_1.printContextBanner)();
        const app = await (0, nest_app_1.getNestApp)();
        try {
            const providerFactory = app.get(provider_factory_1.ProviderFactory);
            const clusterRepo = app.get(cli_cluster_repository_1.CliClusterRepository);
            const clusters = await clusterRepo.find();
            const knownVolumeIds = new Set();
            for (const c of clusters) {
                const id = c.sharedStorageVolumeId;
                if (!id)
                    continue;
                knownVolumeIds.add(id);
                const colon = id.indexOf(':');
                if (colon > 0)
                    knownVolumeIds.add(id.slice(colon + 1));
                else
                    knownVolumeIds.add(id);
            }
            const targets = flags.provider
                ? [flags.provider]
                : [cloud_provider_enum_1.CloudProvider.HETZNER, cloud_provider_enum_1.CloudProvider.SCALEWAY];
            const spinner = (0, ora_1.default)('Scanning providers for Flui-managed volumes...').start();
            const orphans = [];
            for (const p of targets) {
                try {
                    const svc = providerFactory.getProvider(p);
                    if (!svc.listFluiManagedVolumes)
                        continue;
                    const list = await svc.listFluiManagedVolumes();
                    for (const v of list) {
                        if (knownVolumeIds.has(v.volumeId))
                            continue;
                        const colon = v.volumeId.indexOf(':');
                        const bareId = colon > 0 ? v.volumeId.slice(colon + 1) : v.volumeId;
                        if (knownVolumeIds.has(bareId))
                            continue;
                        orphans.push({
                            provider: p,
                            volumeId: v.volumeId,
                            name: v.name,
                            sizeGb: v.sizeGb,
                            region: v.region,
                            attached: !!v.attachedServerId,
                        });
                    }
                }
                catch (err) {
                    spinner.warn(`${p} scan failed: ${err.message}`);
                }
            }
            spinner.succeed(`Scan complete — ${orphans.length} orphan volume(s) found`);
            if (orphans.length === 0) {
                console.log(chalk_1.default.green('\n✅ No orphan volumes detected.\n'));
                return;
            }
            console.log('');
            let totalGb = 0;
            for (const v of orphans) {
                totalGb += v.sizeGb;
                console.log(`   ${chalk_1.default.bold(v.provider)}  ${chalk_1.default.cyan(v.volumeId)}  ` +
                    `${v.sizeGb} GB  ${v.region ?? '?'}  ${chalk_1.default.dim(v.name)}` +
                    (v.attached ? chalk_1.default.yellow('  [attached]') : ''));
            }
            console.log(chalk_1.default.dim(`\n   Total: ${orphans.length} volume(s), ${totalGb} GB\n`));
            if (!flags.cleanup) {
                console.log(chalk_1.default.dim('   Re-run with --cleanup to detach and delete these volumes.\n'));
                return;
            }
            if (!flags.yes) {
                const confirmed = await (0, prompts_1.confirmPrompt)(chalk_1.default.yellow(`Delete ${orphans.length} orphan volume(s)? This is irreversible`), false);
                if (!confirmed) {
                    console.log(chalk_1.default.green('\n✅ Cleanup cancelled\n'));
                    return;
                }
            }
            let deleted = 0;
            let failed = 0;
            for (const v of orphans) {
                const cleanupSpinner = (0, ora_1.default)(`Cleaning up ${v.provider} ${v.volumeId} (${v.sizeGb} GB)...`).start();
                try {
                    const svc = providerFactory.getProvider(v.provider);
                    if (svc.detachVolume) {
                        try {
                            await svc.detachVolume(v.volumeId);
                        }
                        catch (err) {
                            cleanupSpinner.text = `Detach failed, attempting delete anyway... (${err.message})`;
                        }
                    }
                    if (!svc.deleteVolume) {
                        cleanupSpinner.fail(`Provider ${v.provider} has no deleteVolume primitive`);
                        failed++;
                        continue;
                    }
                    await svc.deleteVolume(v.volumeId);
                    cleanupSpinner.succeed(`Deleted ${v.provider} ${v.volumeId}`);
                    deleted++;
                }
                catch (err) {
                    cleanupSpinner.fail(`Failed to delete ${v.volumeId}: ${err.message}`);
                    failed++;
                }
            }
            console.log('');
            console.log(chalk_1.default.green(`✅ Deleted ${deleted} volume(s)`) +
                (failed > 0 ? chalk_1.default.red(` · ${failed} failed`) : ''));
            console.log('');
        }
        finally {
            await (0, nest_app_1.closeNestApp)();
        }
    }
}
EnvOrphanVolumes.description = 'List or clean up Flui-managed block volumes left behind by past destroys';
EnvOrphanVolumes.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --cleanup',
    '<%= config.bin %> <%= command.id %> --provider scaleway --cleanup',
];
EnvOrphanVolumes.flags = {
    provider: core_1.Flags.string({
        char: 'p',
        description: 'Scan only one provider (hetzner | scaleway)',
        options: ['hetzner', 'scaleway'],
    }),
    cleanup: core_1.Flags.boolean({
        description: 'Detach and delete the listed orphan volumes',
        default: false,
    }),
    yes: core_1.Flags.boolean({
        char: 'y',
        description: 'Skip confirmation prompt during cleanup',
        default: false,
    }),
};
exports.default = EnvOrphanVolumes;
