import { describe, expect, it } from 'vitest';
import { summarizeCollectionFields } from '../../api/collection-introspection.js';
function byName(fields) {
    return new Map(fields.map((f) => [f.name, f]));
}
describe('summarizeCollectionFields (WS-B4 deep introspection)', () => {
    it('returns [] for a missing or non-object field map', () => {
        expect(summarizeCollectionFields(undefined)).toEqual([]);
        expect(summarizeCollectionFields(null)).toEqual([]);
        expect(summarizeCollectionFields([])).toEqual([]);
        expect(summarizeCollectionFields('nope')).toEqual([]);
    });
    it('summarizes scalar fields to { name, type, required }', () => {
        const out = byName(summarizeCollectionFields({
            title: { type: 'text', required: true },
            body: { type: 'richText' },
        }));
        expect(out.get('title')).toEqual({ name: 'title', type: 'text', required: true });
        expect(out.get('body')).toEqual({ name: 'body', type: 'richText', required: false });
    });
    it('surfaces relationTo / hasMany / options when present', () => {
        const out = byName(summarizeCollectionFields({
            author: { type: 'relationship', relationTo: 'team' },
            related: { type: 'relationship', relationTo: ['posts', 'pages'], hasMany: true },
            status: {
                type: 'select',
                options: [
                    { label: 'Draft', value: 'draft' },
                    { label: 'Live', value: 'live' },
                ],
            },
        }));
        expect(out.get('author')?.relationTo).toBe('team');
        expect(out.get('author')?.hasMany).toBeUndefined();
        expect(out.get('related')?.relationTo).toEqual(['posts', 'pages']);
        expect(out.get('related')?.hasMany).toBe(true);
        expect(out.get('status')?.options).toEqual([
            { label: 'Draft', value: 'draft' },
            { label: 'Live', value: 'live' },
        ]);
    });
    it('recurses into array element subfields and reports row bounds', () => {
        const out = byName(summarizeCollectionFields({
            gallery: {
                type: 'array',
                minRows: 1,
                maxRows: 6,
                fields: {
                    image: { type: 'media', required: true },
                    caption: { type: 'text' },
                },
            },
        }));
        const gallery = out.get('gallery');
        expect(gallery.type).toBe('array');
        expect(gallery.minRows).toBe(1);
        expect(gallery.maxRows).toBe(6);
        expect(byName(gallery.fields ?? []).get('image')).toEqual({
            name: 'image',
            type: 'media',
            required: true,
        });
        expect(byName(gallery.fields ?? []).get('caption')?.required).toBe(false);
    });
    it('recurses into blocks variants keyed by slug, with labels and subfields', () => {
        const out = byName(summarizeCollectionFields({
            layout: {
                type: 'blocks',
                blocks: [
                    {
                        slug: 'hero',
                        labels: { singular: 'Hero', plural: 'Heroes' },
                        fields: { heading: { type: 'text', required: true } },
                    },
                    {
                        slug: 'cta',
                        labels: { singular: 'Call To Action', plural: 'CTAs' },
                        fields: { url: { type: 'url' }, label: { type: 'text' } },
                    },
                ],
            },
        }));
        const layout = out.get('layout');
        expect(layout.type).toBe('blocks');
        expect(layout.blocks).toHaveLength(2);
        const hero = layout.blocks.find((b) => b.slug === 'hero');
        expect(hero.label).toBe('Hero');
        expect(byName(hero.fields).get('heading')).toEqual({
            name: 'heading',
            type: 'text',
            required: true,
        });
        const cta = layout.blocks.find((b) => b.slug === 'cta');
        expect(cta.fields.map((f) => f.name).sort()).toEqual(['label', 'url']);
    });
    it('handles malformed block entries without throwing', () => {
        const out = byName(summarizeCollectionFields({
            layout: {
                type: 'blocks',
                blocks: [null, 'nope', { slug: 'ok', fields: { x: { type: 'text' } } }],
            },
        }));
        const layout = out.get('layout');
        // Only the one well-formed block survives; no label since none provided.
        expect(layout.blocks).toHaveLength(1);
        expect(layout.blocks[0].slug).toBe('ok');
        expect(layout.blocks[0].label).toBeUndefined();
    });
    it('caps recursion depth defensively (no stack blow-up on deep nesting)', () => {
        // Build an array nested far deeper than MAX_DEPTH (5).
        let leaf = { type: 'text' };
        for (let i = 0; i < 12; i++) {
            leaf = { type: 'array', fields: { child: leaf } };
        }
        const out = summarizeCollectionFields({ deep: leaf });
        // Walk down; at some point `fields` stops being populated (the cap),
        // proving we don't recurse forever.
        let node = out[0];
        let levels = 0;
        while (node?.fields && node.fields.length > 0) {
            node = node.fields[0];
            levels++;
            if (levels > 20)
                throw new Error('recursion not capped');
        }
        expect(levels).toBeLessThanOrEqual(6);
    });
});
//# sourceMappingURL=collection-introspection.test.js.map