/**
 * Check Email Availability Endpoint
 *
 * Determines if an email address is already registered in the system.
 * Used during signup to prevent duplicate account creation and provide
 * helpful UX by redirecting existing users to login.
 *
 * **Security Measures:**
 * - Rate limiting to prevent email enumeration attacks
 * - Input validation and sanitization
 * - Minimal information disclosure
 *
 * **Use Cases:**
 * - Signup flow: Check before sending OTP
 * - User experience: Redirect to login if account exists
 * - Prevent duplicate accounts
 *
 * @endpoint GET /api/auth/check-email
 * @param email - Email address to check (query parameter)
 * @returns JSON with existence status and account details
 *
 * @example
 * ```typescript
 * GET /api/auth/check-email?email=user@example.com
 *
 * Response:
 * {
 *   exists: true,
 *   verified: true,
 *   isGoogleAccount: false
 * }
 * ```
 */

import { NextRequest } from "next/server";
import { prisma } from "@/lib/db";
import { validateEmail, sanitizeInput } from "@/lib/input-validation";
import { withRateLimit, rateLimiters } from "@/lib/rate-limiter";
import { APIResponse, HTTP_STATUS } from "@/lib/utils/api-response.util";
import { normalizeEmail } from "@/lib/utils/auth-helpers.util";
import type { EmailCheckResult } from "@/lib/types/otp.types";
import { getDataSource } from "@/lib/data-source";

export const dynamic = "force-dynamic";
export const runtime = "nodejs";

/**
 * Check email availability handler
 *
 * @param request - Next.js request object
 * @returns JSON response with email status
 */
async function checkEmailHandler(request: NextRequest) {
  try {
    // Extract and validate email from query parameters
    const { searchParams } = new URL(request.url);
    const rawEmail = searchParams.get("email");

    // Validate required parameter
    if (!rawEmail) {
      return APIResponse.validationError(
        "Email parameter is required",
        "email",
      );
    }

    // Validate email format
    const emailValidation = validateEmail(rawEmail);
    if (!emailValidation.valid) {
      return APIResponse.validationError(
        emailValidation.error || "Invalid email format",
        "email",
      );
    }

    // Sanitize and normalize
    const email = normalizeEmail(sanitizeInput(rawEmail));

    // Convex data-source routing
    if (getDataSource("auth") === "convex") {
      try {
        const { convexQuery } = await import("@/lib/convex-client");
        const convexUser = await convexQuery("auth/queries:getUserByEmail", {
          email,
        });

        const result: EmailCheckResult = convexUser
          ? {
              exists: true,
              verified: !!(convexUser as Record<string, unknown>).emailVerified,
              isGoogleAccount: !!(convexUser as Record<string, unknown>)
                .googleId,
            }
          : {
              exists: false,
              available: true,
            };

        return APIResponse.success(result);
      } catch (error) {
        console.error("[Convex fallback] check-email:", error);
        // Fall through to Prisma
      }
    }

    // Query database for existing user
    const existingUser = await prisma.users.findUnique({
      where: { email },
      select: {
        id: true,
        email: true,
        emailVerified: true,
        googleId: true,
      },
    });

    // Build response
    const result: EmailCheckResult = existingUser
      ? {
          exists: true,
          verified: !!existingUser.emailVerified,
          isGoogleAccount: !!existingUser.googleId,
        }
      : {
          exists: false,
          available: true,
        };

    return APIResponse.success(result);
  } catch (error) {
    console.error("[CheckEmail] Unexpected error:", error);
    return APIResponse.internalError(
      "Failed to check email availability",
      true,
      error as Error,
    );
  }
}

/**
 * Rate-limited GET endpoint
 *
 * Applies rate limiting to prevent email enumeration attacks
 * Limit: 10 requests per 5 minutes per IP address
 */
export const GET = withRateLimit(checkEmailHandler, rateLimiters.login);
