import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { sendPasswordResetEmail } from "@/lib/email";
import { generatePasswordResetToken } from "@/lib/password-reset";

type ForgotPasswordBody = {
  email?: string;
};

const GENERIC_OK_MESSAGE = "Si el correo existe, enviaremos un enlace para restablecer la contrasena.";
const FAIL_FAST_TIMEOUT_MS = 3500;

async function withTimeout<T>(promise: Promise<T>, timeoutMs = FAIL_FAST_TIMEOUT_MS): Promise<T> {
  let timeoutId: NodeJS.Timeout | null = null;

  try {
    return await Promise.race([
      promise,
      new Promise<T>((_, reject) => {
        timeoutId = setTimeout(() => {
          reject(new Error("Operation timed out"));
        }, timeoutMs);
      }),
    ]);
  } finally {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  }
}

export async function POST(request: Request) {
  try {
    const body = (await request.json()) as ForgotPasswordBody;
    const email = body.email?.toLowerCase().trim() ?? "";

    if (!email) {
      return NextResponse.json({ ok: true, message: GENERIC_OK_MESSAGE });
    }

    const user = await withTimeout(
      prisma.user.findUnique({
        where: { email },
        select: {
          id: true,
          email: true,
          status: true,
          emailVerified: true,
          passwordHash: true,
        },
      })
    );

    if (!user || user.status !== "active" || !user.emailVerified || !user.passwordHash) {
      return NextResponse.json({ ok: true, message: GENERIC_OK_MESSAGE });
    }

    const { token, tokenHash, expiresAt } = generatePasswordResetToken();

    await withTimeout(
      prisma.$transaction(async (tx) => {
        await tx.passwordResetToken.deleteMany({
          where: { email },
        });

        await tx.passwordResetToken.create({
          data: {
            email,
            tokenHash,
            expiresAt,
          },
        });
      })
    );

    await withTimeout(
      sendPasswordResetEmail({
        toEmail: user.email,
        token,
      })
    );
  } catch (error) {
    console.error("forgot-password failed", error);
  }

  return NextResponse.json({ ok: true, message: GENERIC_OK_MESSAGE });
}
