import { coercePublicNavItems, resolveMedia } from './site.js';
/**
 * Build the server-side Site client. The supplied `db` only needs a tiny
 * subset of the Prisma surface (`document`, `media`) — that lets us accept
 * generated PrismaClient instances from any consumer schema without forcing
 * a hard type dependency.
 */
export function createServerSiteClient(db, config = {}) {
    if (!db || typeof db !== 'object') {
        throw new Error('createServerSiteClient: `db` must be a Prisma-compatible client');
    }
    async function getGlobal(slug) {
        const globalConfig = config.globals?.[slug];
        if (!db.document?.findFirst)
            return null;
        const doc = await db.document.findFirst({
            where: { collection: slug, deletedAt: null },
        });
        if (!doc)
            return null;
        // Honor the same access policy the public REST endpoint enforces. When
        // no policy is configured we default to "public" — globals routed through
        // `getGlobal()` are by definition public site data; integrators that want
        // gating should set `access.read` explicitly.
        if (globalConfig?.access?.read) {
            const allowed = await globalConfig.access.read({ user: null, doc });
            if (!allowed)
                return null;
        }
        return (doc.data && typeof doc.data === 'object' ? doc.data : {});
    }
    async function resolveDocument(path) {
        const segments = path
            .replace(/^\/|\/$/g, '')
            .split('/')
            .filter(Boolean);
        const collectionDefs = Object.values(config.collections ?? {});
        let matchedCollection = null;
        let docSlug = null;
        if (segments.length === 0) {
            const pageCol = collectionDefs.find((c) => c.type === 'page' && !(c.urlPrefix ?? '').replace(/^\/|\/$/g, ''));
            matchedCollection = pageCol?.slug ?? 'pages';
            docSlug = 'home';
        }
        else {
            for (const col of collectionDefs) {
                const prefix = (col.urlPrefix ?? col.slug ?? '').replace(/^\/|\/$/g, '');
                if (prefix && segments.length >= 2) {
                    const prefixParts = prefix.split('/');
                    const pathPrefix = segments.slice(0, prefixParts.length).join('/');
                    if (pathPrefix === prefix) {
                        matchedCollection = col.slug ?? null;
                        docSlug = segments.slice(prefixParts.length).join('/');
                        break;
                    }
                }
                else if (!prefix && col.type === 'page') {
                    matchedCollection = col.slug ?? null;
                    docSlug = segments.join('/');
                }
            }
            if (!matchedCollection && segments.length === 1) {
                matchedCollection = 'pages';
                docSlug = segments[0];
            }
            if (!matchedCollection && segments.length >= 2) {
                matchedCollection = segments[0];
                docSlug = segments.slice(1).join('/');
            }
        }
        if (!matchedCollection || !docSlug)
            return null;
        const isRootPath = segments.length === 0;
        const doc = await db.document.findFirst({
            where: {
                collection: matchedCollection,
                deletedAt: null,
                status: 'PUBLISHED',
                OR: isRootPath
                    ? [
                        { data: { path: ['slug'], equals: 'home' } },
                        { data: { path: ['slug'], equals: 'index' } },
                        { slug: 'home' },
                        { slug: 'index' },
                    ]
                    : [{ data: { path: ['slug'], equals: docSlug } }, { slug: docSlug }],
            },
        });
        if (!doc)
            return null;
        const docData = doc.data && typeof doc.data === 'object' ? doc.data : {};
        // Strip CMS-internal keys (mirrors handler behavior for /resolve).
        const layout = docData._layout && typeof docData._layout === 'object'
            ? docData._layout
            : undefined;
        const { _layout: _omit, ...cleanData } = docData;
        return {
            data: {
                id: doc.id,
                collection: doc.collection,
                data: cleanData,
                status: doc.status,
                publishedAt: doc.publishedAt
                    ? doc.publishedAt instanceof Date
                        ? doc.publishedAt.toISOString()
                        : String(doc.publishedAt)
                    : null,
                structuredData: doc.structuredData,
            },
            ...(layout && Object.keys(layout).length > 0 ? { layout } : {}),
        };
    }
    async function getNavigation(slug) {
        if (!db.document?.findFirst)
            return null;
        const doc = await db.document.findFirst({
            where: {
                collection: 'navigations',
                deletedAt: null,
                OR: [{ slug }, { data: { path: ['slug'], equals: slug } }],
            },
            orderBy: { updatedAt: 'desc' },
        });
        if (!doc)
            return null;
        const data = doc.data && typeof doc.data === 'object' ? doc.data : {};
        return {
            name: typeof data.name === 'string' ? data.name : (doc.title ?? ''),
            slug: typeof data.slug === 'string' ? data.slug : slug,
            location: typeof data.location === 'string' ? data.location : null,
            items: coercePublicNavItems(data.items),
        };
    }
    return {
        getGlobal,
        resolveDocument,
        getNavigation,
        async resolveMedia(value) {
            const options = {
                resolveById: async (id) => {
                    if (!db.media?.findUnique)
                        return null;
                    try {
                        const row = await db.media.findUnique({ where: { id } });
                        if (!row)
                            return null;
                        return {
                            id: row.id,
                            url: row.storageKey,
                            alt: row.altText ?? null,
                            title: row.title ?? null,
                            width: row.width ?? null,
                            height: row.height ?? null,
                            storageKey: row.storageKey ?? null,
                        };
                    }
                    catch {
                        return null;
                    }
                },
            };
            return resolveMedia(value, options);
        },
    };
}
// Re-export the same helpers consumers were using before so a single import
// site covers both the fetch and Prisma flavours.
export { normalizeMedia, resolveMedia } from './site.js';
//# sourceMappingURL=server-site.js.map