import { logEvent } from '../../security/audit.js';
import { guardedDb } from '../guarded-db.js';
import { SECURITY_HEADERS, json, errorResponse, internalError, hasModel, modelNotAvailable, requireAuth, ADMIN_ROLES, requireRole, } from '../route-helpers.js';
export function registerWebhookRoutes(router) {
    const db = guardedDb;
    // ---------------------------------------------------------------------------
    // Webhook management routes
    // ---------------------------------------------------------------------------
    router.get('/webhooks', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const { listEndpoints } = await import('../../webhooks/index.js');
            const endpoints = await listEndpoints();
            return json({ data: endpoints });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.post('/webhooks', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const body = (await request.json());
            if (!body.url || !body.events?.length) {
                return errorResponse('url and events are required', 400);
            }
            const { createEndpoint } = await import('../../webhooks/index.js');
            const secret = body.secret || crypto.randomUUID();
            const endpoint = await createEndpoint({
                url: body.url,
                events: body.events,
                secret,
                name: body.name,
                active: body.active ?? true,
            });
            await logEvent({
                event: 'settings_changed',
                userId: auth.session.userId,
                details: { action: 'webhook_created', endpointId: endpoint.id, url: body.url },
            });
            return json({ data: endpoint }, 201);
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.put('/webhooks/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const body = (await request.json());
            const { updateEndpoint } = await import('../../webhooks/index.js');
            const updated = await updateEndpoint(params.id, body);
            return json({ data: updated });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.delete('/webhooks/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const { deleteEndpoint } = await import('../../webhooks/index.js');
            await deleteEndpoint(params.id);
            await logEvent({
                event: 'settings_changed',
                userId: auth.session.userId,
                details: { action: 'webhook_deleted', endpointId: params.id },
            });
            return json({ data: { success: true } });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.get('/webhooks/:id/deliveries', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const { getDeliveries } = await import('../../webhooks/index.js');
            const deliveries = await getDeliveries(params.id);
            return json({ data: deliveries });
        }
        catch (err) {
            return internalError(err);
        }
    });
    router.post('/webhooks/retry', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const { processRetries } = await import('../../webhooks/index.js');
            const result = await processRetries();
            return json({ data: result });
        }
        catch (err) {
            return internalError(err);
        }
    });
    // ---------------------------------------------------------------------------
    // Script Tags
    // ---------------------------------------------------------------------------
    router.get('/script-tags/resolve', async (request) => {
        try {
            const d = db();
            if (!hasModel(d, 'scriptTag'))
                return modelNotAvailable('ScriptTag');
            const url = new URL(request.url);
            const pathParam = url.searchParams.get('path') ?? '/';
            const normalizedPath = '/' + pathParam.replace(/^\/|\/$/g, '');
            const tags = await d.scriptTag.findMany({
                where: { enabled: true },
                orderBy: { priority: 'asc' },
            });
            const matched = [];
            for (const tag of tags) {
                if (tag.scope === 'site') {
                    matched.push(tag);
                    continue;
                }
                if (tag.scope === 'parents' && Array.isArray(tag.targetPaths)) {
                    for (const target of tag.targetPaths) {
                        const norm = '/' + target.replace(/^\/|\/$/g, '');
                        if (normalizedPath === norm || normalizedPath.startsWith(norm + '/')) {
                            matched.push(tag);
                            break;
                        }
                    }
                    continue;
                }
                if (tag.scope === 'urls' && Array.isArray(tag.targetPaths)) {
                    for (const target of tag.targetPaths) {
                        const norm = '/' + target.replace(/^\/|\/$/g, '');
                        if (normalizedPath === norm) {
                            matched.push(tag);
                            break;
                        }
                    }
                }
            }
            const grouped = { head: [], body_open: [], body_close: [] };
            for (const tag of matched) {
                const bucket = grouped[tag.placement];
                if (bucket) {
                    bucket.push(tag.code);
                }
            }
            // Public endpoint that fans out to many page renders. Add a short
            // edge cache so it doesn't become a per-request DB hit.
            const response = new Response(JSON.stringify(grouped), {
                status: 200,
                headers: { ...SECURITY_HEADERS, 'Content-Type': 'application/json' },
            });
            response.headers.set('Cache-Control', 'public, max-age=60, s-maxage=60, stale-while-revalidate=300');
            response.headers.set('Vary', 'path');
            return response;
        }
        catch (err) {
            return internalError(err, 'script-tags/resolve');
        }
    });
    router.get('/script-tags', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const d = db();
            if (!hasModel(d, 'scriptTag'))
                return modelNotAvailable('ScriptTag');
            const tags = await d.scriptTag.findMany({
                orderBy: { priority: 'asc' },
            });
            return json({ data: tags });
        }
        catch (err) {
            return internalError(err, 'script-tags list');
        }
    });
    router.post('/script-tags', async (request) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const d = db();
            if (!hasModel(d, 'scriptTag'))
                return modelNotAvailable('ScriptTag');
            const body = (await request.json());
            if (!body.name || !body.code || !body.placement) {
                return errorResponse('name, code, and placement are required', 400);
            }
            const validPlacements = ['head', 'body_open', 'body_close'];
            if (!validPlacements.includes(body.placement)) {
                return errorResponse('placement must be head, body_open, or body_close', 400);
            }
            const validScopes = ['site', 'parents', 'urls'];
            const scope = body.scope || 'site';
            if (!validScopes.includes(scope)) {
                return errorResponse('scope must be site, parents, or urls', 400);
            }
            const tag = await d.scriptTag.create({
                data: {
                    name: body.name,
                    code: body.code,
                    placement: body.placement,
                    scope,
                    targetPaths: Array.isArray(body.targetPaths) ? body.targetPaths : [],
                    priority: typeof body.priority === 'number' ? body.priority : 100,
                    enabled: body.enabled !== false,
                },
            });
            await logEvent({
                event: 'settings_changed',
                userId: auth.session.userId,
                details: { action: 'script_tag_created', tagId: tag.id, name: tag.name },
            });
            return json({ data: tag }, 201);
        }
        catch (err) {
            return internalError(err, 'script-tags create');
        }
    });
    router.put('/script-tags/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const d = db();
            if (!hasModel(d, 'scriptTag'))
                return modelNotAvailable('ScriptTag');
            const existing = await d.scriptTag.findUnique({ where: { id: params.id } });
            if (!existing)
                return errorResponse('Script tag not found', 404);
            const body = (await request.json());
            const update = {};
            if (body.name !== undefined)
                update.name = body.name;
            if (body.code !== undefined)
                update.code = body.code;
            if (body.placement !== undefined) {
                const validPlacements = ['head', 'body_open', 'body_close'];
                if (!validPlacements.includes(body.placement)) {
                    return errorResponse('placement must be head, body_open, or body_close', 400);
                }
                update.placement = body.placement;
            }
            if (body.scope !== undefined) {
                const validScopes = ['site', 'parents', 'urls'];
                if (!validScopes.includes(body.scope)) {
                    return errorResponse('scope must be site, parents, or urls', 400);
                }
                update.scope = body.scope;
            }
            if (body.targetPaths !== undefined) {
                update.targetPaths = Array.isArray(body.targetPaths) ? body.targetPaths : [];
            }
            if (typeof body.priority === 'number')
                update.priority = body.priority;
            if (typeof body.enabled === 'boolean')
                update.enabled = body.enabled;
            const tag = await d.scriptTag.update({
                where: { id: params.id },
                data: update,
            });
            await logEvent({
                event: 'settings_changed',
                userId: auth.session.userId,
                details: { action: 'script_tag_updated', tagId: tag.id, name: tag.name },
            });
            return json({ data: tag });
        }
        catch (err) {
            return internalError(err, 'script-tags update');
        }
    });
    router.delete('/script-tags/:id', async (request, params) => {
        try {
            const auth = await requireAuth(request);
            if (auth.error)
                return auth.error;
            const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
            if (roleErr)
                return roleErr;
            const d = db();
            if (!hasModel(d, 'scriptTag'))
                return modelNotAvailable('ScriptTag');
            const existing = await d.scriptTag.findUnique({ where: { id: params.id } });
            if (!existing)
                return errorResponse('Script tag not found', 404);
            await d.scriptTag.delete({ where: { id: params.id } });
            await logEvent({
                event: 'settings_changed',
                userId: auth.session.userId,
                details: { action: 'script_tag_deleted', tagId: existing.id, name: existing.name },
            });
            return json({ data: { deleted: true } });
        }
        catch (err) {
            return internalError(err, 'script-tags delete');
        }
    });
}
//# sourceMappingURL=webhooks.js.map