import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { sanitizeErrorForResponse } from '@/lib/api-helpers/sanitize-error';
import crypto from 'crypto';
import { EXEC_SCOPE, hashExecToken } from '@/lib/executive-display-auth';
import { createExecTokenSchema, deleteExecTokenSchema } from '@/lib/validations/executive-token.schema';

export const dynamic = 'force-dynamic';

/**
 * Admin-only management of executive_display tokens (mirrors /api/noc/tokens).
 * GET list · POST generate (full token shown ONCE) · DELETE revoke.
 */

function generateToken(): string {
    return 'exec_' + crypto.randomBytes(24).toString('hex');
}

async function requireAdmin() {
    const session = await getServerSession(authOptions);
    if (!session || (session.user as { role?: string })?.role !== 'ADMIN') return null;
    return session;
}

export async function GET() {
    if (!(await requireAdmin())) {
        return NextResponse.json({ error: 'Admin access required' }, { status: 403 });
    }
    try {
        const tokens = await prisma.apiToken.findMany({
            where: { scopes: EXEC_SCOPE },
            orderBy: { createdAt: 'desc' },
            include: { user: { select: { id: true, name: true, email: true } } },
        });
        const now = Date.now();
        return NextResponse.json({
            success: true,
            tokens: tokens.map((t) => {
                const isExpired = t.expiresAt ? new Date(t.expiresAt).getTime() < now : false;
                const isRevoked = !!t.revokedAt;
                return {
                    id: t.id,
                    tokenPrefix: t.tokenPrefix,
                    displayName: t.displayName ?? t.name,
                    countryId: t.countryId,
                    deviceName: t.deviceName,
                    locked: !!t.lockedDeviceId,
                    expiresAt: t.expiresAt,
                    expiresIn: t.expiresAt ? Math.ceil((new Date(t.expiresAt).getTime() - now) / 86_400_000) : null,
                    isExpired,
                    isRevoked,
                    isActive: !isExpired && !isRevoked,
                    lastUsedAt: t.lastUsedAt,
                    createdAt: t.createdAt,
                    createdBy: t.user,
                };
            }),
        });
    } catch (error: unknown) {
        const s = sanitizeErrorForResponse(error, { route: '/api/executive/tokens' });
        console.error('[/api/executive/tokens GET]', s.serverContext);
        return NextResponse.json(s.body, { status: s.status });
    }
}

export async function POST(req: NextRequest) {
    const session = await requireAdmin();
    if (!session) {
        return NextResponse.json({ error: 'Admin access required' }, { status: 403 });
    }
    try {
        // Auditor T1D (2026-06-01): Zod-validate the create payload.
        const parsed = createExecTokenSchema.safeParse(await req.json());
        if (!parsed.success) {
            return NextResponse.json(
                { success: false, error: parsed.error.issues[0]?.message || 'Invalid request body' },
                { status: 400 }
            );
        }
        const { displayName, countryId, expiryDays, deviceName } = parsed.data;

        const token = generateToken();
        let expiresAt: Date | null = null;
        if (expiryDays && expiryDays > 0) {
            expiresAt = new Date();
            expiresAt.setDate(expiresAt.getDate() + expiryDays);
        }

        const adminUser = await prisma.user.findUnique({ where: { email: session.user?.email || '' } });
        if (!adminUser) {
            return NextResponse.json({ success: false, error: 'Admin user not found' }, { status: 400 });
        }

        // countryId is already coerced to number | undefined | null by Zod
        // (z.coerce.number().int().positive().optional().nullable()).
        const normalizedCountryId = countryId ?? null;

        const apiToken = await prisma.apiToken.create({
            data: {
                userId: adminUser.id,
                name: displayName,
                displayName,
                countryId: normalizedCountryId,
                deviceName: deviceName || null,
                tokenHash: hashExecToken(token),
                tokenPrefix: token.substring(0, 8),
                scopes: EXEC_SCOPE,
                expiresAt,
            },
        });

        let countryName: string | null = null;
        if (normalizedCountryId) {
            const c = await prisma.country.findUnique({ where: { id: normalizedCountryId }, select: { name: true } });
            countryName = c?.name ?? null;
        }

        return NextResponse.json({
            success: true,
            token: {
                id: apiToken.id,
                fullToken: token, // shown ONCE
                tokenPrefix: apiToken.tokenPrefix,
                displayName,
                countryId: normalizedCountryId,
                countryName,
                deviceName: deviceName || null,
                expiresAt: apiToken.expiresAt,
                createdAt: apiToken.createdAt,
            },
        });
    } catch (error: unknown) {
        const s = sanitizeErrorForResponse(error, { route: '/api/executive/tokens POST', publicMessage: 'Failed to create token' });
        console.error('[/api/executive/tokens POST]', s.serverContext);
        return NextResponse.json(s.body, { status: s.status });
    }
}

export async function DELETE(req: NextRequest) {
    if (!(await requireAdmin())) {
        return NextResponse.json({ error: 'Admin access required' }, { status: 403 });
    }
    try {
        // Auditor T1D (2026-06-01): Zod-validate the delete payload.
        // Schema is a union: `{ action: 'clear_all' }` OR `{ tokenId: N }`.
        const parsed = deleteExecTokenSchema.safeParse(await req.json());
        if (!parsed.success) {
            return NextResponse.json(
                { success: false, error: parsed.error.issues[0]?.message || 'Invalid request body' },
                { status: 400 }
            );
        }
        if ('action' in parsed.data && parsed.data.action === 'clear_all') {
            await prisma.apiToken.deleteMany({ where: { scopes: EXEC_SCOPE } });
            return NextResponse.json({ success: true, message: 'All executive tokens cleared' });
        }
        // The other branch of the union — `{ tokenId: N }` is guaranteed
        // by the schema when we reach here.
        const { tokenId } = parsed.data as { tokenId: number };
        await prisma.apiToken.delete({ where: { id: tokenId } });
        return NextResponse.json({ success: true });
    } catch (error: unknown) {
        const s = sanitizeErrorForResponse(error, { route: '/api/executive/tokens DELETE', publicMessage: 'Failed to revoke token' });
        console.error('[/api/executive/tokens DELETE]', s.serverContext);
        return NextResponse.json(s.body, { status: s.status });
    }
}
