import { beforeEach, describe, expect, it } from 'vitest';
import { handleActuateAPI } from '../../api/index.js';
import { initDB } from '../../db.js';
function createMockDB(docs) {
    const findFirst = async (args) => {
        const where = args?.where ?? {};
        const matches = docs.filter((d) => {
            if (where.collection && d.collection !== where.collection)
                return false;
            if (where.status && d.status !== where.status)
                return false;
            if (where.deletedAt === null) {
                // mock docs never carry deletedAt
            }
            if (where.OR && Array.isArray(where.OR)) {
                return where.OR.some((clause) => {
                    if (clause.slug !== undefined)
                        return d.slug === clause.slug;
                    if (clause.data?.path && clause.data?.equals) {
                        const path = clause.data.path[0];
                        return d.data?.[path] === clause.data.equals;
                    }
                    return false;
                });
            }
            return true;
        });
        const doc = matches[0];
        if (!doc)
            return null;
        return {
            ...doc,
            publishedAt: doc.publishedAt ?? null,
            updatedAt: doc.updatedAt ?? new Date('2026-03-15T12:00:00Z'),
            createdAt: doc.createdAt ?? new Date('2026-01-01T00:00:00Z'),
            structuredData: doc.structuredData ?? null,
        };
    };
    const findMany = async (args) => {
        const where = args?.where ?? {};
        return docs.filter((d) => {
            if (where.collection && d.collection !== where.collection)
                return false;
            if (where.status && d.status !== where.status)
                return false;
            return true;
        });
    };
    return {
        document: { findFirst, findMany },
        user: {},
        session: {},
        media: {},
    };
}
describe('public SEO routes', () => {
    beforeEach(() => {
        delete globalThis.__actuateConfig;
    });
    it('exposes /sitemap.xml as a sitemap index over configured collections', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', siteName: 'Example' },
                collections: {
                    pages: {
                        slug: 'pages',
                        labels: { singular: 'Page', plural: 'Pages' },
                        urlPrefix: '',
                        type: 'page',
                        fields: {},
                    },
                    posts: {
                        slug: 'posts',
                        labels: { singular: 'Post', plural: 'Posts' },
                        urlPrefix: 'blog',
                        type: 'post',
                        fields: {},
                    },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemap.xml'));
        expect(response.status).toBe(200);
        expect(response.headers.get('Content-Type')).toContain('application/xml');
        const text = await response.text();
        expect(text).toContain('<sitemapindex');
        expect(text).toContain('/api/cms/sitemaps/pages.xml');
        expect(text).toContain('/api/cms/sitemaps/posts.xml');
    });
    it('respects seo.sitemap.excludeCollections', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: {
                    siteUrl: 'https://example.com',
                    sitemap: { excludeCollections: ['drafts'] },
                },
                collections: {
                    pages: {
                        slug: 'pages',
                        type: 'page',
                        labels: { singular: 'P', plural: 'Pp' },
                        urlPrefix: '',
                        fields: {},
                    },
                    drafts: {
                        slug: 'drafts',
                        type: 'page',
                        labels: { singular: 'D', plural: 'Dd' },
                        urlPrefix: 'd',
                        fields: {},
                    },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemap.xml'));
        const text = await response.text();
        expect(text).toContain('/sitemaps/pages.xml');
        expect(text).not.toContain('/sitemaps/drafts.xml');
    });
    it('returns 404 when seo.sitemap.disabled is true', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', sitemap: { disabled: true } },
                collections: {
                    pages: { slug: 'pages', labels: { singular: 'P', plural: 'P' }, fields: {} },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemap.xml'));
        expect(response.status).toBe(404);
    });
    it('renders per-collection sitemap with absolute URLs and lastmod', async () => {
        const docs = [
            {
                id: '1',
                slug: 'about',
                collection: 'pages',
                status: 'PUBLISHED',
                data: { title: 'About', slug: 'about' },
                updatedAt: new Date('2026-03-10T09:00:00Z'),
            },
            {
                id: '2',
                slug: 'contact',
                collection: 'pages',
                status: 'PUBLISHED',
                data: { title: 'Contact', slug: 'contact' },
                updatedAt: new Date('2026-03-11T09:00:00Z'),
            },
        ];
        initDB(createMockDB(docs));
        const handler = handleActuateAPI({
            prismaClient: createMockDB(docs),
            config: {
                seo: { siteUrl: 'https://example.com' },
                collections: {
                    pages: {
                        slug: 'pages',
                        labels: { singular: 'P', plural: 'Pp' },
                        urlPrefix: '',
                        type: 'page',
                        fields: {},
                    },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemaps/pages.xml'));
        expect(response.status).toBe(200);
        const text = await response.text();
        expect(text).toContain('<urlset');
        expect(text).toContain('<loc>https://example.com/about</loc>');
        expect(text).toContain('<loc>https://example.com/contact</loc>');
        expect(text).toContain('<priority>0.8</priority>');
        expect(text).toContain('2026-03-10T09:00:00.000Z');
    });
    it('returns 404 for sitemap of an unknown collection', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com' },
                collections: {
                    pages: { slug: 'pages', labels: { singular: 'P', plural: 'P' }, fields: {} },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemaps/unknown.xml'));
        expect(response.status).toBe(404);
    });
    it('includes archivePath in a post-type sitemap', async () => {
        const docs = [
            {
                id: '1',
                slug: 'first',
                collection: 'posts',
                status: 'PUBLISHED',
                data: { title: 'First', slug: 'first' },
            },
        ];
        initDB(createMockDB(docs));
        const handler = handleActuateAPI({
            prismaClient: createMockDB(docs),
            config: {
                seo: { siteUrl: 'https://example.com' },
                collections: {
                    posts: {
                        slug: 'posts',
                        labels: { singular: 'Post', plural: 'Posts' },
                        urlPrefix: 'blog',
                        type: 'post',
                        seo: { archivePath: '/blog' },
                        fields: {},
                    },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/sitemaps/posts.xml'));
        const text = await response.text();
        expect(text).toContain('<loc>https://example.com/blog</loc>');
        expect(text).toContain('<loc>https://example.com/blog/first</loc>');
    });
    it('serves /robots.txt with a Sitemap reference', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com' },
                collections: {},
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/robots.txt'));
        expect(response.status).toBe(200);
        expect(response.headers.get('Content-Type')).toContain('text/plain');
        const text = await response.text();
        expect(text).toMatch(/^User-agent: \*/m);
        expect(text).toContain('Disallow: /admin');
        expect(text).toContain('Sitemap: https://example.com/api/cms/sitemap.xml');
    });
    it('appends AI bot blocks when seo.robots.blockAIBots is true', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', robots: { blockAIBots: true } },
                collections: {},
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/robots.txt'));
        const text = await response.text();
        expect(text).toContain('User-agent: GPTBot');
        expect(text).toContain('User-agent: ClaudeBot');
        expect(text).toContain('Disallow: /');
    });
    it('returns 404 for /robots.txt when seo.robots.disabled is true', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', robots: { disabled: true } },
                collections: {},
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/robots.txt'));
        expect(response.status).toBe(404);
    });
    it('renders /og.png as an SVG OG card', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', siteName: 'Example' },
                collections: {},
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/og.png?title=Hello%20World&description=Welcome'));
        expect(response.status).toBe(200);
        expect(response.headers.get('Content-Type')).toContain('image/svg+xml');
        const text = await response.text();
        expect(text).toContain('<svg');
        expect(text).toContain('Hello');
        expect(text).toContain('Example');
    });
    it('returns 404 for /og.png when seo.ogImage.disabled is true', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB([]),
            config: {
                seo: { siteUrl: 'https://example.com', ogImage: { disabled: true } },
                collections: {},
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/og.png?title=X'));
        expect(response.status).toBe(404);
    });
    it('enriches /resolve with composed jsonLd and meta', async () => {
        const docs = [
            {
                id: 'post-1',
                slug: 'hello',
                collection: 'posts',
                status: 'PUBLISHED',
                data: {
                    title: 'Hello World',
                    slug: 'hello',
                    metaDescription: 'A first post',
                    authorName: 'Jane',
                },
                publishedAt: new Date('2026-02-01T00:00:00Z'),
                updatedAt: new Date('2026-02-10T00:00:00Z'),
            },
        ];
        initDB(createMockDB(docs));
        const handler = handleActuateAPI({
            prismaClient: createMockDB(docs),
            config: {
                seo: {
                    siteUrl: 'https://example.com',
                    siteName: 'Example',
                    organization: { name: 'Example Inc' },
                },
                collections: {
                    posts: {
                        slug: 'posts',
                        labels: { singular: 'Post', plural: 'Posts' },
                        urlPrefix: 'blog',
                        type: 'post',
                        fields: {},
                    },
                },
            },
        });
        const response = await handler(new Request('https://example.com/api/cms/resolve?path=/blog/hello'));
        expect(response.status).toBe(200);
        const body = (await response.json());
        expect(body.meta).toBeDefined();
        expect(body.meta.title).toBe('Hello World');
        expect(body.meta.canonical).toBe('https://example.com/blog/hello');
        expect(body.meta.tags['og:title']).toBe('Hello World');
        expect(body.jsonLd['@type']).toBe('BlogPosting');
        expect(body.jsonLd.author).toMatchObject({ '@type': 'Person', name: 'Jane' });
        expect(body.jsonLd.publisher).toMatchObject({ '@type': 'Organization', name: 'Example Inc' });
        expect(typeof body.jsonLdHtml).toBe('string');
        expect(body.jsonLdHtml).toContain('<script type="application/ld+json">');
    });
});
//# sourceMappingURL=public-seo.test.js.map