import { NextResponse } from 'next/server';
import { logVisit } from '@/lib/db';
import {
    getClientAddress,
    getUserAgent,
    isSameOriginRequest,
    normalizeVisitPath,
} from '@/lib/request';

export const runtime = 'nodejs';

const MAX_BODY_BYTES = 4096;

function getAdminRelayUrl() {
    const adminUrl = process.env.ADMIN_DASH_URL;
    if (!adminUrl) return null;

    try {
        const url = new URL(adminUrl);
        if (url.protocol !== 'https:' && url.protocol !== 'http:') return null;
        return url.toString();
    } catch {
        return null;
    }
}

function relayVisit(path: string, visitorId: string | null) {
    const adminUrl = getAdminRelayUrl();
    if (!adminUrl) return;

    const headers: Record<string, string> = {
        'Content-Type': 'application/json',
    };

    if (process.env.ADMIN_DASH_KEY) {
        headers.Authorization = `Bearer ${process.env.ADMIN_DASH_KEY}`;
    }

    fetch(adminUrl, {
        method: 'POST',
        body: JSON.stringify({ path, visitorId, timestamp: Date.now() }),
        headers,
        signal: AbortSignal.timeout(1500),
    }).catch((error) => {
        if (process.env.NODE_ENV !== 'production') {
            console.error('Analytics relay failed', error);
        }
    });
}

export async function POST(req: Request) {
    try {
        if (!isSameOriginRequest(req)) {
            return NextResponse.json({ success: false, error: 'Forbidden' }, { status: 403 });
        }

        const contentType = req.headers.get('content-type') || '';
        if (!contentType.toLowerCase().includes('application/json')) {
            return NextResponse.json({ success: false, error: 'Unsupported media type' }, { status: 415 });
        }

        const contentLength = Number(req.headers.get('content-length') || 0);
        if (contentLength > MAX_BODY_BYTES) {
            return NextResponse.json({ success: false, error: 'Payload too large' }, { status: 413 });
        }

        const rawBody = await req.text();
        if (Buffer.byteLength(rawBody, 'utf8') > MAX_BODY_BYTES) {
            return NextResponse.json({ success: false, error: 'Payload too large' }, { status: 413 });
        }

        const body = JSON.parse(rawBody);
        if (!body || typeof body !== 'object' || Array.isArray(body)) {
            return NextResponse.json({ success: false, error: 'Invalid input' }, { status: 400 });
        }

        const visitPath = normalizeVisitPath(body.path);

        if (!visitPath) {
            return NextResponse.json({ success: false, error: 'Invalid input' }, { status: 400 });
        }

        const headers = req.headers;
        const clientAddress = getClientAddress(headers);
        const userAgent = getUserAgent(headers);
        let visitorId: string | null = null;

        try {
            visitorId = logVisit(clientAddress, userAgent, visitPath);
        } catch (e) {
            console.error('Failed to log visit to SQLite', e);
        }

        relayVisit(visitPath, visitorId);

        return NextResponse.json({ success: true });
    } catch {
        return NextResponse.json({ success: false, error: 'Bad request' }, { status: 400 });
    }
}
