import { NextRequest, NextResponse } from 'next/server';
import { getSession } from '@/lib/auth';
import {
  generateTOTPSecret,
  generateVerificationCode,
  create2FAChallenge,
  sendEmail2FACode,
  sendSMS2FACode,
  enable2FA,
  disable2FA,
  is2FAEnabled,
  verifyTOTP,
  verify2FAChallenge,
} from '@/lib/2fa';
import { z } from 'zod';

const setupSchema = z.object({
  action: z.enum(['generate-secret', 'send-email', 'send-sms', 'enable', 'disable', 'verify-and-enable']),
  method: z.enum(['email', 'sms', 'authenticator']).optional(),
  code: z.string().optional(),
  secret: z.string().optional(),
  phoneNumber: z.string().optional(),
  challengeId: z.string().optional(),
});

/**
 * POST /api/auth/2fa/setup
 * Handle 2FA setup actions
 */
export async function POST(request: NextRequest) {
  try {
    // Authenticate user
    const session = await getSession(request.cookies.get('scriba.access_token')?.value);
    if (!session) {
      return NextResponse.json({ error: 'Non autorizzato' }, { status: 401 });
    }

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

    const { action, method, code, secret, phoneNumber, challengeId } = parsed.data;
    const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown';
    const userAgent = request.headers.get('user-agent') || undefined;

    switch (action) {
      case 'generate-secret': {
        // Generate TOTP secret for authenticator app
        const { secret, otpauthUrl } = generateTOTPSecret();
        return NextResponse.json({
          success: true,
          secret,
          otpauthUrl,
          message: 'Scan this QR code with your authenticator app',
        });
      }

      case 'send-email': {
        // Send 2FA code via email
        const emailCode = generateVerificationCode();
        const challengeId = await create2FAChallenge(
          session.user.id,
          'email',
          emailCode,
          ip,
          userAgent
        );
        await sendEmail2FACode(session.user.email, emailCode);
        return NextResponse.json({
          success: true,
          challengeId,
          message: 'Verification code sent to your email',
        });
      }

      case 'send-sms': {
        if (!phoneNumber) {
          return NextResponse.json({ error: 'Phone number required' }, { status: 400 });
        }
        // Send 2FA code via SMS
        const smsCode = generateVerificationCode();
        const challengeId = await create2FAChallenge(
          session.user.id,
          'sms',
          smsCode,
          ip,
          userAgent
        );
        await sendSMS2FACode(phoneNumber, smsCode);
        return NextResponse.json({
          success: true,
          challengeId,
          message: 'Verification code sent to your phone',
        });
      }

      case 'verify-and-enable': {
        if (!method || !code) {
          return NextResponse.json({ error: 'Method and code required' }, { status: 400 });
        }

        // Verify the code based on method
        let isValid = false;
        let enableSecret: string | undefined;

        if (method === 'authenticator') {
          if (!secret) {
            return NextResponse.json({ error: 'Secret required for authenticator' }, { status: 400 });
          }
          isValid = verifyTOTP(code, secret);
          enableSecret = secret;
        } else {
          // For email/sms, verify the code against the stored challenge
          if (!challengeId) {
            return NextResponse.json({ error: 'Challenge ID required for email/SMS verification' }, { status: 400 });
          }
          const challengeResult = await verify2FAChallenge(challengeId, code);
          isValid = challengeResult.success;
        }

        if (!isValid) {
          return NextResponse.json({ error: 'Codice di verifica non valido' }, { status: 400 });
        }

        // Enable 2FA
        await enable2FA(session.user.id, method, enableSecret, phoneNumber);

        return NextResponse.json({
          success: true,
          message: '2FA enabled successfully',
        });
      }

      case 'enable': {
        if (!method) {
          return NextResponse.json({ error: 'Method required' }, { status: 400 });
        }
        await enable2FA(session.user.id, method, secret, phoneNumber);
        return NextResponse.json({
          success: true,
          message: '2FA enabled successfully',
        });
      }

      case 'disable': {
        await disable2FA(session.user.id);
        return NextResponse.json({
          success: true,
          message: '2FA disabled successfully',
        });
      }

      default:
        return NextResponse.json({ error: 'Azione non valida' }, { status: 400 });
    }
  } catch (error) {
    console.error('2FA setup error:', error);
    return NextResponse.json({ error: 'Setup 2FA fallito' }, { status: 500 });
  }
}

/**
 * GET /api/auth/2fa/setup
 * Get 2FA status for current user
 */
export async function GET(request: NextRequest) {
  try {
    const session = await getSession(request.cookies.get('scriba.access_token')?.value);
    if (!session) {
      return NextResponse.json({ error: 'Non autorizzato' }, { status: 401 });
    }

    const status = await is2FAEnabled(session.user.id);
    return NextResponse.json({
      enabled: status.enabled,
      method: status.method,
    });
  } catch (error) {
    console.error('2FA status error:', error);
    return NextResponse.json({ error: 'Impossibile ottenere lo stato 2FA' }, { status: 500 });
  }
}
