import { describe, expect, it } from 'vitest';
import { layoutTreeToSections } from '../bridge.js';
import { coerceSections } from '../helpers.js';
import { isKnownSectionType } from '../registry.js';
/**
 * WS-A5: the page-builder tree (Model B, `data._layout`) → canonical
 * `PageSection[]` (Model A) bridge. These lock in that existing page-builder
 * content is surfaced through the canonical renderer rather than stranded.
 */
/** Minimal builder-tree factory helpers (mirror page-builder/types shapes). */
function block(blockType, data) {
    return { id: `b_${blockType}`, type: 'block', settings: { blockType }, data };
}
function column(children) {
    return { id: 'col', type: 'column', settings: { width: 12 }, children };
}
function row(children) {
    return { id: 'row', type: 'row', settings: {}, children };
}
function section(children, settings = {}) {
    return { id: 'sec', type: 'section', settings, children };
}
function page(children) {
    return { id: 'page', type: 'page', children };
}
describe('layoutTreeToSections', () => {
    it('maps a hero block to a canonical hero section', () => {
        const tree = page([
            section([
                row([
                    column([
                        block('hero', {
                            title: 'Big headline',
                            subtitle: 'Supporting copy',
                            ctaText: 'Start',
                            ctaLink: '/start',
                        }),
                    ]),
                ]),
            ]),
        ]);
        const sections = layoutTreeToSections(tree);
        expect(sections).toHaveLength(1);
        expect(sections[0].sectionType).toBe('hero');
        expect(sections[0].content).toMatchObject({
            heading: 'Big headline',
            body: 'Supporting copy',
            primaryButtonLabel: 'Start',
            primaryButtonUrl: '/start',
        });
    });
    it('flattens nested layout into ordered sections (document order preserved)', () => {
        const tree = page([
            section([row([column([block('hero', { title: 'A' })])])]),
            section([
                row([
                    column([block('text', { heading: 'B', body: 'b' })]),
                    column([block('cta', { heading: 'C', buttonText: 'Go', buttonLink: '/c' })]),
                ]),
            ]),
        ]);
        const sections = layoutTreeToSections(tree);
        expect(sections.map((s) => s.sectionType)).toEqual(['hero', 'text', 'cta']);
    });
    it('degrades unknown/complex block types to a text section that surfaces content', () => {
        const tree = page([
            section([
                row([
                    column([
                        block('cards', {
                            items: [
                                { title: 'Card one', description: 'first' },
                                { title: 'Card two', description: 'second' },
                            ],
                        }),
                    ]),
                ]),
            ]),
        ]);
        const sections = layoutTreeToSections(tree);
        expect(sections).toHaveLength(1);
        expect(sections[0].sectionType).toBe('text');
        const body = String(sections[0].content.body);
        expect(body).toContain('Card one');
        expect(body).toContain('first');
        expect(body).toContain('Card two');
    });
    it('maps image and gallery blocks to their closest canonical types', () => {
        const tree = page([
            section([
                row([
                    column([
                        block('image', { src: { url: 'https://x/i.png' }, alt: 'pic', caption: 'cap' }),
                        block('gallery', {
                            images: [
                                { src: 'https://x/1.png', alt: 'one', caption: 'c1' },
                                { src: { url: 'https://x/2.png' }, alt: 'two' },
                            ],
                        }),
                    ]),
                ]),
            ]),
        ]);
        const sections = layoutTreeToSections(tree);
        expect(sections.map((s) => s.sectionType)).toEqual(['feature', 'gallery']);
        expect(sections[0].content).toMatchObject({
            imageUrl: 'https://x/i.png',
            imageAlt: 'pic',
            body: 'cap',
        });
        expect(sections[1].content.images).toEqual([
            { url: 'https://x/1.png', alt: 'one', caption: 'c1' },
            { url: 'https://x/2.png', alt: 'two' },
        ]);
    });
    it('propagates the enclosing section anchor + hidden visibility to derived sections', () => {
        const tree = page([
            section([row([column([block('text', { heading: 'H' })])])], {
                htmlId: 'about',
                visibility: 'hidden',
            }),
        ]);
        const [s] = layoutTreeToSections(tree);
        expect(s.settings.anchorId).toBe('about');
        expect(s.visible).toBe(false);
    });
    it('skips savedSectionRef nodes (cannot resolve without a DB lookup)', () => {
        const tree = page([
            { id: 'ref', type: 'savedSectionRef', settings: { refId: 'saved_1' } },
            section([row([column([block('text', { heading: 'Kept' })])])]),
        ]);
        const sections = layoutTreeToSections(tree);
        expect(sections).toHaveLength(1);
        expect(sections[0].content.heading).toBe('Kept');
    });
    it('every produced section is a known, renderable type (survives coerceSections)', () => {
        const tree = page([
            section([
                row([
                    column([
                        block('hero', { title: 'A' }),
                        block('faq', { items: [{ question: 'q', answer: 'a' }] }),
                        block('video', { url: 'https://x/v.mp4' }),
                    ]),
                ]),
            ]),
        ]);
        const sections = layoutTreeToSections(tree);
        for (const s of sections)
            expect(isKnownSectionType(s.sectionType)).toBe(true);
        // coerceSections drops unknown types — the bridge output must survive it intact.
        expect(coerceSections(sections)).toHaveLength(sections.length);
    });
    it('never throws on malformed/partial input', () => {
        expect(layoutTreeToSections(null)).toEqual([]);
        expect(layoutTreeToSections(undefined)).toEqual([]);
        expect(layoutTreeToSections('not a tree')).toEqual([]);
        expect(layoutTreeToSections({})).toEqual([]);
        expect(layoutTreeToSections([])).toEqual([]);
        expect(layoutTreeToSections({ type: 'page' })).toEqual([]);
        expect(layoutTreeToSections({ type: 'page', children: [null, 42, {}] })).toEqual([]);
    });
    it('tolerates a block placed directly under the page node', () => {
        const tree = page([block('text', { heading: 'Loose', body: 'block' })]);
        const sections = layoutTreeToSections(tree);
        expect(sections).toHaveLength(1);
        expect(sections[0].sectionType).toBe('text');
        expect(sections[0].visible).toBe(true);
    });
});
//# sourceMappingURL=bridge.test.js.map