import { beforeEach, describe, expect, it } from 'vitest';
import { EMAIL_CONFIG_COLLECTION, detectEnvEmailProvider, emailKeyLast4, encryptEmailSecret, getEmailConfig, putEmailConfig, resolveEmailProviderSettings, toPublicEmailConfig, validateEmailSettingsInput, } from '../../email/settings-store.js';
function createMockDB() {
    let row = null;
    const db = {
        document: {
            findFirst: async ({ where, select }) => {
                if (where?.collection !== EMAIL_CONFIG_COLLECTION || !row)
                    return null;
                if (select?.id)
                    return { id: row.id };
                return { data: row.data };
            },
            update: async ({ data }) => {
                row = { id: row.id, data: data.data };
                return row;
            },
            create: async ({ data }) => {
                row = { id: 'email-config-1', data: data.data };
                return row;
            },
        },
    };
    return { db, getRow: () => row };
}
describe('email settings store', () => {
    beforeEach(() => {
        delete process.env.CMS_ENCRYPTION_KEY;
    });
    it('returns { provider: null } when no config document exists', async () => {
        const { db } = createMockDB();
        expect(await getEmailConfig(db)).toEqual({ provider: null });
    });
    it('round-trips a config document and stamps updatedAt/updatedBy', async () => {
        const { db } = createMockDB();
        await putEmailConfig(db, { provider: 'smtpcom', from: 'noreply@example.com', channel: 'marketing' }, 'user-1');
        const read = await getEmailConfig(db);
        expect(read.provider).toBe('smtpcom');
        expect(read.from).toBe('noreply@example.com');
        expect(read.channel).toBe('marketing');
        expect(read.updatedBy).toBe('user-1');
        expect(read.updatedAt).toBeTruthy();
    });
    it('toPublicEmailConfig strips encrypted secrets and adds has-flags', () => {
        const doc = {
            provider: 'resend',
            from: 'noreply@example.com',
            apiKeyEncrypted: 'enc:v1:deadbeef',
            apiKeyLast4: 'k3y9',
            smtpPassEncrypted: 'enc:v1:cafebabe',
        };
        const pub = toPublicEmailConfig(doc);
        expect(pub).not.toHaveProperty('apiKeyEncrypted');
        expect(pub).not.toHaveProperty('smtpPassEncrypted');
        expect(pub.hasApiKey).toBe(true);
        expect(pub.hasSmtpPass).toBe(true);
        expect(pub.apiKeyLast4).toBe('k3y9');
        expect(JSON.stringify(pub)).not.toContain('deadbeef');
        expect(JSON.stringify(pub)).not.toContain('cafebabe');
    });
    it('encrypts secrets at rest when CMS_ENCRYPTION_KEY is set', async () => {
        process.env.CMS_ENCRYPTION_KEY = 'a'.repeat(64);
        const { encrypted, last4 } = await encryptEmailSecret('re_super_secret_value');
        expect(encrypted.startsWith('enc:v1:')).toBe(true);
        expect(encrypted).not.toContain('re_super_secret_value');
        expect(last4).toBe('alue');
    });
    describe('resolveEmailProviderSettings', () => {
        it('decrypts the API key for resend/smtpcom', async () => {
            process.env.CMS_ENCRYPTION_KEY = 'a'.repeat(64);
            const { encrypted } = await encryptEmailSecret('re_abc123');
            const settings = await resolveEmailProviderSettings({
                provider: 'resend',
                from: 'noreply@example.com',
                apiKeyEncrypted: encrypted,
            });
            expect(settings).toEqual({
                provider: 'resend',
                from: 'noreply@example.com',
                apiKey: 're_abc123',
            });
        });
        it('returns null when required pieces are missing', async () => {
            expect(await resolveEmailProviderSettings({ provider: null })).toBeNull();
            expect(await resolveEmailProviderSettings({ provider: 'resend', from: 'a@b.co' })).toBeNull();
            expect(await resolveEmailProviderSettings({ provider: 'ses', from: 'a@b.co' })).toBeNull();
            expect(await resolveEmailProviderSettings({ provider: 'smtp', from: 'a@b.co' })).toBeNull();
        });
        it('builds smtp settings with optional auth', async () => {
            const settings = await resolveEmailProviderSettings({
                provider: 'smtp',
                from: 'a@b.co',
                host: 'smtp.example.com',
                port: 465,
                secure: true,
                smtpUser: 'mailer',
                smtpPassEncrypted: 'plaintext-pass', // no enc prefix → passthrough
            });
            expect(settings).toEqual({
                provider: 'smtp',
                from: 'a@b.co',
                host: 'smtp.example.com',
                port: 465,
                secure: true,
                auth: { user: 'mailer', pass: 'plaintext-pass' },
            });
        });
    });
    describe('validateEmailSettingsInput', () => {
        const noStored = { hasApiKey: false };
        it('accepts provider: null (clearing)', () => {
            expect(validateEmailSettingsInput({ provider: null }, noStored)).toBeNull();
        });
        it('rejects unknown providers and missing/invalid from', () => {
            expect(validateEmailSettingsInput({ provider: 'sendgrid' }, noStored)).toMatch(/provider/);
            expect(validateEmailSettingsInput({ provider: 'resend' }, noStored)).toMatch(/sender/);
            expect(validateEmailSettingsInput({ provider: 'resend', from: 'not-an-email' }, noStored)).toMatch(/sender/);
        });
        it('requires an API key for resend/smtpcom unless one is stored', () => {
            const base = { provider: 'resend', from: 'a@b.co' };
            expect(validateEmailSettingsInput(base, noStored)).toMatch(/API key/);
            expect(validateEmailSettingsInput({ ...base, apiKey: 're_x' }, noStored)).toBeNull();
            expect(validateEmailSettingsInput(base, { hasApiKey: true })).toBeNull();
        });
        it('requires a valid region for ses and a valid host/port for smtp', () => {
            expect(validateEmailSettingsInput({ provider: 'ses', from: 'a@b.co', region: 'nope' }, noStored)).toMatch(/region/);
            expect(validateEmailSettingsInput({ provider: 'ses', from: 'a@b.co', region: 'us-east-1' }, noStored)).toBeNull();
            expect(validateEmailSettingsInput({ provider: 'smtp', from: 'a@b.co', host: 'http://smtp.example.com' }, noStored)).toMatch(/hostname/);
            expect(validateEmailSettingsInput({ provider: 'smtp', from: 'a@b.co', host: 'smtp.example.com', port: 99999 }, noStored)).toMatch(/port/);
            expect(validateEmailSettingsInput({ provider: 'smtp', from: 'a@b.co', host: 'smtp.example.com', port: 587 }, noStored)).toBeNull();
        });
    });
    describe('detectEnvEmailProvider', () => {
        it('honours explicit EMAIL_PROVIDER then infers from credentials', () => {
            expect(detectEnvEmailProvider({ EMAIL_PROVIDER: 'ses' })).toBe('ses');
            expect(detectEnvEmailProvider({ SMTP_HOST: 'smtp.x.com' })).toBe('smtp');
            expect(detectEnvEmailProvider({ SMTP_KEY: 'k' })).toBe('smtpcom');
            expect(detectEnvEmailProvider({ SMTPCOM_API_KEY: 'k' })).toBe('smtpcom');
            expect(detectEnvEmailProvider({ RESEND_API_KEY: 're_x' })).toBe('resend');
            expect(detectEnvEmailProvider({})).toBeNull();
        });
    });
    it('emailKeyLast4 masks to the trailing 4 characters', () => {
        expect(emailKeyLast4('re_abcdef')).toBe('cdef');
        expect(emailKeyLast4('abc')).toBe('abc');
        expect(emailKeyLast4('')).toBeUndefined();
    });
});
//# sourceMappingURL=settings-store.test.js.map