import { beforeEach, describe, expect, it } from 'vitest';
import { handleActuateAPI } from '../../api/index.js';
import { initDB } from '../../db.js';
import { generateApiKey } from '../../security/api-key-enhanced.js';
/**
 * Phase 5.5 #1: verify the public-read endpoints emit (or refuse to emit)
 * the `Cache-Control` header per the rules in `cache/http.ts`.
 *
 * The unit tests in `cache/__tests__/http.test.ts` already cover the
 * pure helper. These tests prove the wiring inside the handlers is
 * intact end-to-end.
 */
const VALID_SECRET = 'a'.repeat(48);
function createMockDB(opts) {
    const apiKey = opts.apiKey;
    return {
        apiKey: {
            findMany: async () => (apiKey ? [apiKey] : []),
            findUnique: async ({ where }) => {
                if (!apiKey)
                    return null;
                if (apiKey.keyHash !== where.keyHash)
                    return null;
                return apiKey;
            },
            update: async () => apiKey,
        },
        document: {
            findFirst: async () => opts.global ?? null,
            findMany: async () => [],
            count: async () => 0,
        },
        user: {},
        session: {},
        media: {},
    };
}
async function makeKey(scopes) {
    const { key, keyHash, keyPrefix } = await generateApiKey({ prefix: 'act_sk', scopes });
    return {
        key,
        record: {
            id: 'apikey-1',
            keyHash,
            keyPrefix,
            userId: 'user-1',
            scopes,
            ipRestrictions: null,
            expiresAt: null,
            lastUsedAt: null,
            revokedAt: null,
        },
    };
}
describe('Public-read Cache-Control (Phase 5.5 #1)', () => {
    beforeEach(() => {
        delete globalThis.__actuateConfig;
        process.env.CMS_SECRET = VALID_SECRET;
    });
    it('emits public s-maxage on /collections/:slug when publicReads is enabled', async () => {
        const { key, record } = await makeKey({ collections: ['posts'], actions: ['read'] });
        const db = createMockDB({ apiKey: record });
        initDB(db);
        const handler = handleActuateAPI({
            prismaClient: db,
            config: {
                collections: {
                    posts: { slug: 'posts', labels: { singular: 'Post', plural: 'Posts' }, fields: {} },
                },
                cache: {
                    publicReads: { enabled: true, maxAge: 60, staleWhileRevalidate: 300 },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/collections/posts', {
            headers: { Authorization: `Bearer ${key}` },
        }));
        expect(response.status).toBe(200);
        expect(response.headers.get('cache-control')).toBe('public, s-maxage=60, stale-while-revalidate=300');
    });
    it('emits no Cache-Control when publicReads is disabled (default behaviour)', async () => {
        const { key, record } = await makeKey({ collections: ['posts'], actions: ['read'] });
        const db = createMockDB({ apiKey: record });
        initDB(db);
        const handler = handleActuateAPI({
            prismaClient: db,
            config: {
                collections: {
                    posts: { slug: 'posts', labels: { singular: 'Post', plural: 'Posts' }, fields: {} },
                },
                // cache is intentionally absent — this is the pre-5.5 default.
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/collections/posts', {
            headers: { Authorization: `Bearer ${key}` },
        }));
        expect(response.status).toBe(200);
        expect(response.headers.get('cache-control')).toBeNull();
    });
    it('emits private/no-store on /globals/:slug for session-cookie requests', async () => {
        // No API key — we send an Actuate session cookie instead. Even though
        // the cookie value is junk (so the request will eventually 401), the
        // Cache-Control branch is evaluated before auth and must already
        // refuse the shared cache.
        const db = createMockDB({ apiKey: undefined, global: { data: { siteName: 'X' } } });
        initDB(db);
        const handler = handleActuateAPI({
            prismaClient: db,
            config: {
                collections: {},
                globals: {
                    settings: {
                        slug: 'settings',
                        label: 'Settings',
                        fields: {},
                        access: { read: () => true },
                    },
                },
                cache: { publicReads: { enabled: true, maxAge: 60 } },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/globals/settings', {
            headers: { Cookie: 'actuate_session=bogus' },
        }));
        // Whether the response is 200 or 401, the cache header rule fires
        // identically — and is enforced on the response that DOES come back
        // (errorResponse uses plain `json()` so no Cache-Control on 401).
        // The asymmetric check below is deliberate: we accept either no
        // header (error path) or the private/no-store header (success path),
        // but NEVER the public variant.
        const cc = response.headers.get('cache-control');
        expect(cc === null || cc === 'private, no-store').toBe(true);
    });
});
//# sourceMappingURL=cache-headers.test.js.map