import { listDocuments, getDocument, createDocument, updateDocument, deleteDocument, } from '../../actions.js';
import { logEvent } from '../../security/audit.js';
import { applyFieldAccess } from '../../security/access.js';
import { ACTUATE_TAG_ROOT, actuateTag, cachedRead } from '../../cache/http.js';
import { notifyPreviewUpdate } from '../../preview/event-bus.js';
import { getActuateConfig } from '../../config/runtime.js';
import { guardedDb } from '../guarded-db.js';
import { maybePopulate, json, jsonWithCache, errorResponse, internalError, clampPageSize, requireAuth, requireCollectionScope, buildActionContext, } from '../route-helpers.js';
export function registerDocumentRoutes(router) {
    const db = guardedDb;
    // ---------------------------------------------------------------------------
    // Document routes
    // ---------------------------------------------------------------------------
    router.get('/collections/:slug', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const scopeErr = requireCollectionScope(auth.session, params.slug, 'read');
            if (scopeErr)
                return scopeErr;
            return cachedRead(request, {
                cache: getActuateConfig()?.cache,
                tags: [ACTUATE_TAG_ROOT, actuateTag('collection', params.slug)],
                wrap: jsonWithCache,
                build: async () => {
                    const url = new URL(request.url);
                    const ctx = buildActionContext(auth.session, db(), url.searchParams.get('locale') ?? undefined);
                    const result = await listDocuments({
                        collection: params.slug,
                        page: Number(url.searchParams.get('page')) || 1,
                        pageSize: clampPageSize(url.searchParams.get('pageSize')),
                        sort: url.searchParams.get('sort') ?? undefined,
                        order: url.searchParams.get('order') ?? undefined,
                        status: url.searchParams.get('status') ?? undefined,
                        locale: url.searchParams.get('locale') ?? undefined,
                        folderId: url.searchParams.get('folderId') ?? undefined,
                        // Exact slug filter — powers slug→id resolution for the MCP
                        // relationship resolver (WS-C C2). Additive: omitted ⇒ no filter.
                        slug: url.searchParams.get('slug') ?? undefined,
                    }, ctx);
                    const collectionConfig = getActuateConfig()?.collections?.[params.slug];
                    const fields = collectionConfig?.fields;
                    if (fields && result.docs.length > 0) {
                        const user = { id: auth.session.userId, role: auth.session.role };
                        result.docs = await Promise.all(result.docs.map(async (doc) => {
                            if (doc.data && typeof doc.data === 'object') {
                                return {
                                    ...doc,
                                    data: await applyFieldAccess('read', fields, doc.data, user),
                                };
                            }
                            return doc;
                        }));
                    }
                    return { data: result };
                },
            });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.get('/collections/:slug/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const scopeErr = requireCollectionScope(auth.session, params.slug, 'read');
            if (scopeErr)
                return scopeErr;
            return cachedRead(request, {
                cache: getActuateConfig()?.cache,
                tags: [
                    ACTUATE_TAG_ROOT,
                    actuateTag('collection', params.slug),
                    actuateTag('doc', params.id),
                ],
                wrap: jsonWithCache,
                build: async () => {
                    const ctx = buildActionContext(auth.session, db());
                    const doc = await getDocument(params.slug, params.id, ctx);
                    if (!doc) {
                        // Returning a Response short-circuits the cache layer — we
                        // never cache 404s. The next request gets a fresh DB lookup
                        // so a doc that's restored from soft-delete is visible
                        // immediately.
                        return errorResponse('Document not found', 404);
                    }
                    // `getDocument` already lifts `_layout` / `_pageSettings` to
                    // the top-level page builder envelope and strips internal keys
                    // from `data`. Field-level access has been applied as well.
                    //
                    // Opt-in relation population (?populate=author,relatedPosts |
                    // *) replaces stored IDs with reference summaries. The
                    // `?populate=` param is part of the cache key (URL-derived),
                    // so populated and non-populated reads cache independently.
                    const populated = await maybePopulate(request, params.slug, doc, db());
                    return { data: populated };
                },
            });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.post('/collections/:slug', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const scopeErr = requireCollectionScope(auth.session, params.slug, 'create');
            if (scopeErr)
                return scopeErr;
            const body = (await request.json());
            const ctx = buildActionContext(auth.session, db());
            const doc = await createDocument(params.slug, body, ctx);
            await logEvent({
                event: 'document_created',
                userId: auth.session.userId,
                details: { collection: params.slug, documentId: doc?.id },
            });
            return json({ data: doc }, 201);
        }
        catch (err) {
            return internalError(err, 'create document');
        }
    });
    router.put('/collections/:slug/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const scopeErr = requireCollectionScope(auth.session, params.slug, 'update');
            if (scopeErr)
                return scopeErr;
            const body = (await request.json());
            const ctx = buildActionContext(auth.session, db());
            const doc = await updateDocument(params.slug, params.id, body, ctx);
            await logEvent({
                event: 'document_updated',
                userId: auth.session.userId,
                details: { collection: params.slug, documentId: params.id },
            });
            // Push to any open live-preview SSE streams. No-op when no admin is
            // watching the document; the bus drops the call cheaply.
            notifyPreviewUpdate(params.slug, params.id, {
                values: doc.data,
                status: doc.status,
                updatedAt: doc.updatedAt?.toISOString?.(),
            });
            return json({ data: doc });
        }
        catch (err) {
            return internalError(err, 'update document');
        }
    });
    router.delete('/collections/:slug/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const scopeErr = requireCollectionScope(auth.session, params.slug, 'delete');
            if (scopeErr)
                return scopeErr;
            const ctx = buildActionContext(auth.session, db());
            await deleteDocument(params.slug, params.id, ctx);
            await logEvent({
                event: 'document_deleted',
                userId: auth.session.userId,
                details: { collection: params.slug, documentId: params.id },
            });
            return json({ data: { success: true } });
        }
        catch (err) {
            return internalError(err, 'delete document');
        }
    });
}
//# sourceMappingURL=documents.js.map