"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCertsCommand = createCertsCommand;
const cert_manager_1 = require("../services/cert-manager");
const docker_compose_1 = require("../services/docker-compose");
const env_loader_1 = require("../utils/env-loader");
const logger_1 = require("../utils/logger");
const i18n_1 = require("../i18n");
const command_1 = require("../utils/command");
const nss_certutil_1 = require("../services/nss-certutil");
function shouldRestartOnWindows(changed) {
    return changed && process.platform === 'win32';
}
function restartIfRunningOnWindows(composePath, changed) {
    if (!shouldRestartOnWindows(changed)) {
        return;
    }
    const running = docker_compose_1.composeService.ps(composePath).some((container) => container.State === 'running');
    if (!running) {
        logger_1.logger.warn('Certificate files changed, but no runestone container is running to restart.');
        return;
    }
    logger_1.logger.info('Restarting runestone container so Docker Desktop picks up certificate/config changes');
    docker_compose_1.composeService.restart(composePath);
}
function formatCertificateTable(items, options) {
    const rows = items.map((item) => [
        item.status,
        item.sans.length > 0 ? item.sans.join(', ') : '-',
        item.issuer || '-',
        item.validUntil || '-',
        item.expiry || '-'
    ]);
    const allRows = options.header ? [['Status', 'SANs', 'Issuer', 'Valid Until', 'Expiry'], ...rows] : rows;
    const widths = allRows.reduce((next, row) => row.map((cell, index) => Math.max(next[index] ?? 0, cell.length)), []);
    return allRows
        .map((row) => row.map((cell, index) => cell.padEnd(widths[index])).join('  ').trimEnd())
        .join('\n');
}
function createCertsCommand() {
    const command = (0, command_1.createCommand)('certs')
        .alias('cert')
        .description((0, i18n_1.t)('commands.certs.description'));
    command
        .addCommand((0, command_1.createCommand)('create')
        .alias('c')
        .description((0, i18n_1.t)('commands.certs.create.description'))
        .argument('<domain>', (0, i18n_1.t)('arguments.domain.create'))
        .action(async (domain) => {
        try {
            const config = env_loader_1.envLoader.load();
            const result = await (0, cert_manager_1.createDomainCertificate)(config.PROJECT_DIR, domain);
            restartIfRunningOnWindows(config.COMPOSE_FILE_PATH, result.certificateChanged || result.dynamicConfigChanged);
            logger_1.logger.success(`Certificate configuration ready for '${result.artifacts.domain}'`);
            console.log(`  Certificate: ${result.artifacts.certFile}`);
            console.log(`  Key: ${result.artifacts.keyFile}`);
            console.log(`  Traefik TLS config: ${result.artifacts.dynamicConfigFile}`);
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            logger_1.logger.error(`Failed to create certificate: ${message}`);
            process.exit(1);
        }
    }));
    command
        .addCommand((0, command_1.createCommand)('install')
        .alias('i')
        .description((0, i18n_1.t)('commands.certs.install.description'))
        .action(() => {
        try {
            const config = env_loader_1.envLoader.load();
            const caPath = (0, nss_certutil_1.rootCaPath)(config.PROJECT_DIR);
            if (process.platform === 'win32') {
                logger_1.logger.info('Windows uses the system trust store through mkcert; no NSS database install is required.');
                console.log(`  Certificate: ${caPath}`);
                return;
            }
            const result = (0, nss_certutil_1.importRootCaToNssDatabases)(caPath);
            logger_1.logger.success(`Root CA imported into ${result.imported.length} NSS database(s)`);
            for (const db of result.imported) {
                console.log(`  Imported: ${db.dir}`);
            }
            for (const db of result.skipped) {
                console.log(`  Already installed: ${db.dir}`);
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            logger_1.logger.error(`Failed to install root CA: ${message}`);
            process.exit(1);
        }
    }));
    command
        .addCommand((0, command_1.createCommand)('list')
        .alias('ls')
        .description((0, i18n_1.t)('commands.certs.list.description'))
        .option('--no-header', (0, i18n_1.t)('options.noHeader.description'))
        .action((options) => {
        try {
            const config = env_loader_1.envLoader.load();
            const table = formatCertificateTable((0, cert_manager_1.listDomainCertificates)(config.PROJECT_DIR), { header: options.header });
            if (table) {
                console.log(table);
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            logger_1.logger.error(`Failed to list certificates: ${message}`);
            process.exit(1);
        }
    }));
    command
        .addCommand((0, command_1.createCommand)('remove')
        .alias('rm')
        .alias('del')
        .description((0, i18n_1.t)('commands.certs.remove.description'))
        .argument('<domain>', (0, i18n_1.t)('arguments.domain.remove'))
        .action((domain) => {
        try {
            const config = env_loader_1.envLoader.load();
            const result = (0, cert_manager_1.removeDomainCertificate)(config.PROJECT_DIR, domain);
            const changed = result.certificateChanged || result.dynamicConfigChanged;
            restartIfRunningOnWindows(config.COMPOSE_FILE_PATH, changed);
            if (changed) {
                logger_1.logger.success(`Certificate configuration removed for '${result.artifacts.domain}'`);
            }
            else {
                logger_1.logger.warn(`No certificate configuration found for '${result.artifacts.domain}'`);
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            logger_1.logger.error(`Failed to remove certificate: ${message}`);
            process.exit(1);
        }
    }));
    return command;
}
//# sourceMappingURL=certs.js.map