import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { sanitizeErrorForResponse } from '@/lib/api-helpers/sanitize-error';
import crypto from 'crypto';
import {
    EXEC_SCOPE,
    EXEC_TOKEN_COOKIE,
    EXEC_DEVICE_COOKIE,
    EXEC_TOKEN_EXPIRY,
    hashExecToken,
} from '@/lib/executive-display-auth';

export const dynamic = 'force-dynamic';

/**
 * Executive display token exchange — login-less. POST patches a token into the
 * browser (device-locked on first use); GET verifies/refreshes; DELETE logs
 * out. Mirrors /api/noc/auth. Public by design (the token IS the credential).
 */

function deviceId(req: NextRequest): string {
    return req.cookies.get(EXEC_DEVICE_COOKIE)?.value ?? crypto.randomBytes(16).toString('hex');
}

const cookieOpts = {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax' as const,
    maxAge: EXEC_TOKEN_EXPIRY,
    path: '/',
};

export async function POST(req: NextRequest) {
    try {
        const { token } = await req.json();
        if (!token) {
            return NextResponse.json({ success: false, error: 'Token is required' }, { status: 400 });
        }

        const apiToken = await prisma.apiToken.findFirst({
            where: { tokenHash: hashExecToken(token), scopes: EXEC_SCOPE, revokedAt: null },
        });
        if (!apiToken) {
            return NextResponse.json({ success: false, error: 'Invalid or revoked token' }, { status: 401 });
        }
        if (apiToken.expiresAt && new Date(apiToken.expiresAt) < new Date()) {
            return NextResponse.json(
                { success: false, error: 'Token has expired. Ask an administrator for a new one.' },
                { status: 401 },
            );
        }

        const dev = deviceId(req);
        // Single-device lock: reject a second device; bind on first use.
        if (apiToken.lockedDeviceId && apiToken.lockedDeviceId !== dev) {
            return NextResponse.json(
                { success: false, error: 'This token is already in use on another device.' },
                { status: 403 },
            );
        }
        if (!apiToken.lockedDeviceId) {
            await prisma.apiToken.update({ where: { id: apiToken.id }, data: { lockedDeviceId: dev } });
        }
        await prisma.apiToken.update({ where: { id: apiToken.id }, data: { lastUsedAt: new Date() } });

        const response = NextResponse.json({
            success: true,
            displayName: apiToken.displayName,
            countryId: apiToken.countryId,
            deviceName: apiToken.deviceName,
        });
        response.cookies.set(EXEC_TOKEN_COOKIE, token, cookieOpts);
        response.cookies.set(EXEC_DEVICE_COOKIE, dev, cookieOpts);
        return response;
    } catch (error: unknown) {
        const s = sanitizeErrorForResponse(error, { route: '/api/executive/auth POST', publicMessage: 'Authentication failed' });
        console.error('[/api/executive/auth POST]', s.serverContext);
        return NextResponse.json({ ...s.body, success: false }, { status: s.status });
    }
}

export async function GET(req: NextRequest) {
    try {
        const token = req.cookies.get(EXEC_TOKEN_COOKIE)?.value;
        const currentDeviceId = req.cookies.get(EXEC_DEVICE_COOKIE)?.value;
        if (!token) {
            return NextResponse.json({ success: false, authenticated: false }, { status: 401 });
        }

        const apiToken = await prisma.apiToken.findFirst({
            where: { tokenHash: hashExecToken(token), scopes: EXEC_SCOPE, revokedAt: null },
        });

        const clearAnd = (status: number, error: string) => {
            const r = NextResponse.json({ success: false, authenticated: false, error }, { status });
            r.cookies.set(EXEC_TOKEN_COOKIE, '', { path: '/', maxAge: 0 });
            r.cookies.set(EXEC_DEVICE_COOKIE, '', { path: '/', maxAge: 0 });
            return r;
        };

        if (!apiToken) return clearAnd(401, 'Token revoked');
        if (apiToken.expiresAt && new Date(apiToken.expiresAt) < new Date()) return clearAnd(401, 'Token expired');
        if (apiToken.lockedDeviceId && apiToken.lockedDeviceId !== currentDeviceId) {
            return NextResponse.json({ success: false, authenticated: false, error: 'Device mismatch' }, { status: 403 });
        }

        await prisma.apiToken.update({ where: { id: apiToken.id }, data: { lastUsedAt: new Date() } });

        const response = NextResponse.json({
            success: true,
            authenticated: true,
            displayName: apiToken.displayName,
            countryId: apiToken.countryId,
            deviceName: apiToken.deviceName,
            expiresAt: apiToken.expiresAt,
        });
        response.cookies.set(EXEC_TOKEN_COOKIE, token, cookieOpts);
        if (currentDeviceId) response.cookies.set(EXEC_DEVICE_COOKIE, currentDeviceId, cookieOpts);
        return response;
    } catch (error: unknown) {
        const s = sanitizeErrorForResponse(error, { route: '/api/executive/auth GET', publicMessage: 'Verification failed' });
        console.error('[/api/executive/auth GET]', s.serverContext);
        return NextResponse.json({ ...s.body, authenticated: false }, { status: s.status });
    }
}

export async function DELETE(_req: NextRequest) {
    const response = NextResponse.json({ success: true });
    response.cookies.set(EXEC_TOKEN_COOKIE, '', { ...cookieOpts, maxAge: 0 });
    response.cookies.set(EXEC_DEVICE_COOKIE, '', { ...cookieOpts, maxAge: 0 });
    return response;
}
