/**
 * Coerce stored navigation `data.items` (open JSON) into a clean public tree.
 * Drops anything without a usable label, defends against deep recursion, and
 * strips fields a public consumer shouldn't need (e.g. internal ids). Shared by
 * the public REST handler and the DB-backed server client so both expose an
 * identical shape.
 */
export function coercePublicNavItems(value, depth = 0) {
    if (!Array.isArray(value) || depth > 6)
        return [];
    const out = [];
    for (const raw of value) {
        if (!raw || typeof raw !== 'object')
            continue;
        const obj = raw;
        const label = typeof obj.label === 'string' ? obj.label.trim() : '';
        if (!label)
            continue;
        const item = {
            label,
            url: typeof obj.url === 'string' ? obj.url : '',
        };
        if (obj.target === '_blank' || obj.target === '_self')
            item.target = obj.target;
        const children = coercePublicNavItems(obj.children, depth + 1);
        if (children.length > 0)
            item.children = children;
        out.push(item);
    }
    return out;
}
const DEFAULT_API_PATH = '/api/cms';
function trimTrailingSlash(value) {
    return value.replace(/\/+$/, '');
}
function normalizeApiPath(apiPath) {
    const path = apiPath.startsWith('/') ? apiPath : `/${apiPath}`;
    return trimTrailingSlash(path);
}
/**
 * Resolve a base URL, in order of preference:
 *   1. explicit `baseUrl` option
 *   2. `NEXT_PUBLIC_SITE_URL`
 *   3. `VERCEL_URL` (with `https://` prefix; Vercel only sets the host)
 *   4. empty string (relative URL — only safe in browsers and Next.js
 *      route handlers; will throw under bare Node `fetch`)
 */
function resolveBaseUrl(baseUrl) {
    if (baseUrl)
        return trimTrailingSlash(baseUrl);
    const env = process.env;
    if (env.NEXT_PUBLIC_SITE_URL)
        return trimTrailingSlash(env.NEXT_PUBLIC_SITE_URL);
    if (env.VERCEL_URL)
        return `https://${env.VERCEL_URL}`;
    return '';
}
function buildBaseUrl(baseUrl, apiPath) {
    const origin = resolveBaseUrl(baseUrl);
    return `${origin}${normalizeApiPath(apiPath ?? DEFAULT_API_PATH)}`;
}
async function readApiData(response) {
    if (response.status === 404)
        return null;
    if (!response.ok) {
        throw new Error(`Actuate CMS API error: ${response.status} ${response.statusText}`);
    }
    const body = (await response.json());
    if (body && typeof body === 'object' && 'data' in body) {
        return body.data ?? null;
    }
    return body;
}
export function createSiteClient(options = {}) {
    const fetchImpl = options.fetch ?? fetch;
    const apiBase = buildBaseUrl(options.baseUrl, options.apiPath);
    const headers = {
        'Content-Type': 'application/json',
    };
    if (options.apiKey) {
        headers.Authorization = `Bearer ${options.apiKey}`;
    }
    return {
        async getGlobal(slug) {
            const response = await fetchImpl(`${apiBase}/public/globals/${encodeURIComponent(slug)}`, {
                headers,
            });
            return readApiData(response);
        },
        async resolveDocument(path) {
            const response = await fetchImpl(`${apiBase}/resolve?path=${encodeURIComponent(path)}`, {
                headers,
            });
            if (response.status === 404)
                return null;
            if (!response.ok) {
                throw new Error(`Actuate CMS API error: ${response.status} ${response.statusText}`);
            }
            return response.json();
        },
        async getNavigation(slug) {
            const response = await fetchImpl(`${apiBase}/public/navigations/${encodeURIComponent(slug)}`, { headers });
            return readApiData(response);
        },
    };
}
function asString(value) {
    return typeof value === 'string' && value.length > 0 ? value : undefined;
}
function asNullableString(value) {
    return typeof value === 'string' ? value : null;
}
function asNullableNumber(value) {
    return typeof value === 'number' && Number.isFinite(value) ? value : null;
}
function looksLikeUrl(value) {
    return value.startsWith('/') || /^https?:\/\//i.test(value) || value.startsWith('data:');
}
export function normalizeMedia(value) {
    if (!value)
        return null;
    if (typeof value === 'string') {
        if (!looksLikeUrl(value))
            return null;
        return {
            url: value,
            alt: null,
            title: null,
            width: null,
            height: null,
            storageKey: null,
        };
    }
    const url = asString(value.url);
    if (!url)
        return null;
    const id = asString(value.id);
    return {
        ...(id ? { id } : {}),
        url,
        alt: asNullableString(value.alt),
        title: asNullableString(value.title),
        width: asNullableNumber(value.width),
        height: asNullableNumber(value.height),
        storageKey: asNullableString(value.storageKey),
    };
}
export async function resolveMedia(value, options = {}) {
    const normalized = normalizeMedia(value);
    if (normalized)
        return normalized;
    if (typeof value === 'string' && options.resolveById) {
        const resolved = await options.resolveById(value);
        return normalizeMedia(resolved);
    }
    return null;
}
//# sourceMappingURL=site.js.map