"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";

type ClientPreviewBannerProps = {
  expiresAt: string;
  onExpire: () => void;
};

const FIVE_MINUTES_MS = 5 * 60 * 1000;

export default function ClientPreviewBanner({
  expiresAt,
  onExpire,
}: ClientPreviewBannerProps) {
  const expiry = useMemo(() => Date.parse(expiresAt), [expiresAt]);
  const [remainingMs, setRemainingMs] = useState<number | null>(null);
  const [warning, setWarning] = useState("");
  const warningAnnounced = useRef(false);
  const expiryHandled = useRef(false);

  const recalculate = useCallback(() => {
    const remaining = Math.max(0, expiry - Date.now());
    setRemainingMs(remaining);

    if (
      remaining > 0 &&
      remaining <= FIVE_MINUTES_MS &&
      !warningAnnounced.current
    ) {
      warningAnnounced.current = true;
      setWarning("This preview expires in five minutes.");
    }

    if (remaining === 0 && !expiryHandled.current) {
      expiryHandled.current = true;
      onExpire();
    }
  }, [expiry, onExpire]);

  useEffect(() => {
    recalculate();
    const interval = window.setInterval(recalculate, 15_000);
    const timeout = window.setTimeout(
      recalculate,
      Math.max(0, expiry - Date.now()),
    );
    const onVisibilityChange = () => {
      if (document.visibilityState === "visible") recalculate();
    };

    window.addEventListener("focus", recalculate);
    document.addEventListener("visibilitychange", onVisibilityChange);
    return () => {
      window.clearInterval(interval);
      window.clearTimeout(timeout);
      window.removeEventListener("focus", recalculate);
      document.removeEventListener("visibilitychange", onVisibilityChange);
    };
  }, [expiry, recalculate]);

  const isWarning = remainingMs !== null && remainingMs <= FIVE_MINUTES_MS;
  const remainingMinutes =
    remainingMs === null ? null : Math.max(1, Math.ceil(remainingMs / 60_000));

  return (
    <div
      className={`border-b px-4 py-3 text-sm ${
        isWarning
          ? "border-amber-300 bg-amber-100 text-amber-950 dark:border-amber-700 dark:bg-amber-950 dark:text-amber-100"
          : "border-sky-200 bg-sky-50 text-midnightBlue dark:border-sky-900 dark:bg-sky-950 dark:text-sky-100"
      }`}
    >
      <div className="mx-auto flex max-w-5xl flex-wrap items-center justify-center gap-x-3 gap-y-1 text-center">
        <strong>Internal preview · Read-only</strong>
        <span>
          Expires at{" "}
          <time suppressHydrationWarning dateTime={expiresAt}>
            {new Date(expiresAt).toLocaleTimeString([], {
              hour: "2-digit",
              minute: "2-digit",
              timeZoneName: "short",
            })}
          </time>
          {remainingMinutes !== null && ` · ${remainingMinutes} min remaining`}
        </span>
        <form action="/participant-list/preview/end" method="post">
          <button className="font-semibold underline" type="submit">
            Return to Hub
          </button>
        </form>
      </div>
      <span aria-live="polite" className="sr-only">
        {warning}
      </span>
    </div>
  );
}
