import { describe, it, expect } from 'vitest';
import { validateEnvShape } from '../../diagnostics/env.js';
function envFrom(values) {
    return { get: (name) => values[name] };
}
describe('validateEnvShape', () => {
    it('returns ok=false when CMS_SECRET is missing', () => {
        const r = validateEnvShape(envFrom({ DATABASE_URL: 'postgres://x' }));
        expect(r.ok).toBe(false);
        const secret = r.checks.find((c) => c.name === 'CMS_SECRET');
        expect(secret?.status).toBe('missing');
    });
    it('escalates a partial Blob link (store present, token missing) to an error', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            BLOB_STORE_ID: 'store_abc',
            // BLOB_READ_WRITE_TOKEN missing — uploads would fail at runtime.
        }));
        const blob = r.checks.find((c) => c.name === 'BLOB_READ_WRITE_TOKEN');
        expect(blob?.status).toBe('error');
        expect(blob?.required).toBe(true);
    });
    it('keeps a missing Blob token a warning when no store is linked', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
        }));
        expect(r.checks.find((c) => c.name === 'BLOB_READ_WRITE_TOKEN')?.status).toBe('warn');
    });
    it('flags a CMS_SECRET shorter than 32 chars as an error', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'too-short',
            DATABASE_URL: 'postgres://x',
        }));
        expect(r.ok).toBe(false);
        expect(r.checks.find((c) => c.name === 'CMS_SECRET')?.status).toBe('error');
    });
    it('flags placeholder-looking CMS_SECRET values', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'change-me-in-prod-this-is-a-placeholder-string-xx',
            DATABASE_URL: 'postgres://x',
        }));
        expect(r.checks.find((c) => c.name === 'CMS_SECRET')?.status).toBe('error');
    });
    it('flags a CMS_ENCRYPTION_KEY that is not 64 hex chars', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            CMS_ENCRYPTION_KEY: 'aes256-local-dev-key-change-in-prod',
        }));
        expect(r.ok).toBe(false);
        const enc = r.checks.find((c) => c.name === 'CMS_ENCRYPTION_KEY');
        expect(enc?.status).toBe('error');
    });
    it('accepts a valid 64-hex-char CMS_ENCRYPTION_KEY', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            CMS_ENCRYPTION_KEY: 'a1b2'.repeat(16), // 64 hex chars
        }));
        expect(r.checks.find((c) => c.name === 'CMS_ENCRYPTION_KEY')?.status).toBe('ok');
    });
    it('flags non-hex chars in the encryption key', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            CMS_ENCRYPTION_KEY: 'z'.repeat(64), // wrong alphabet
        }));
        expect(r.checks.find((c) => c.name === 'CMS_ENCRYPTION_KEY')?.status).toBe('error');
    });
    it('flags an invalid Upstash URL when only one of URL/token is set', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            UPSTASH_REDIS_REST_URL: 'https://r.upstash.io',
            // no token
        }));
        expect(r.checks.find((c) => c.name === 'UPSTASH_REDIS_REST_TOKEN')?.status).toBe('error');
    });
    it('treats Upstash as configured via the native UPSTASH_* names', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            UPSTASH_REDIS_REST_URL: 'https://r.upstash.io',
            UPSTASH_REDIS_REST_TOKEN: 'tok',
        }));
        expect(r.checks.find((c) => c.name === 'UPSTASH_REDIS_REST_URL')?.status).toBe('ok');
    });
    it('treats Upstash as configured via the Vercel KV_REST_API_* names', () => {
        // Vercel's Marketplace Upstash integration provisions KV_REST_API_* — the
        // diagnostic must recognise them or it falsely warns on a working setup.
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            KV_REST_API_URL: 'https://kv.upstash.io',
            KV_REST_API_TOKEN: 'kv-tok',
        }));
        const check = r.checks.find((c) => c.name === 'UPSTASH_REDIS_REST_URL');
        expect(check?.status).toBe('ok');
    });
    it('warns when neither UPSTASH_* nor KV_REST_API_* is set', () => {
        const r = validateEnvShape(envFrom({ CMS_SECRET: 'a'.repeat(40), DATABASE_URL: 'postgres://x' }));
        expect(r.checks.find((c) => c.name === 'UPSTASH_REDIS_REST_URL')?.status).toBe('warn');
    });
    it('flags a CRON_SECRET that is too short', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://x',
            CRON_SECRET: 'short',
        }));
        expect(r.checks.find((c) => c.name === 'CRON_SECRET')?.status).toBe('error');
    });
    it.each([
        ['postgres://user:pass@host:5432/db'],
        ['postgresql://user:pass@host:5432/db'],
        ['mysql://user:pass@host:3306/db'],
        ['file:./dev.db'],
        // Prisma Accelerate / Prisma Postgres URLs route through the Accelerate
        // transport at runtime; the validator must treat them as valid schemes.
        ['prisma://accelerate.prisma-data.net/?api_key=eyJ'],
        ['prisma+postgres://accelerate.prisma-data.net/?api_key=eyJ'],
    ])('accepts %s as a valid DATABASE_URL scheme', (dbUrl) => {
        const r = validateEnvShape(envFrom({ CMS_SECRET: 'a'.repeat(40), DATABASE_URL: dbUrl }));
        expect(r.checks.find((c) => c.name === 'DATABASE_URL')?.status).toBe('ok');
    });
    it.each([['redis://localhost:6379'], ['http://example.com'], ['not-a-url']])('flags %s as an invalid DATABASE_URL scheme', (dbUrl) => {
        const r = validateEnvShape(envFrom({ CMS_SECRET: 'a'.repeat(40), DATABASE_URL: dbUrl }));
        expect(r.checks.find((c) => c.name === 'DATABASE_URL')?.status).toBe('error');
    });
    describe('email provider (RESEND_API_KEY check)', () => {
        const base = { CMS_SECRET: 'a'.repeat(40), DATABASE_URL: 'postgres://x' };
        it('warns when no email provider is configured', () => {
            const r = validateEnvShape(envFrom(base));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('warn');
            expect(check?.message).toMatch(/no email provider/i);
        });
        it('is ok and names Resend when RESEND_API_KEY is a real key', () => {
            const r = validateEnvShape(envFrom({ ...base, RESEND_API_KEY: 're_abc' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/Resend/);
        });
        it('warns when a Resend key does not start with re_', () => {
            const r = validateEnvShape(envFrom({ ...base, RESEND_API_KEY: 'nope' }));
            expect(r.checks.find((c) => c.name === 'RESEND_API_KEY')?.status).toBe('warn');
        });
        it('is ok and names SMTP when EMAIL_PROVIDER=smtp + SMTP_HOST is set', () => {
            const r = validateEnvShape(envFrom({ ...base, EMAIL_PROVIDER: 'smtp', SMTP_HOST: 'smtp.example.com' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/SMTP/);
        });
        it('infers SMTP from SMTP_HOST when EMAIL_PROVIDER is unset', () => {
            const r = validateEnvShape(envFrom({ ...base, SMTP_HOST: 'smtp.example.com' }));
            expect(r.checks.find((c) => c.name === 'RESEND_API_KEY')?.status).toBe('ok');
        });
        it('is ok for EMAIL_PROVIDER=ses with a region', () => {
            const r = validateEnvShape(envFrom({ ...base, EMAIL_PROVIDER: 'ses', AWS_REGION: 'us-east-1' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/SES/);
        });
        it('warns when EMAIL_PROVIDER=smtp but SMTP_HOST is missing', () => {
            const r = validateEnvShape(envFrom({ ...base, EMAIL_PROVIDER: 'smtp' }));
            expect(r.checks.find((c) => c.name === 'RESEND_API_KEY')?.status).toBe('warn');
        });
        it('is ok and names SMTP.com via the canonical SMTPCOM_API_KEY', () => {
            const r = validateEnvShape(envFrom({ ...base, EMAIL_PROVIDER: 'smtpcom', SMTPCOM_API_KEY: 'k_abc' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/SMTP\.com/);
        });
        it('infers SMTP.com from the SMTP_KEY alias when EMAIL_PROVIDER is unset', () => {
            const r = validateEnvShape(envFrom({ ...base, SMTP_KEY: 'k_abc' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/SMTP\.com/);
        });
        it('prefers a generic SMTP relay over SMTP.com when SMTP_HOST is also set', () => {
            const r = validateEnvShape(envFrom({ ...base, SMTP_HOST: 'smtp.example.com', SMTP_KEY: 'k_abc' }));
            const check = r.checks.find((c) => c.name === 'RESEND_API_KEY');
            expect(check?.status).toBe('ok');
            expect(check?.message).toMatch(/SMTP\)/);
        });
    });
    it('returns ok=true when every required var is well-formed', () => {
        const r = validateEnvShape(envFrom({
            CMS_SECRET: 'a'.repeat(40),
            DATABASE_URL: 'postgres://user:pass@host:5432/db',
            CMS_ENCRYPTION_KEY: 'a1b2'.repeat(16),
            CRON_SECRET: 'a-real-cron-secret-of-sufficient-length',
            BLOB_READ_WRITE_TOKEN: 'vercel_blob_rw_xxx',
            RESEND_API_KEY: 're_xxx',
        }));
        expect(r.ok).toBe(true);
        expect(r.errorCount).toBe(0);
    });
    // Bugbot review (PR #41): the unauthenticated /health endpoint surfaces
    // these messages, and the previous "ok" wording (`Configured (42 chars).`)
    // leaked exact secret lengths to anyone who could reach the URL — narrowing
    // brute-force search space with no operational benefit. Lengths must not
    // appear in any "ok" message.
    it.each([
        [
            'CMS_SECRET',
            {
                CMS_SECRET: 'a'.repeat(42),
                DATABASE_URL: 'postgres://x',
            },
        ],
        [
            'CMS_ENCRYPTION_KEY',
            {
                CMS_SECRET: 'a'.repeat(40),
                DATABASE_URL: 'postgres://x',
                CMS_ENCRYPTION_KEY: 'a1b2'.repeat(16),
            },
        ],
        [
            'CRON_SECRET',
            {
                CMS_SECRET: 'a'.repeat(40),
                DATABASE_URL: 'postgres://x',
                CRON_SECRET: 'a-real-cron-secret-of-sufficient-length',
            },
        ],
    ])('does not include exact length in the "ok" message for %s', (name, env) => {
        const r = validateEnvShape(envFrom(env));
        const check = r.checks.find((c) => c.name === name);
        expect(check?.status).toBe('ok');
        expect(check?.message ?? '').not.toMatch(/\d+\s*chars?/i);
    });
});
//# sourceMappingURL=env.test.js.map