import { ACTUATE_TAG_ROOT, actuateTag, cachedRead } from '../../cache/http.js';
import { coercePublicNavItems } from '../../site.js';
import { getActuateConfig } from '../../config/runtime.js';
import { guardedDb } from '../guarded-db.js';
import { json, jsonWithCache, errorResponse, internalError, requireAuth } from '../route-helpers.js';
export function registerGlobalRoutes(router) {
    const db = guardedDb;
    // ---------------------------------------------------------------------------
    // Globals routes
    // ---------------------------------------------------------------------------
    router.get('/public/globals/:slug', async (_request, params) => {
        try {
            const slug = params.slug;
            const globalConfig = getActuateConfig()?.globals?.[slug];
            if (!globalConfig) {
                return errorResponse('Global not found', 404);
            }
            const doc = await db().document.findFirst({
                // Globals are singleton site config and intentionally NOT PUBLISHED-gated
                // (many installs never "publish" a global). But an ARCHIVED global is
                // explicitly retired, so exclude it from the public surface.
                where: { collection: slug, deletedAt: null, status: { not: 'ARCHIVED' } },
            });
            if (!doc) {
                return errorResponse('Global not found', 404);
            }
            // Globals routed through `/public/globals/:slug` are by definition
            // public site data — when no `access.read` is set we default to
            // allowed. Integrators that want to gate a global must set
            // `access.read` explicitly (returning `false` for public).
            const readAccess = globalConfig.access?.read;
            const allowed = readAccess ? await readAccess({ user: null, doc }) : true;
            if (!allowed) {
                return errorResponse('Forbidden', 403);
            }
            return json({
                data: doc.data && typeof doc.data === 'object' ? doc.data : {},
            });
        }
        catch (err) {
            return internalError(err);
        }
    });
    // Public navigation menu — site chrome (like globals/brand), so unauthenticated
    // and not status-gated. Look up the `navigations` collection document by slug
    // and return a clean { name, slug, location, items } tree the public site
    // layout renders into a header/footer. Safe when the navigation plugin isn't
    // installed: the query simply finds no document and returns 404.
    router.get('/public/navigations/:slug', async (_request, params) => {
        try {
            const slug = params.slug;
            const doc = await db().document.findFirst({
                where: {
                    collection: 'navigations',
                    deletedAt: null,
                    // Site chrome: not PUBLISHED-gated, but never serve a retired (ARCHIVED) menu.
                    status: { not: 'ARCHIVED' },
                    OR: [{ slug }, { data: { path: ['slug'], equals: slug } }],
                },
                orderBy: { updatedAt: 'desc' },
            });
            if (!doc)
                return errorResponse('Navigation not found', 404);
            const data = doc.data && typeof doc.data === 'object' ? doc.data : {};
            return json({
                data: {
                    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),
                },
            });
        }
        catch (err) {
            return internalError(err);
        }
    });
    // Public brand: resolved logos + favicon for the public frontend. No auth —
    // brand assets are public site data. Only the PUBLIC brand view + favicon are
    // exposed here (never the admin-only brand) so a white-labeled admin doesn't
    // leak through the public API.
    router.get('/public/brand', async (request) => {
        try {
            const { resolveBrand } = await import('../../appearance/index.js');
            const resolved = await resolveBrand(db(), null);
            return cachedRead(request, {
                cache: getActuateConfig()?.cache,
                tags: [ACTUATE_TAG_ROOT, actuateTag('global', 'settings')],
                wrap: jsonWithCache,
                build: async () => ({
                    data: { public: resolved.public, favicon: resolved.favicon },
                }),
            });
        }
        catch (err) {
            return internalError(err, 'public/brand GET');
        }
    });
    // Authenticated appearance read: stored appearance + brand settings plus the
    // fully resolved admin/public/favicon views (with asset URLs) so the admin
    // Appearance tab can render live previews. View-only auth — writes go through
    // PUT /globals/settings (ADMIN_ROLES), so editors can view but not save.
    router.get('/appearance', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const { getAppearanceSettings, getBrandSettings, resolveBrand } = await import('../../appearance/index.js');
            const [appearance, brand, resolved] = await Promise.all([
                getAppearanceSettings(db()),
                getBrandSettings(db()),
                resolveBrand(db(), null),
            ]);
            return json({
                data: {
                    appearance,
                    brand,
                    resolved: { admin: resolved.admin, public: resolved.public, favicon: resolved.favicon },
                    // Direct per-asset URLs so the editor shows each field's actual
                    // asset (not the resolved fallback chain).
                    assets: resolved.assets,
                    siteTitle: resolved.siteTitle,
                },
            });
        }
        catch (err) {
            return internalError(err, 'appearance GET');
        }
    });
}
//# sourceMappingURL=globals.js.map