import { NextRequest } from "next/server";
import { z } from "zod";
import { getPrisma } from "../../../../lib/db";
import { hashPassword } from "../../../../lib/auth/password";
import { isStrongPassword, sanitizeText } from "../../../../lib/auth/validation";
import { ok, fail } from "../../../../lib/http";
import { loadSystemConfig } from "../../../../lib/system-config";
import { sendEmail } from "../../../../lib/email";
import { verifyCaptcha } from "../../../../lib/captcha";
import crypto from "crypto";

export const runtime = "nodejs";

const Body = z.object({
  firstName: z.string().min(1),
  lastName: z.string().min(1),
  gender: z.string().optional(),
  dob: z.string().optional(),
  address: z.string().optional(),
  email: z.string().email(),
  password: z.string().min(8),
  confirmPassword: z.string().min(8),
  captchaId: z.string().optional(),
  captchaCode: z.string().optional(),
});

export async function POST(req: NextRequest) {
  const cfg = await loadSystemConfig();
  const prisma = await getPrisma();
  const body = Body.safeParse(await req.json().catch(() => ({})));

  if (!body.success) return fail(new Error("Invalid input"));

  if (!prisma) return fail(new Error("Database not configured"), { status: 503 });

  // Validate CAPTCHA if provided
  if (body.data.captchaId && body.data.captchaCode) {
    const captchaResult = verifyCaptcha(body.data.captchaId, body.data.captchaCode);
    if (!captchaResult.success) {
      return fail(new Error(captchaResult.error || "CAPTCHA verification failed. Please try again."));
    }
  }

  const email = body.data.email.toLowerCase();
  const password = body.data.password;
  const confirmPassword = body.data.confirmPassword;

  if (password !== confirmPassword) return fail(new Error("Passwords do not match"));
  if (!isStrongPassword(password)) return fail(new Error("Password is not strong enough"));

  // Validate birth date if provided
  if (body.data.dob) {
    const birthDate = new Date(body.data.dob);
    const today = new Date();
    const minDate = new Date(today.getFullYear() - 100, today.getMonth(), today.getDate());
    const maxDate = new Date(today.getFullYear() - 18, today.getMonth(), today.getDate());
    if (birthDate < minDate || birthDate > maxDate) {
      return fail(new Error("Birth date must be between 18 and 100 years old"));
    }
  }

  const passwordHash = await hashPassword(password);

  try {
    const user = await prisma.user.create({
      data: {
        email,
        role: "USER",
        name: `${body.data.firstName} ${body.data.lastName}`,
        firstName: sanitizeText(body.data.firstName),
        lastName: sanitizeText(body.data.lastName),
        gender: body.data.gender ? sanitizeText(body.data.gender) : null,
        dob: body.data.dob ? new Date(body.data.dob) : null,
        address: body.data.address ? sanitizeText(body.data.address) : null,
        // If email is enabled, require verification; otherwise mark as verified
        emailVerified: !cfg.email?.enabled,
        forcePasswordReset: false,
        isActive: true,
      },
    });

    // Create credential for email/password authentication
    await prisma.credential.create({
      data: {
        userId: user.id,
        password: passwordHash,
      },
    });

    // Only create verification token and send email if email is enabled
    if (cfg.email?.enabled) {
      const token = crypto.randomBytes(32).toString("hex");
      const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000);
      await prisma.verification.create({
        data: {
          userId: user.id,
          identifier: email,
          value: token,
          expiresAt,
        },
      });

      const baseUrl = process.env.APP_BASE_URL || "http://localhost:3000";
      const link = `${baseUrl}/auth/verify?token=${token}`;
      await sendEmail({
        to: email,
        subject: "Verify your email",
        html: `<p>Welcome! Please verify your email:</p><p><a href="${link}">Verify Email</a></p>`,
      });
      return ok({ message: "Account created. Please check your email to verify your account." });
    } else {
      return ok({ message: "Account created successfully. You can now log in." });
    }
  } catch (e: any) {
    // Check if the error is due to unique constraint on email
    if (e.code === 'P2002' && e.meta?.target?.includes('email')) {
      return fail(new Error("This email is already taken"));
    }
    console.error("Registration error:", e);
    return fail(new Error("Account creation failed. Please try again or contact support."));
  }

  return ok({ message: "Account created. Please check your email to verify your account." });
}
