"use server";

import { redirect } from "next/navigation";
import { z } from "zod";
import { db } from "@/lib/db";
import { getCurrentUser } from "@/lib/auth";
import { audit } from "@/lib/audit";
import { newRegCode, newTxnId } from "@/lib/utils";
import { sendRegistrationConfirmedEmail } from "@/lib/email";

const regSchema = z.object({
  ticketTypeId: z.string().min(1, "Choose a pass"),
  name: z.string().min(2, "Enter your full name"),
  email: z.string().email("Enter a valid email"),
  phone: z.string().optional(),
  organization: z.string().optional(),
  designation: z.string().optional(),
  city: z.string().optional(),
  mode: z.enum(["PHYSICAL", "VIRTUAL"]).default("PHYSICAL"),
  coupon: z.string().optional(),
});

export async function registerAction(slug: string, formData: FormData) {
  const conf = await db.conference.findUnique({ where: { slug } });
  if (!conf || !["PUBLISHED", "LIVE"].includes(conf.status)) redirect(`/c/${slug}`);

  const now = new Date();
  if ((conf.regOpensAt && now < conf.regOpensAt) || (conf.regClosesAt && now > conf.regClosesAt)) {
    redirect(`/c/${slug}/register?error=${encodeURIComponent("Registration is not open.")}`);
  }

  const parsed = regSchema.safeParse({
    ticketTypeId: formData.get("ticketTypeId"),
    name: formData.get("name"),
    email: formData.get("email"),
    phone: formData.get("phone") || undefined,
    organization: formData.get("organization") || undefined,
    designation: formData.get("designation") || undefined,
    city: formData.get("city") || undefined,
    mode: (formData.get("mode") as string) || "PHYSICAL",
    coupon: formData.get("coupon") || undefined,
  });
  if (!parsed.success) {
    redirect(`/c/${slug}/register?error=${encodeURIComponent(parsed.error.issues[0].message)}`);
  }
  const data = parsed.data;

  const ticket = await db.ticketType.findFirst({
    where: { id: data.ticketTypeId, conferenceId: conf.id, active: true },
    include: { _count: { select: { registrations: { where: { status: { not: "CANCELLED" } } } } } },
  });
  if (!ticket) redirect(`/c/${slug}/register?error=${encodeURIComponent("That pass is unavailable.")}`);
  if (ticket.quantity != null && ticket._count.registrations >= ticket.quantity) {
    redirect(`/c/${slug}/register?error=${encodeURIComponent(`${ticket.name} is sold out.`)}`);
  }
  const saleNotStarted = ticket.saleStartsAt && now < ticket.saleStartsAt;
  const saleEnded = ticket.saleEndsAt && now > ticket.saleEndsAt;
  if (saleNotStarted || saleEnded) {
    redirect(`/c/${slug}/register?error=${encodeURIComponent(`${ticket.name} sales are ${saleNotStarted ? "not open yet" : "over"}.`)}`);
  }

  // Duplicate guard: one active registration per email per conference
  const dup = await db.registration.findFirst({
    where: { conferenceId: conf.id, email: data.email.toLowerCase(), status: { not: "CANCELLED" } },
  });
  if (dup) {
    redirect(`/c/${slug}/ticket/${dup.regCode}?existing=1`);
  }

  // Coupon
  let amount = ticket.price;
  let couponId: string | null = null;
  if (data.coupon && amount > 0) {
    const coupon = await db.coupon.findUnique({
      where: { conferenceId_code: { conferenceId: conf.id, code: data.coupon.toUpperCase().trim() } },
    });
    if (!coupon || !coupon.active || (coupon.maxUses != null && coupon.usedCount >= coupon.maxUses)) {
      redirect(`/c/${slug}/register?error=${encodeURIComponent("That coupon code is invalid or exhausted.")}`);
    }
    amount = coupon.discountType === "PERCENT"
      ? Math.max(0, Math.round(amount * (1 - coupon.value / 100)))
      : Math.max(0, amount - coupon.value);
    couponId = coupon.id;
  }

  const user = await getCurrentUser();
  const free = amount === 0;
  const registration = await db.registration.create({
    data: {
      regCode: newRegCode(),
      conferenceId: conf.id,
      ticketTypeId: ticket.id,
      userId: user?.id,
      couponId,
      name: data.name,
      email: data.email.toLowerCase(),
      phone: data.phone,
      organization: data.organization,
      designation: data.designation,
      city: data.city,
      mode: conf.type === "VIRTUAL" ? "VIRTUAL" : data.mode,
      amount,
      status: free ? "CONFIRMED" : "PENDING",
    },
  });
  if (couponId) await db.coupon.update({ where: { id: couponId }, data: { usedCount: { increment: 1 } } });
  await audit({ userId: user?.id, conferenceId: conf.id, action: "registration.create", entity: "Registration", entityId: registration.id, meta: { ticket: ticket.name, amount } });

  if (free) {
    await sendRegistrationConfirmedEmail(registration.id);
    redirect(`/c/${slug}/ticket/${registration.regCode}?new=1`);
  }
  redirect(`/c/${slug}/pay/${registration.id}`);
}

/** Mock gateway confirmation — Razorpay/Stripe-shaped. Swap with a real webhook later. */
export async function mockPayAction(slug: string, registrationId: string, outcome: "success" | "failure") {
  const registration = await db.registration.findUnique({
    where: { id: registrationId },
    include: { conference: true },
  });
  if (!registration || registration.conference.slug !== slug) redirect(`/c/${slug}`);
  if (registration.status === "CONFIRMED") redirect(`/c/${slug}/ticket/${registration.regCode}`);

  const success = outcome === "success";
  await db.payment.create({
    data: {
      registrationId,
      amount: registration.amount,
      gateway: "mock-razorpay",
      status: success ? "SUCCESS" : "FAILED",
      txnId: newTxnId(),
    },
  });
  if (success) {
    await db.registration.update({ where: { id: registrationId }, data: { status: "CONFIRMED" } });
    await sendRegistrationConfirmedEmail(registrationId);
  }
  await audit({ conferenceId: registration.conferenceId, action: success ? "payment.success" : "payment.failed", entity: "Registration", entityId: registrationId, meta: { amount: registration.amount } });

  if (success) redirect(`/c/${slug}/ticket/${registration.regCode}?new=1`);
  redirect(`/c/${slug}/pay/${registrationId}?error=1`);
}
