import { sql } from "@/lib/db";
import { hashPassword } from "@/lib/password";
import { sendEmail } from "@/lib/mailer";
import {
  CODE_TTL_MINUTES,
  generateCode,
  hashCode,
  verificationEmail,
} from "@/lib/otp";

const normalizePhone = (raw: string): string => {
  const cleaned = raw.replace(/[^\d+]/g, "");
  if (cleaned.startsWith("+")) return cleaned;
  return `+961${cleaned.replace(/^0+/, "")}`;
};

export async function POST(req: Request) {
  const { name, email, phone, password, role } = await req.json();

  if (!name?.trim() || !email?.trim() || !password) {
    return Response.json(
      { error: "Name, email and password are required." },
      { status: 400 },
    );
  }

  const normalizedRole = role === "driver" ? "driver" : "rider";

  if (typeof password !== "string" || password.length < 8) {
    return Response.json(
      { error: "Password must be at least 8 characters." },
      { status: 400 },
    );
  }

  try {
    const existing = await sql<{ id: string; email_verified: boolean }>`
      SELECT id, email_verified FROM users WHERE email = ${email.trim().toLowerCase()}
    `;

    if (existing[0]?.email_verified) {
      return Response.json(
        { error: "An account with this email already exists. Please sign in." },
        { status: 409 },
      );
    }

    // Unverified rows may be re-registered (e.g. the first mail never arrived).
    await sql`
      INSERT INTO users (name, email, phone, password_hash, email_verified, role)
      VALUES (
        ${name.trim()},
        ${email.trim().toLowerCase()},
        ${phone ? normalizePhone(phone) : null},
        ${hashPassword(password)},
        FALSE,
        ${normalizedRole}
      )
      ON CONFLICT (email) DO UPDATE SET
        name = EXCLUDED.name,
        phone = COALESCE(EXCLUDED.phone, users.phone),
        password_hash = EXCLUDED.password_hash,
        role = EXCLUDED.role
    `;

    const code = generateCode();

    await sql`
      INSERT INTO email_verification_codes (email, code_hash, expires_at)
      VALUES (
        ${email.trim().toLowerCase()},
        ${hashCode(email.trim().toLowerCase(), code)},
        CURRENT_TIMESTAMP + make_interval(mins => ${CODE_TTL_MINUTES})
      )
      ON CONFLICT (email) DO UPDATE SET
        code_hash = EXCLUDED.code_hash,
        expires_at = EXCLUDED.expires_at,
        attempts = 0
    `;

    const mail = verificationEmail(code);
    const delivered = await sendEmail(
      email.trim().toLowerCase(),
      mail.subject,
      mail.text,
    );

    return Response.json(
      {
        data: {
          sent: delivered,
          // Without SMTP/Gmail configured there is nothing to receive, so
          // surface the code to keep self-hosted sign-up usable.
          ...(delivered ? {} : { devCode: code }),
        },
      },
      { status: 201 },
    );
  } catch (error) {
    console.error("[REGISTER]: ", error);
    return Response.json({ error: "Internal Server Error" }, { status: 500 });
  }
}
