import { z } from 'zod';
import { createSubcommand } from '../../../types';
import * as tui from '../../../tui';
import { createPrompt } from '../../../tui';
import { getCommand } from '../../../command-prefix';
import { isDryRunMode, outputDryRun } from '../../../explain';
import { ErrorCode } from '../../../errors';
import { loadProjectConfig, updateProjectConfig } from '../../../config';
import { checkCustomDomainForDNS, isSuccess, isMisconfigured, isError } from '../../../domain';
export const domainSubcommand = createSubcommand({
    name: 'domain',
    aliases: ['dns'],
    description: 'Add a custom domain to the current project',
    tags: ['mutating', 'slow', 'requires-auth', 'requires-project'],
    idempotent: true,
    requires: { auth: true, org: true, region: true, project: true },
    examples: [
        {
            command: getCommand('project add domain example.com'),
            description: 'Add a custom domain',
        },
        {
            command: getCommand('project add domain example.com --skip-validation'),
            description: 'Add a domain without DNS validation',
        },
        {
            command: getCommand('--dry-run project add domain example.com'),
            description: 'Preview adding a domain without making changes',
        },
    ],
    schema: {
        args: z.object({
            domain: z.string().describe('Domain name to add'),
        }),
        options: z.object({
            skipValidation: z
                .boolean()
                .optional()
                .describe('Skip DNS validation (domain will be validated on deploy)'),
        }),
        response: z.object({
            success: z.boolean().describe('Whether adding the domain succeeded'),
            domain: z.string().describe('Added domain name'),
            domains: z.array(z.string()).describe('All configured domains'),
            dryRun: z.boolean().optional().describe('True if this was a dry-run preview'),
        }),
    },
    async handler(ctx) {
        const { args, opts, options, projectDir, config, logger } = ctx;
        if (isDryRunMode(options)) {
            const message = `Would add domain "${args.domain}" to project in ${projectDir}`;
            outputDryRun(message, options);
            if (!options.json) {
                tui.newline();
                tui.info('[DRY RUN] Domain addition skipped');
            }
            return {
                success: true,
                dryRun: true,
                domain: args.domain,
                domains: [],
            };
        }
        const project = await loadProjectConfig(projectDir, config);
        const existingDomains = project.deployment?.domains ?? [];
        const domain = args.domain.toLowerCase().trim();
        // Validate domain format
        const domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+$/;
        if (!domainRegex.test(domain)) {
            logger.fatal('Please enter a valid domain name', ErrorCode.VALIDATION_FAILED);
        }
        // Check if domain already exists
        if (existingDomains.includes(domain)) {
            if (!options.json) {
                tui.warning(`Domain "${domain}" is already configured for this project`);
            }
            return {
                success: false,
                domain,
                domains: existingDomains,
            };
        }
        // Validate DNS unless skipped
        if (!opts?.skipValidation) {
            const results = await tui.spinner({
                message: `Checking DNS for ${domain}`,
                clearOnSuccess: true,
                callback: async () => {
                    return checkCustomDomainForDNS(project.projectId, [domain], project.region, config);
                },
            });
            // Handle empty results - DNS validation service returned no data
            if (results.length === 0) {
                logger.fatal(`DNS validation failed: no response from DNS validation service for domain "${domain}". ` +
                    'Use --skip-validation to add the domain without DNS verification.', ErrorCode.VALIDATION_FAILED);
            }
            // Safe to assert non-null since we've checked results.length above
            // (logger.fatal never returns - it exits the process)
            const result = results[0];
            if (!isSuccess(result)) {
                if (isError(result)) {
                    logger.fatal(`DNS validation failed: ${result.error}`, ErrorCode.VALIDATION_FAILED);
                }
                tui.newline();
                tui.warning('DNS record not yet configured. Please add one of the following DNS records:');
                tui.newline();
                tui.output(`  ${tui.colorInfo('Domain:')}  ${tui.colorPrimary(result.domain)}`);
                tui.output(`  ${tui.colorInfo('CNAME:')}   ${tui.colorPrimary(result.target)}`);
                if (result.aRecordTarget) {
                    tui.output(`  ${tui.colorInfo('A:')}       ${tui.colorPrimary(result.aRecordTarget)}`);
                }
                tui.newline();
                if (isMisconfigured(result)) {
                    tui.error(`Current configuration: ${result.misconfigured}`);
                    tui.newline();
                }
                // In non-interactive mode, fail with guidance
                const isHeadless = !process.stdin.isTTY || !process.stdout.isTTY;
                if (isHeadless) {
                    logger.fatal('DNS is not configured. Add the DNS record above and try again, or use --skip-validation', ErrorCode.VALIDATION_FAILED);
                }
                const prompt = createPrompt();
                const proceed = await prompt.confirm({
                    message: 'Add domain anyway? (DNS will be validated on deploy)',
                    initial: true,
                });
                if (process.stdin.isTTY) {
                    process.stdin.pause();
                }
                if (!proceed) {
                    logger.fatal('Operation cancelled', ErrorCode.USER_CANCELLED);
                }
            }
        }
        // Update the project config
        const updatedDomains = [...existingDomains, domain];
        await updateProjectConfig(projectDir, {
            deployment: {
                ...project.deployment,
                domains: updatedDomains,
            },
        }, config);
        if (!options.json) {
            tui.success(`Added domain: ${tui.bold(domain)}`);
            tui.info('Domain will be active after next deployment');
        }
        return {
            success: true,
            domain,
            domains: updatedDomains,
        };
    },
});
//# sourceMappingURL=domain.js.map