import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq } from 'drizzle-orm';
import { verify2FAChallenge } from '@/lib/2fa';
import { generateAccessToken, generateRefreshToken } from '@/lib/tokens';
import { rateLimit } from '@/lib/rate-limit';
import { z } from 'zod';
import { ACCESS_TOKEN_MAX_AGE_SECONDS, REFRESH_TOKEN_MAX_AGE_SECONDS } from '@/lib/constants';

const verifySchema = z.object({
  challengeId: z.string(),
  code: z.string(),
});

/**
 * POST /api/auth/2fa/verify
 * Verify 2FA code during login
 */
export async function POST(request: NextRequest) {
  try {
    // Rate limit: 5 attempts per 60s per IP
    const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown';
    const rl = rateLimit(`2fa-verify:${ip}`, { limit: 5, windowSeconds: 60 });
    if (!rl.allowed) {
      return NextResponse.json(
        { error: 'Troppi tentativi. Riprova tra un minuto.' },
        { status: 429, headers: { 'Retry-After': String(Math.ceil((rl.resetAt - Date.now()) / 1000)) } }
      );
    }

    const body = await request.json();
    const parsed = verifySchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json({ error: parsed.error.issues[0]?.message ?? 'Input non valido' }, { status: 400 });
    }

    const { challengeId, code } = parsed.data;

    // Verify the 2FA challenge
    const result = await verify2FAChallenge(challengeId, code);

    if (!result.success) {
      return NextResponse.json({ error: result.message }, { status: 400 });
    }

    // Get the challenge to find the user
    const challenge = await db.query.twoFactorChallenges.findFirst({
      where: eq(schema.twoFactorChallenges.id, challengeId),
    });

    if (!challenge) {
      return NextResponse.json({ error: 'Challenge not found' }, { status: 404 });
    }

    // Get user information
    const user = await db.query.users.findFirst({
      where: eq(schema.users.id, challenge.userId),
    });

    if (!user) {
      return NextResponse.json({ error: 'Utente non trovato' }, { status: 404 });
    }

    // Generate tokens (similar to successful login)
    const { refreshToken, sessionId } = await generateRefreshToken(
      user.id,
      request.headers.get('x-forwarded-for') || undefined,
      request.headers.get('user-agent') || undefined
    );

    const accessToken = generateAccessToken({
      userId: user.id,
      email: user.email,
      role: user.role,
      sessionId,
    });

    // Clean up the challenge after successful verification
    await db
      .delete(schema.twoFactorChallenges)
      .where(eq(schema.twoFactorChallenges.id, challengeId));

    // Set HttpOnly cookies
    const response = NextResponse.json({
      success: true,
      user: { id: user.id, email: user.email, name: user.name, role: user.role }
    });

    // Access token cookie (short-lived)
    response.cookies.set('scriba.access_token', accessToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: ACCESS_TOKEN_MAX_AGE_SECONDS,
    });

    // Refresh token cookie (long-lived)
    response.cookies.set('scriba.refresh_token', refreshToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: REFRESH_TOKEN_MAX_AGE_SECONDS,
    });

    return response;
  } catch (error) {
    console.error('2FA verification error:', error);
    return NextResponse.json({ error: 'Verifica 2FA fallita' }, { status: 500 });
  }
}
