"use client";

import { useEffect, useRef, useState, type ReactNode } from "react";
import { Spinner } from "@/components/ui/spinner";

// While admitted: how often to renew the slot so it doesn't expire under an
// open tab (must stay comfortably under the backend's WAITING_ROOM_SLOT_TTL,
// default 120s — see apps/backend/config/waitingroom.php).
const HEARTBEAT_INTERVAL_MS = 5_000;

// While waiting: how often to re-check for a free slot.
const RETRY_INTERVAL_MS = 4_000;

type GateStatus = "checking" | "waiting" | "admitted";

interface EnterResponse {
  admitted: boolean;
  active: number;
  capacity: number;
}

/**
 * Wraps the checkout entry point (regular CheckoutForm or Signature
 * CheckoutWizard) and holds it back until the backend grants a waiting-room
 * slot. Mirrors App\Http\Middleware\WaitingRoom on the API side — that
 * middleware is what actually enforces the limit; this is the UX so people
 * see a waiting screen instead of their checkout submit just failing.
 *
 * When the backend's WAITING_ROOM_ENABLED is false (the default until
 * capacity is decided), /waiting-room/enter always returns admitted: true
 * immediately, so this behaves as a no-op passthrough.
 */
export function WaitingRoomGate({ children }: { children: ReactNode }) {
  const [status, setStatus] = useState<GateStatus>("checking");
  const [meta, setMeta] = useState<{ active: number; capacity: number } | null>(null);
  const cancelledRef = useRef(false);

  useEffect(() => {
    cancelledRef.current = false;
    let timer: ReturnType<typeof setTimeout>;

    async function poll() {
      try {
        const res = await fetch("/api/waiting-room/enter", { method: "POST" });
        const body = await res.json().catch(() => null);
        if (cancelledRef.current) return;

        const data: EnterResponse | undefined = body?.data;

        if (data?.admitted) {
          setStatus("admitted");
          timer = setTimeout(poll, HEARTBEAT_INTERVAL_MS);
        } else {
          setStatus("waiting");
          setMeta({ active: data?.active ?? 0, capacity: data?.capacity ?? 0 });
          timer = setTimeout(poll, RETRY_INTERVAL_MS);
        }
      } catch {
        // Network hiccup — treat like "still waiting" and try again rather
        // than surfacing a dead end.
        if (cancelledRef.current) return;
        setStatus("waiting");
        timer = setTimeout(poll, RETRY_INTERVAL_MS);
      }
    }

    poll();

    return () => {
      cancelledRef.current = true;
      clearTimeout(timer);
    };
  }, []);

  if (status === "admitted") {
    return <>{children}</>;
  }

  return <WaitingRoomScreen checking={status === "checking"} active={meta?.active} capacity={meta?.capacity} />;
}

function WaitingRoomScreen({
  checking,
  active,
  capacity,
}: {
  checking: boolean;
  active?: number;
  capacity?: number;
}) {
  return (
    <div className="mx-auto flex max-w-md flex-col items-center gap-4 px-6 py-24 text-center">
      <Spinner className="h-8 w-8 text-kolabora-primary" />
      <h1 className="text-xl font-semibold">
        {checking ? "Checking availability…" : "You're in the waiting room"}
      </h1>
      <p className="text-sm text-kolabora-neutral-dark/70">
        {checking
          ? "One moment while we check if a checkout slot is free."
          : "Demand is high right now. This page will refresh automatically as soon as a slot opens up — no need to reload."}
      </p>
      {!checking && typeof active === "number" && typeof capacity === "number" && capacity > 0 && (
        <p className="text-xs text-kolabora-neutral-dark/70">
          {active}/{capacity} slots currently in use
        </p>
      )}
    </div>
  );
}
