import { NextResponse } from "next/server";
import { hash } from "bcryptjs";
import crypto from "crypto";
import { z } from "zod";
import { prisma } from "@/lib/prisma";
import { sendEmail } from "@/lib/email";
import { checkRateLimit, AUTH_RATE_LIMITS } from "@/lib/rate-limit";

const registerSchema = z.object({
  email: z.email("Invalid email address"),
  password: z.string().min(8, "Password must be at least 8 characters"),
  name: z.string().min(1).optional(),
});

export async function POST(request: Request) {
  try {
    const ip = request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? "unknown";
    const rl = await checkRateLimit(`register:${ip}`, AUTH_RATE_LIMITS.register);
    if (!rl.allowed) {
      return NextResponse.json(
        { error: "Too many registration attempts. Please try again later." },
        { status: 429, headers: { "Retry-After": String(Math.ceil((rl.resetAt - Date.now()) / 1000)) } }
      );
    }

    const body: unknown = await request.json();
    const parsed = registerSchema.safeParse(body);

    if (!parsed.success) {
      return NextResponse.json(
        { error: parsed.error.issues[0]?.message ?? "Invalid input" },
        { status: 400 }
      );
    }

    const { email, password, name } = parsed.data;
    const normalizedEmail = email.toLowerCase();

    const existing = await prisma.user.findUnique({
      where: { email: normalizedEmail },
    });

    if (existing) {
      return NextResponse.json(
        { message: "If this email is available, a confirmation email will be sent." },
        { status: 200 }
      );
    }

    const passwordHash = await hash(password, 12);

    const user = await prisma.user.create({
      data: {
        email: normalizedEmail,
        passwordHash,
        name: name ?? null,
        subscription: {
          create: {
            tier: "FREE",
            sessionsLimit: 20,
          },
        },
      },
      select: {
        id: true,
        email: true,
        name: true,
        createdAt: true,
      },
    });

    try {
      const rawToken = crypto.randomBytes(32).toString("hex");
      const tokenHash = crypto
        .createHash("sha256")
        .update(rawToken)
        .digest("hex");

      await prisma.emailVerificationToken.create({
        data: {
          userId: user.id,
          token: tokenHash,
          expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
        },
      });

      const verifyUrl = `https://agentlens.vectry.tech/verify-email?token=${rawToken}`;
      await sendEmail({
        to: user.email,
        subject: "Verify your AgentLens email",
        html: `
          <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 480px; margin: 0 auto; padding: 40px 20px;">
            <h2 style="color: #e5e5e5; margin-bottom: 16px;">Verify your email</h2>
            <p style="color: #a3a3a3; line-height: 1.6;">
              Thanks for signing up for AgentLens. Click the link below to verify your email address.
            </p>
            <a href="${verifyUrl}" style="display: inline-block; margin-top: 24px; padding: 12px 24px; background-color: #10b981; color: #000; text-decoration: none; border-radius: 8px; font-weight: 600;">
              Verify Email
            </a>
            <p style="color: #737373; font-size: 13px; margin-top: 32px;">
              This link expires in 24 hours. If you didn't create an account, you can safely ignore this email.
            </p>
          </div>
        `,
      });
    } catch (emailError) {
      console.error("[register] Failed to send verification email:", emailError);
    }

    return NextResponse.json(
      { message: "If this email is available, a confirmation email will be sent." },
      { status: 200 }
    );
  } catch {
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}
