/**
 * Read-time media enrichment for the `/resolve` endpoint (WS-E E3).
 *
 * Section content stores image references as plain URL strings (the value the
 * media picker hands back — usually a public blob URL). The public renderer can
 * lay out images without shift and fall back to library alt text if it also
 * knows each image's intrinsic `width`/`height` and `altText`. Rather than
 * change the stored shape, we look those up from `actuate_media` at read time
 * and attach them as optional sibling fields the renderers already read:
 *
 *   - `feature` sections gain `imageWidth` / `imageHeight`; empty `imageAlt`
 *     is backfilled from the library.
 *   - `gallery` rows gain `width` / `height`; empty `alt` is backfilled.
 *
 * This is purely additive and non-destructive — the stored document is never
 * mutated, only the resolve response. The pure functions here are unit-tested;
 * the (mockable) DB lookup is wired in the handler.
 */
function isObj(v) {
    return typeof v === 'object' && v !== null && !Array.isArray(v);
}
function asUrl(v) {
    if (typeof v !== 'string' || !v)
        return null;
    const ok = v.startsWith('/') || /^https?:\/\//i.test(v);
    return ok ? v : null;
}
/**
 * Collect the distinct image URLs referenced by `feature` and `gallery`
 * sections, so the caller can batch-load their media metadata in one query.
 */
export function collectSectionImageUrls(sections) {
    if (!Array.isArray(sections))
        return [];
    const urls = new Set();
    for (const section of sections) {
        if (!isObj(section))
            continue;
        const content = isObj(section.content) ? section.content : {};
        if (section.sectionType === 'feature') {
            const url = asUrl(content.imageUrl);
            if (url)
                urls.add(url);
        }
        else if (section.sectionType === 'gallery') {
            const images = Array.isArray(content.images) ? content.images : [];
            for (const row of images) {
                if (!isObj(row))
                    continue;
                const url = asUrl(row.url);
                if (url)
                    urls.add(url);
            }
        }
    }
    return [...urls];
}
function num(v) {
    return typeof v === 'number' && Number.isFinite(v) ? v : null;
}
function nonEmpty(v) {
    return typeof v === 'string' && v.trim().length > 0;
}
/**
 * Return a new sections array with intrinsic dimensions + library alt text
 * applied from `lookup`. Sections without a matching image are returned as-is
 * (by reference); enriched sections get a shallow-cloned `content`.
 */
export function applyMediaMeta(sections, lookup) {
    if (!Array.isArray(sections))
        return [];
    if (lookup.size === 0)
        return sections;
    return sections.map((section) => {
        if (!isObj(section))
            return section;
        const content = isObj(section.content) ? section.content : null;
        if (!content)
            return section;
        if (section.sectionType === 'feature') {
            const url = asUrl(content.imageUrl);
            const meta = url ? lookup.get(url) : undefined;
            if (!meta)
                return section;
            const next = { ...content };
            if (num(meta.width) !== null && num(next.imageWidth) === null)
                next.imageWidth = meta.width;
            if (num(meta.height) !== null && num(next.imageHeight) === null) {
                next.imageHeight = meta.height;
            }
            if (!nonEmpty(next.imageAlt) && nonEmpty(meta.alt))
                next.imageAlt = meta.alt;
            return { ...section, content: next };
        }
        if (section.sectionType === 'gallery') {
            const images = Array.isArray(content.images) ? content.images : null;
            if (!images)
                return section;
            let touched = false;
            const nextImages = images.map((row) => {
                if (!isObj(row))
                    return row;
                const url = asUrl(row.url);
                const meta = url ? lookup.get(url) : undefined;
                if (!meta)
                    return row;
                const nextRow = { ...row };
                if (num(meta.width) !== null && num(nextRow.width) === null)
                    nextRow.width = meta.width;
                if (num(meta.height) !== null && num(nextRow.height) === null)
                    nextRow.height = meta.height;
                if (!nonEmpty(nextRow.alt) && nonEmpty(meta.alt))
                    nextRow.alt = meta.alt;
                touched = true;
                return nextRow;
            });
            if (!touched)
                return section;
            return { ...section, content: { ...content, images: nextImages } };
        }
        return section;
    });
}
//# sourceMappingURL=media-enrich.js.map