export class DeployService {
    ports;
    constructor(ports) {
        this.ports = ports;
    }
    async execute(plan) {
        const { logger } = this.ports;
        // ─── Validate ───────────────────────────────────────────────
        if (!plan.skipHosting && plan.ftpLogin.length > 32) {
            throw new Error(`ftp_login "${plan.ftpLogin}" exceeds 32 characters (${plan.ftpLogin.length}). Use a shorter project name or set ftp_login in aurora.yaml.`);
        }
        // ─── Generate SSH key pair ────────────────────────────────────
        let sshKeys;
        if (!plan.skipSsh) {
            logger.header('SSH Keys');
            const sshSpinner = logger.step('Generando par de claves SSH...');
            sshKeys = await this.ports.ssh.generateKeyPair(`deploy@${plan.domain}`);
            sshSpinner.succeed('Claves SSH generadas (ed25519)');
        }
        // ─── Step 1: DNS ──────────────────────────────────────────────
        if (!plan.skipDns) {
            logger.header('Step 1: DNS (IONOS)');
            await this.ports.dns.upsertRecord({
                domain: plan.domain,
                type: plan.dnsRecordType,
                value: plan.dnsValue ?? plan.server.host,
                zone: plan.dnsZone,
            });
        }
        // ─── Step 2: Hosting ──────────────────────────────────────────
        if (!plan.skipHosting) {
            logger.header('Step 2: Hosting (Plesk)');
            const { domainId } = await this.ports.hosting.createSubscription({
                domain: plan.domain,
                ftpLogin: plan.ftpLogin,
                ftpPassword: plan.ftpPassword,
                plan: plan.server.plan,
            });
            if (plan.database) {
                await this.ports.hosting.createDatabase({
                    domainId,
                    name: plan.database.name,
                    password: plan.database.password,
                    type: plan.database.type,
                    user: plan.database.user,
                });
            }
            await this.ports.hosting.enableShellAccess({
                domain: plan.domain,
                sshUser: plan.pleskSshUser,
            });
            await this.ports.hosting.disableProxyMode({
                domain: plan.domain,
            });
            const sslEmail = plan.project.email ??
                (await this.ports.hosting.getAdminEmail({
                    sshUser: plan.pleskSshUser,
                }));
            await this.ports.hosting.installSslCertificate({
                domain: plan.domain,
                email: sslEmail,
                sshUser: plan.pleskSshUser,
            });
            if (plan.nginxDirectives) {
                await this.ports.hosting.setNginxDirectives({
                    directives: plan.nginxDirectives,
                    domain: plan.domain,
                    sshUser: plan.pleskSshUser,
                });
            }
            if (plan.target === 'back') {
                await this.ports.hosting.enableNodeJs({
                    domain: plan.domain,
                    startupFile: plan.startupFile,
                });
            }
            if (sshKeys) {
                await this.ports.hosting.installSshKey({
                    domain: plan.domain,
                    ftpLogin: plan.ftpLogin,
                    publicKey: sshKeys.publicKey,
                    sshUser: plan.pleskSshUser,
                });
            }
        }
        // ─── Step 3: CI/CD ────────────────────────────────────────────
        if (!plan.skipCicd) {
            logger.header('Paso 3: GitHub (CI/CD)');
            await this.configureCiCd(plan, sshKeys?.privateKey);
        }
        // ─── Summary ──────────────────────────────────────────────────
        const label = `[${plan.environment}/${plan.target}]`;
        logger.header(`Setup completado ${label}`);
        if (!plan.skipDns) {
            logger.success(`DNS:      ${plan.domain} → ${plan.server.host}`);
        }
        if (!plan.skipHosting) {
            logger.success('Hosting:  Suscripción configurada en Plesk');
        }
        if (!plan.skipCicd) {
            logger.success(`GitHub:   Secrets y variables configurados en ${plan.project.repo}`);
        }
        logger.info('Haz git push para lanzar el primer despliegue.');
    }
    async configureCiCd(plan, sshPrivateKey) {
        const p = plan.secretPrefix;
        const secrets = {
            [`${p}FTP_USERNAME`]: plan.ftpLogin,
        };
        if (sshPrivateKey) {
            secrets[`${p}SSH_PRIVATE_KEY`] = sshPrivateKey;
        }
        const variables = {
            [`${p}SERVER_HOST`]: plan.server.host,
            [`${p}VHOST_PATH`]: `/var/www/vhosts/${plan.domain}`,
        };
        if (plan.target === 'back') {
            if (plan.oauthPrivateKey)
                secrets[`${p}OAUTH_PRIVATE_KEY`] = plan.oauthPrivateKey;
            if (plan.oauthPublicKey)
                secrets[`${p}OAUTH_PUBLIC_KEY`] = plan.oauthPublicKey;
            if (plan.dotEnv)
                secrets[`${p}DOT_ENV`] = plan.dotEnv;
            if (plan.sopsAgeKey)
                secrets[`${p}SOPS_AGE_SECRET_KEY`] = plan.sopsAgeKey;
            if (plan.dotEnvEnc)
                variables[`${p}DOT_ENV_ENC`] = plan.dotEnvEnc;
        }
        if (plan.target === 'front' && plan.envConfiguration)
            variables[`${p}ENV_CONFIGURATION`] = plan.envConfiguration;
        await this.ports.cicd.setSecrets({ repo: plan.project.repo, secrets });
        await this.ports.cicd.setVariables({ repo: plan.project.repo, variables });
    }
}
