import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq } from 'drizzle-orm';
import {
  generateVerificationCode,
  create2FAChallenge,
  sendEmail2FACode,
  sendSMS2FACode,
} from '@/lib/2fa';
import { rateLimit } from '@/lib/rate-limit';
import { z } from 'zod';

const sendSchema = z.object({
  challengeId: z.string(),
  method: z.enum(['email', 'sms', 'authenticator']),
});

/**
 * POST /api/auth/2fa/send
 * Send or resend 2FA code for pending challenge
 */
export async function POST(request: NextRequest) {
  try {
    // Rate limit: 3 attempts per 60s per IP
    const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown';
    const rl = rateLimit(`2fa-send:${ip}`, { limit: 3, 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 = sendSchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json({ error: parsed.error.issues[0]?.message ?? 'Input non valido' }, { status: 400 });
    }

    const { challengeId, method } = parsed.data;

    // Get the challenge
    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 });
    }

    // Delete old challenge and create new one with fresh code
    await db
      .delete(schema.twoFactorChallenges)
      .where(eq(schema.twoFactorChallenges.id, challengeId));

    const newCode = generateVerificationCode();
    const newChallengeId = await create2FAChallenge(
      challenge.userId,
      method,
      newCode,
      ip,
      request.headers.get('user-agent') || undefined
    );

    // Send code based on method
    if (method === 'email') {
      await sendEmail2FACode(user.email, newCode);
      return NextResponse.json({
        success: true,
        challengeId: newChallengeId,
        message: 'Codice di verifica inviato via email',
      });
    } else if (method === 'sms') {
      if (!user.phoneNumber) {
        return NextResponse.json({ error: 'Numero di telefono non configurato' }, { status: 400 });
      }
      await sendSMS2FACode(user.phoneNumber, newCode);
      return NextResponse.json({
        success: true,
        challengeId: newChallengeId,
        message: 'Codice di verifica inviato via SMS',
      });
    } else {
      // For authenticator, no code is sent - user uses their app
      return NextResponse.json({
        success: true,
        challengeId: newChallengeId,
        message: 'Inserisci il codice dalla tua app di autenticazione',
      });
    }
  } catch (error) {
    console.error('2FA send error:', error);
    return NextResponse.json({ error: 'Invio codice 2FA fallito' }, { status: 500 });
  }
}
