import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { validatePublishableDocument, resolvePublishValidationMode, isGatedContentCollection, enforcePublishValidation, } from '../../validation/publish.js';
import { createDocument, updateDocument } from '../../actions.js';
import { setActuateConfig } from '../../config/runtime.js';
import { vi } from 'vitest';
describe('validatePublishableDocument (pure)', () => {
    it('passes a page with a title and slug', () => {
        const r = validatePublishableDocument({ data: { title: 'About', slug: 'about' } });
        expect(r.errors).toEqual([]);
    });
    it('flags a missing title', () => {
        const r = validatePublishableDocument({ data: { slug: 'about' } });
        expect(r.errors.some((e) => /title/i.test(e))).toBe(true);
    });
    it('flags a missing URL (no slug and no path)', () => {
        const r = validatePublishableDocument({ data: { title: 'About' } });
        expect(r.errors.some((e) => /url|slug|path/i.test(e))).toBe(true);
    });
    it('accepts data.path in place of a slug', () => {
        const r = validatePublishableDocument({ data: { title: 'Home', path: '/' } });
        expect(r.errors).toEqual([]);
    });
    it('warns (not errors) on a missing meta description', () => {
        const r = validatePublishableDocument({ data: { title: 'About', slug: 'about' } });
        expect(r.errors).toEqual([]);
        expect(r.warnings.some((w) => /description/i.test(w))).toBe(true);
    });
    it('rejects a malformed slug', () => {
        const r = validatePublishableDocument({ data: { title: 'About', slug: 'About Us!' } });
        expect(r.errors.some((e) => /slug/i.test(e))).toBe(true);
    });
    it('rejects a reserved slug', () => {
        const r = validatePublishableDocument({ data: { title: 'Admin', slug: 'admin' } });
        expect(r.errors.some((e) => /reserved/i.test(e))).toBe(true);
    });
    it('accepts a page that uses path with no slug (slug check skipped)', () => {
        const r = validatePublishableDocument({ data: { title: 'Home', path: '/' } });
        expect(r.errors).toEqual([]);
    });
});
describe('resolvePublishValidationMode', () => {
    it('defaults to block', () => {
        expect(resolvePublishValidationMode(null)).toBe('block');
        expect(resolvePublishValidationMode({ seo: {} })).toBe('block');
    });
    it('honors warn/off', () => {
        expect(resolvePublishValidationMode({ seo: { publishValidation: 'warn' } })).toBe('warn');
        expect(resolvePublishValidationMode({ seo: { publishValidation: 'off' } })).toBe('off');
    });
});
describe('isGatedContentCollection', () => {
    it('gates page/post, skips everything else', () => {
        expect(isGatedContentCollection({ slug: 'p', type: 'page' })).toBe(true);
        expect(isGatedContentCollection({ slug: 'b', type: 'post' })).toBe(true);
        expect(isGatedContentCollection({ slug: 'x' })).toBe(false);
        expect(isGatedContentCollection(null)).toBe(false);
    });
});
describe('enforcePublishValidation', () => {
    const pageDef = { slug: 'pages', type: 'page' };
    it('throws in block mode on hard errors', () => {
        expect(() => enforcePublishValidation({ collectionDef: pageDef, data: { slug: 'x' }, config: null })).toThrow(/cannot publish/i);
    });
    it('does not throw in warn mode', () => {
        expect(() => enforcePublishValidation({
            collectionDef: pageDef,
            data: { slug: 'x' },
            config: { seo: { publishValidation: 'warn' } },
        })).not.toThrow();
    });
    it('skips non-gated collections', () => {
        expect(() => enforcePublishValidation({
            collectionDef: { slug: 'forms' },
            data: {},
            config: null,
        })).not.toThrow();
    });
});
// --- Integration through the action layer -----------------------------------
function createMockDB() {
    const docs = new Map();
    return {
        document: {
            findFirst: vi.fn(async ({ where }) => {
                const d = docs.get(where.id);
                if (!d)
                    return null;
                if (where.deletedAt === null && d.deletedAt !== null)
                    return null;
                return { ...d };
            }),
        },
        version: { create: vi.fn(async () => ({})) },
        $transaction: vi.fn(async (fn) => fn({
            document: {
                create: vi.fn(async ({ data }) => {
                    const doc = { id: `doc-${docs.size}`, ...data, deletedAt: null };
                    docs.set(doc.id, doc);
                    return doc;
                }),
                update: vi.fn(async ({ where, data }) => {
                    const doc = docs.get(where.id);
                    Object.assign(doc, data);
                    return { ...doc };
                }),
            },
            version: { create: vi.fn(async () => ({})) },
            redirect: {
                findMany: vi.fn(async () => []),
                upsert: vi.fn(),
                update: vi.fn(),
                delete: vi.fn(),
            },
        })),
        redirect: { findMany: vi.fn(async () => []) },
        _docs: docs,
        _seed(doc) {
            docs.set(doc.id, doc);
        },
    };
}
function ctx(db) {
    return { userId: 'u1', role: 'ADMIN', db };
}
describe('publish gate through createDocument/updateDocument', () => {
    beforeEach(() => {
        setActuateConfig({
            collections: { pages: { slug: 'pages', type: 'page', fields: {} } },
        });
    });
    afterEach(() => setActuateConfig({}));
    it('blocks creating a published page with no title', async () => {
        const db = createMockDB();
        await expect(createDocument('pages', { slug: 'no-title', status: 'PUBLISHED' }, ctx(db))).rejects.toThrow(/cannot publish/i);
    });
    it('allows creating a published page with title + slug', async () => {
        const db = createMockDB();
        await expect(createDocument('pages', { title: 'OK', slug: 'ok', status: 'PUBLISHED' }, ctx(db))).resolves.toMatchObject({ status: 'PUBLISHED' });
    });
    it('allows saving an untitled DRAFT (gate only fires on publish)', async () => {
        const db = createMockDB();
        await expect(createDocument('pages', { slug: 'draft-no-title' }, ctx(db))).resolves.toMatchObject({ status: 'DRAFT' });
    });
    it('blocks an update that would publish a page lacking a URL', async () => {
        const db = createMockDB();
        db._seed({
            id: 'd1',
            collection: 'pages',
            status: 'DRAFT',
            slug: null,
            data: { title: 'Has title' },
            deletedAt: null,
        });
        await expect(updateDocument('pages', 'd1', { status: 'PUBLISHED' }, ctx(db))).rejects.toThrow(/slug or path/i);
    });
    it('does not gate non page/post collections', async () => {
        setActuateConfig({
            collections: { widgets: { slug: 'widgets', fields: {} } },
        });
        const db = createMockDB();
        await expect(createDocument('widgets', { status: 'PUBLISHED' }, ctx(db))).resolves.toMatchObject({ status: 'PUBLISHED' });
    });
});
//# sourceMappingURL=publish.test.js.map