/**
 * Verify Reset OTP Endpoint
 *
 * AUTH STRATEGY: Clerk-first with legacy OTP fallback.
 * When Clerk is configured, OTP verification is not used for password resets
 * (Clerk handles the entire forgot-password flow via its prebuilt UI).
 * This endpoint only processes requests when Clerk is NOT configured.
 *
 * Security features:
 * - Rate limiting (5 attempts per 15 minutes)
 * - Input validation and sanitization
 * - Brute force protection
 *
 * Note: CSRF protection not needed for unauthenticated password reset flows
 */

import { NextRequest, NextResponse } from "next/server";
import { verifyOTP, getRemainingAttempts } from "@/lib/otp-storage";
import {
  withRateLimit,
  rateLimiters,
  getEmailIdentifier,
} from "@/lib/rate-limiter";
import { validateOTPCode, sanitizeInput } from "@/lib/input-validation";
import { logger } from "@/lib/logger";

const isClerkConfigured = () =>
  Boolean(process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY);

// Force dynamic rendering to prevent build-time execution
export const dynamic = "force-dynamic";
export const runtime = "nodejs";

async function verifyResetOTPHandler(request: NextRequest) {
  try {
    // ── Clerk-first path ──
    // When Clerk is active, OTP verification for password resets is not
    // needed — Clerk handles the entire flow. Return a redirect hint.
    if (isClerkConfigured()) {
      logger.info("OTP verification request received while Clerk is active — redirecting to Clerk flow");
      return NextResponse.json(
        {
          success: false,
          useClerk: true,
          message: "Password reset is handled by the sign-in page.",
        },
        { status: 200 },
      );
    }
    const body = await request.json();
    const { phone, email, identifier, code } = body;

    // Support both 'identifier' (flexible) or specific 'phone'/'email' parameters
    const actualIdentifier = identifier || phone || email;

    if (!actualIdentifier || !code) {
      return NextResponse.json(
        { error: "Email/phone and verification code are required" },
        { status: 400 },
      );
    }

    // Validate OTP code format
    const codeValidation = validateOTPCode(code);
    if (!codeValidation.valid) {
      return NextResponse.json(
        { error: codeValidation.error },
        { status: 400 },
      );
    }

    const sanitizedIdentifier = sanitizeInput(actualIdentifier);
    const sanitizedCode = sanitizeInput(code);

    // Check remaining attempts
    const remaining = await getRemainingAttempts(sanitizedIdentifier);
    if (remaining <= 0) {
      return NextResponse.json(
        {
          error:
            "Maximum verification attempts exceeded. Please request a new code.",
        },
        { status: 429 },
      );
    }

    // Verify OTP
    const isValid = await verifyOTP(sanitizedIdentifier, sanitizedCode);

    if (!isValid) {
      const newRemaining = await getRemainingAttempts(sanitizedIdentifier);
      return NextResponse.json(
        {
          error: "Invalid or expired OTP",
          remainingAttempts: newRemaining,
        },
        { status: 401 },
      );
    }

    // Detect if identifier is email or phone for token generation
    const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(sanitizedIdentifier);

    // Generate a temporary reset token valid for 10 minutes
    const resetToken = Buffer.from(
      JSON.stringify({
        identifier: sanitizedIdentifier,
        type: isEmail ? "email" : "phone",
        timestamp: Date.now(),
        expires: Date.now() + 600000, // 10 minutes to complete password reset
      }),
    ).toString("base64");

    return NextResponse.json(
      {
        success: true,
        message: "OTP verified successfully",
        resetToken,
      },
      { status: 200 },
    );
  } catch (error) {
    logger.error("Verify reset OTP API error", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 },
    );
  }
}

// Apply rate limiting only (CSRF not needed for unauthenticated flows)
// Note: Using IP-based limiting to avoid request body consumption issues
export const POST = withRateLimit(
  verifyResetOTPHandler,
  rateLimiters.otpVerify,
);
