import { NextRequest, NextResponse } from "next/server";
import bcrypt from "bcryptjs";
import crypto from "crypto";
import { db } from "@/lib/db";

const IRAN_MOBILE_REGEX = /^(\+98|98|0)?9\d{9}$/;
const SESSION_MAX_AGE_DAYS = 30;

function normalizeIranMobile(phone: string) {
  const digits = phone.replace(/[^\d+]/g, "");
  if (!IRAN_MOBILE_REGEX.test(digits)) return null;

  if (digits.startsWith("+98")) return `0${digits.slice(3)}`;
  if (digits.startsWith("98")) return `0${digits.slice(2)}`;
  if (digits.startsWith("9")) return `0${digits}`;
  return digits;
}

function buildPhoneEmail(phone: string) {
  return `${phone}@mobile.local`;
}

export async function POST(req: NextRequest) {
  const { phone, code, name } = await req.json().catch(() => ({}));
  const normalizedPhone = typeof phone === "string" ? normalizeIranMobile(phone) : null;
  const normalizedCode = typeof code === "string" ? code.trim() : "";

  if (!normalizedPhone || !/^\d{6}$/.test(normalizedCode)) {
    return NextResponse.json({ error: "شماره موبایل یا کد ورود معتبر نیست" }, { status: 400 });
  }

  const otp = await db.loginOtp.findFirst({
    where: {
      phone: normalizedPhone,
      consumedAt: null,
      expiresAt: { gt: new Date() },
    },
    orderBy: { createdAt: "desc" },
  });

  if (!otp || otp.attempts >= 5) {
    return NextResponse.json({ error: "کد ورود نامعتبر یا منقضی شده است" }, { status: 400 });
  }

  const isValidCode = await bcrypt.compare(normalizedCode, otp.codeHash);
  if (!isValidCode) {
    await db.loginOtp.update({
      where: { id: otp.id },
      data: { attempts: { increment: 1 } },
    });

    return NextResponse.json({ error: "کد ورود نامعتبر است" }, { status: 400 });
  }

  const user = await db.user.upsert({
    where: { phone: normalizedPhone },
    update: {
      name: typeof name === "string" && name.trim() ? name.trim() : undefined,
    },
    create: {
      phone: normalizedPhone,
      email: buildPhoneEmail(normalizedPhone),
      name: typeof name === "string" && name.trim() ? name.trim() : null,
      password: await bcrypt.hash(crypto.randomBytes(24).toString("hex"), 10),
    },
  });

  await db.loginOtp.update({
    where: { id: otp.id },
    data: { consumedAt: new Date() },
  });

  const token = crypto.randomBytes(32).toString("hex");
  const expires = new Date(Date.now() + SESSION_MAX_AGE_DAYS * 24 * 60 * 60 * 1000);

  await db.session.create({
    data: {
      sessionToken: token,
      userId: user.id,
      expires,
    },
  });

  return NextResponse.json({
    token,
    tokenType: "Bearer",
    expiresAt: expires.toISOString(),
    user: {
      id: user.id,
      name: user.name,
      phone: user.phone,
      role: user.role,
    },
  });
}
