"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.smtpShape = exports.smtpInputSpec = exports.systemSmtpSpec = exports.smtpProviderVariants = exports.customSmtp = void 0;
exports.smtpPrefill = smtpPrefill;
const util_1 = require("../../util");
const inputSpec_1 = require("./builder/inputSpec");
const value_1 = require("./builder/value");
const variants_1 = require("./builder/variants");
const zod_1 = require("zod");
const securityVariants = variants_1.Variants.of({
    tls: {
        name: 'TLS',
        spec: inputSpec_1.InputSpec.of({
            port: value_1.Value.dynamicText(async () => ({
                name: 'Port',
                required: true,
                default: '465',
                disabled: 'Fixed for TLS',
            })),
        }),
    },
    starttls: {
        name: 'STARTTLS',
        spec: inputSpec_1.InputSpec.of({
            port: value_1.Value.select({
                name: 'Port',
                default: '587',
                values: { '25': '25', '587': '587', '2525': '2525' },
            }),
        }),
    },
});
/**
 * Creates an SMTP field spec with provider-specific defaults pre-filled.
 */
function smtpFields(defaults = {}) {
    const hostSpec = value_1.Value.text({
        name: 'Host',
        required: true,
        default: defaults.host ?? null,
        placeholder: 'smtp.example.com',
    });
    return inputSpec_1.InputSpec.of({
        host: defaults.hostDisabled
            ? hostSpec.withDisabled('Fixed for this provider')
            : hostSpec,
        security: value_1.Value.union({
            name: 'Connection Security',
            default: defaults.security ?? 'tls',
            variants: securityVariants,
        }),
        from: value_1.Value.text({
            name: 'From Address',
            required: true,
            default: null,
            placeholder: 'Example Name <test@example.com>',
            patterns: [util_1.Patterns.emailWithName],
        }),
        username: value_1.Value.text({
            name: 'Username',
            required: true,
            default: null,
        }),
        password: value_1.Value.text({
            name: 'Password',
            required: false,
            default: null,
            masked: true,
        }),
    });
}
/**
 * Base SMTP settings with no provider-specific defaults.
 */
exports.customSmtp = smtpFields();
/**
 * Provider presets for SMTP configuration.
 * Each variant has SMTP fields pre-filled with the provider's recommended settings.
 */
exports.smtpProviderVariants = variants_1.Variants.of({
    gmail: {
        name: 'Gmail',
        spec: smtpFields({
            host: 'smtp.gmail.com',
            security: 'tls',
            hostDisabled: true,
        }),
    },
    ses: {
        name: 'Amazon SES',
        spec: smtpFields({
            host: 'email-smtp.us-east-1.amazonaws.com',
            security: 'tls',
        }),
    },
    sendgrid: {
        name: 'SendGrid',
        spec: smtpFields({
            host: 'smtp.sendgrid.net',
            security: 'tls',
            hostDisabled: true,
        }),
    },
    mailgun: {
        name: 'Mailgun',
        spec: smtpFields({
            host: 'smtp.mailgun.org',
            security: 'tls',
            hostDisabled: true,
        }),
    },
    protonmail: {
        name: 'Proton Mail',
        spec: smtpFields({
            host: 'smtp.protonmail.ch',
            security: 'tls',
            hostDisabled: true,
        }),
    },
    other: {
        name: 'Other',
        spec: exports.customSmtp,
    },
});
/**
 * System SMTP settings with provider presets.
 * Wraps smtpProviderVariants in a union for use by the system email settings page.
 */
exports.systemSmtpSpec = inputSpec_1.InputSpec.of({
    provider: value_1.Value.union({
        name: 'Provider',
        default: 'gmail',
        variants: exports.smtpProviderVariants,
    }),
});
const smtpVariants = variants_1.Variants.of({
    disabled: { name: 'Disabled', spec: inputSpec_1.InputSpec.of({}) },
    system: {
        name: 'System Credentials',
        spec: inputSpec_1.InputSpec.of({
            customFrom: value_1.Value.text({
                name: 'Custom From Address',
                description: 'A custom from address for this service. If not provided, the system from address will be used.',
                required: false,
                default: null,
                placeholder: 'Name <test@example.com>',
                patterns: [util_1.Patterns.emailWithName],
            }),
        }),
    },
    custom: {
        name: 'Custom Credentials',
        spec: inputSpec_1.InputSpec.of({
            provider: value_1.Value.union({
                name: 'Provider',
                default: null,
                variants: exports.smtpProviderVariants,
            }),
        }),
    },
});
/**
 * For service inputSpec. Gives users 3 options for SMTP: (1) disabled, (2) use system SMTP settings, (3) use custom SMTP settings with provider presets
 */
exports.smtpInputSpec = value_1.Value.dynamicUnion(async ({ effects }) => {
    const smtp = await new util_1.GetSystemSmtp(effects).once();
    const disabled = smtp ? [] : ['system'];
    return {
        name: 'SMTP',
        description: 'Optionally provide an SMTP server for sending emails',
        default: 'disabled',
        disabled,
        variants: smtpVariants,
    };
}, smtpVariants.validator);
const securityShape = zod_1.z
    .object({
    selection: zod_1.z.enum(['tls', 'starttls']).catch('tls'),
    value: zod_1.z.object({ port: zod_1.z.string().catch('465') }).catch({ port: '465' }),
})
    .catch({ selection: 'tls', value: { port: '465' } });
const providerShape = zod_1.z
    .object({
    selection: zod_1.z.string().catch('other'),
    value: zod_1.z
        .object({
        host: zod_1.z.string().catch(''),
        from: zod_1.z.string().catch(''),
        username: zod_1.z.string().catch(''),
        password: zod_1.z.string().nullable().optional().catch(null),
        security: securityShape,
    })
        .catch({
        host: '',
        from: '',
        username: '',
        password: null,
        security: securityShape.parse(undefined),
    }),
})
    .catch({
    selection: 'other',
    value: {
        host: '',
        from: '',
        username: '',
        password: null,
        security: securityShape.parse(undefined),
    },
});
/**
 * Zod schema for persisting SMTP selection in a store file model.
 * Use this instead of `smtpInputSpec.validator` to avoid cross-zod-instance issues.
 */
exports.smtpShape = zod_1.z
    .discriminatedUnion('selection', [
    zod_1.z.object({
        selection: zod_1.z.literal('disabled'),
        value: zod_1.z.object({}).catch({}),
    }),
    zod_1.z.object({
        selection: zod_1.z.literal('system'),
        value: zod_1.z
            .object({ customFrom: zod_1.z.string().nullable().optional().catch(null) })
            .catch({ customFrom: null }),
    }),
    zod_1.z.object({
        selection: zod_1.z.literal('custom'),
        value: zod_1.z
            .object({ provider: providerShape })
            .catch({ provider: providerShape.parse(undefined) }),
    }),
])
    .catch({ selection: 'disabled', value: {} });
/**
 * Convert a stored SmtpSelection to a value suitable for prefilling smtpInputSpec.
 *
 * The stored type (SmtpSelection from smtpShape) uses flat unions for provider/security
 * selection, while the input spec (smtpInputSpec) uses distributed discriminated unions
 * (UnionRes). These are structurally incompatible in TypeScript's type system, even
 * though the runtime values are identical. This function bridges the two types so that
 * service code doesn't need `as any`.
 */
function smtpPrefill(smtp) {
    return smtp || undefined;
}
//# sourceMappingURL=inputSpecConstants.js.map