/**
 * Verify Signup OTP Endpoint
 *
 * Security features:
 * - Rate limiting (5 attempts per 15 minutes)
 * - CSRF protection
 * - Input validation and sanitization
 * - Brute force protection (built into OTP storage)
 * - Audit logging
 */

import { NextRequest, NextResponse } from "next/server";
import { verifyOTP, getRemainingAttempts } from "@/lib/otp-storage";
import {
  withRateLimit,
  rateLimiters,
  getEmailIdentifier,
} from "@/lib/rate-limiter";
import { withCSRF } from "@/lib/csrf";
import {
  validateEmail,
  validateOTPCode,
  sanitizeInput,
} from "@/lib/input-validation";
import { logger } from "@/lib/logger";
import { prisma } from "@/lib/db";
import { getDataSource } from "@/lib/data-source";

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

async function verifySignupOTPHandler(request: NextRequest) {
  try {
    const body = await request.json();
    const { email, code, fullName, selectedPackage } = body;

    // Validate email
    const emailValidation = validateEmail(email);
    if (!emailValidation.valid) {
      return NextResponse.json(
        { error: emailValidation.error },
        { status: 400 },
      );
    }

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

    const sanitizedEmail = sanitizeInput(email).toLowerCase();
    const sanitizedCode = sanitizeInput(code);

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

    // Development logging for debugging
    if (process.env.NODE_ENV !== "production") {
      logger.info("[DEV] Verifying OTP", {
        email: sanitizedEmail,
        codeLength: sanitizedCode.length,
        remaining: await getRemainingAttempts(sanitizedEmail),
      });
    }

    // Verify OTP (includes attempt tracking and audit logging)
    const isValid = await verifyOTP(sanitizedEmail, sanitizedCode);

    if (!isValid) {
      const newRemaining = await getRemainingAttempts(sanitizedEmail);

      // Development hint
      if (process.env.NODE_ENV !== "production") {
        logger.warn("[DEV] OTP verification failed", {
          email: sanitizedEmail,
          remainingAttempts: newRemaining,
          hint:
            "Check Redis for otp_dev:" +
            sanitizedEmail +
            " or check MailHog for the email",
        });
      }

      return NextResponse.json(
        {
          error: "Invalid or expired verification code",
          remainingAttempts: newRemaining,
        },
        { status: 401 },
      );
    }

    // OTP verified successfully!
    // Now create the user account (passwordless)

    // Check if user already exists — try Convex first if configured
    let existingUserFromConvex: { id: string } | null = null;
    if (getDataSource("auth") === "convex") {
      try {
        const { convexQuery } = await import("@/lib/convex-client");
        const cu = (await convexQuery("auth/queries:getUserByEmail", {
          email: sanitizedEmail,
        })) as Record<string, unknown> | null;
        if (cu) {
          existingUserFromConvex = {
            id: (cu.prismaId as string) || (cu._id as string),
          };
        }
      } catch (error) {
        console.error(
          "[Convex fallback] auth verify-signup-otp user lookup:",
          error,
        );
      }
    }

    const existingUser = existingUserFromConvex
      ? { id: existingUserFromConvex.id }
      : await prisma.users.findUnique({ where: { email: sanitizedEmail } });

    if (existingUser) {
      // User already exists, just mark as verified
      await prisma.users.update({
        where: { id: existingUser.id },
        data: {
          emailVerified: new Date(),
        },
      });

      return NextResponse.json(
        {
          success: true,
          message: "Email verified successfully",
          userId: existingUser.id,
        },
        { status: 200 },
      );
    }

    // Create new passwordless user
    const sanitizedName = sanitizeInput(fullName || "User");
    const ip =
      request.headers.get("x-forwarded-for") ||
      request.headers.get("x-real-ip") ||
      "127.0.0.1";
    const now = new Date();
    const userId = crypto.randomUUID();

    logger.info("Creating new passwordless user", {
      email: sanitizedEmail,
      userId,
    });

    // Create user in database (via Convex-backed adapter)
    let newUser;
    try {
      newUser = await prisma.users.create({
        data: {
          id: userId,
          email: sanitizedEmail,
          name: sanitizedName,
          password: null, // Passwordless account!
          emailVerified: now,
          selectedPackage: selectedPackage || null,
          lastLoginIp: ip,
          createdAt: now,
          updatedAt: now,
        },
      });
      logger.info("User created successfully", {
        userId,
        email: sanitizedEmail,
      });
    } catch (prismaError) {
      logger.error("CRITICAL: Failed to create user", {
        error: prismaError,
        email: sanitizedEmail,
        userId,
      });
      throw new Error("Failed to create user account in primary database");
    }

    // Mirror new user to Convex
    if (getDataSource("auth") === "convex") {
      try {
        const { convexMutation } = await import("@/lib/convex-client");
        await convexMutation("auth/mutations:createUserNoAuth", {
          email: sanitizedEmail,
          name: sanitizedName,
          prismaId: userId,
        });
        logger.info("User mirrored to Convex", {
          userId,
          email: sanitizedEmail,
        });
      } catch (error) {
        console.error(
          "[Convex fallback] auth verify-signup-otp user create:",
          error,
        );
      }
    }

    // Log successful signup
    await prisma.audit_logs.create({
      data: {
        id: crypto.randomUUID(),
        userId: newUser.id,
        type: "signup_success",
        action: "Passwordless user account created",
        success: true,
        ip,
        userAgent: request.headers.get("user-agent") || undefined,
        metadata: { passwordless: true },
      },
    });

    logger.info("Passwordless signup completed", {
      userId: newUser.id,
      email: sanitizedEmail,
    });

    // Success - email verified and account created
    return NextResponse.json(
      {
        success: true,
        message: "Account created successfully",
        userId: newUser.id,
      },
      { status: 200 },
    );
  } catch (error) {
    logger.error("Verify Signup OTP API error", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 },
    );
  }
}

// Apply rate limiting (5 attempts per 15 min per IP) and CSRF protection
// Note: Using IP-based limiting to avoid request body consumption issues
export const POST = withCSRF(
  withRateLimit(verifySignupOTPHandler, rateLimiters.otpVerify),
);
