"use client";

import { useCallback } from "react";
import { useRouter } from "next/navigation";
import { ArrowLeft } from "lucide-react";

import { canGoBackWithinApp, HOME_FALLBACK, internalReturnToFromReferrer } from "@/lib/history-back";
import { cn } from "@/lib/utils";

/**
 * Shared Back styling.
 *
 * One definition, used by the detail pages and the player, so the two can never
 * drift apart visually.
 */
export function backButtonClass(
  variant: "floating" | "plain" = "floating",
  className?: string,
): string {
  return cn(
    "inline-flex h-9 items-center gap-1.5 rounded-pill px-3 text-[13px] font-semibold transition-colors",
    variant === "floating"
      ? "bg-black/55 text-white/90 ring-1 ring-white/15 backdrop-blur-md hover:bg-black/75 hover:text-white"
      : "border border-line text-ink-soft hover:border-white/30 hover:text-ink",
    className,
  );
}

/**
 * The Back control, shared by the detail pages and the player.
 *
 * ── Why it is a button ──────────────────────────────────────────────────────
 * The destination is whatever the visitor actually came from, so it cannot be an
 * `href`. This is the real bug this component exists to fix: the detail pages
 * used to render `<Link href="/movies">` and `<Link href="/tv">`, hard-coded per
 * media type, so a visitor who opened a title from Home, from a search, or from
 * a filtered genre page was sent to a listing they had never visited. The link
 * never consulted history at all, which is why the behaviour looked like a
 * routing problem — the route was fine; the destination was a guess.
 *
 * ── The decision, in priority order ─────────────────────────────────────────
 *  1. The tab has an earlier FlixTV page. `history.back()` returns to exactly
 *     that entry, which is why a search keeps its query string, a genre page
 *     keeps its filters, and a listing keeps its scroll position, all without
 *     this component knowing anything about any of them. It also adds no entry,
 *     so Back never becomes a loop.
 *  2. `document.referrer` names a same-origin page. This covers arrivals the
 *     session counters cannot see — a detail page opened in a new tab, or
 *     restored — where history has nothing to pop but the browser still knows
 *     where the visitor came from. Navigated with `replace`, so it does not
 *     leave a dead entry behind a Back that was just pressed.
 *  3. Nothing to go back to, which means the URL was typed, pasted or shared.
 *     Home, the one destination that is never wrong.
 *
 * ── Why `replace` for the two non-history branches ──────────────────────────
 * Both of those are navigations the visitor asked to *undo*. Pushing them would
 * mean the next press of Back returns to the page they just left, so a single
 * Back press would appear to do nothing. Replacing keeps the stack behind the
 * visitor where it was.
 */
export function BackButton({
  variant = "floating",
  label = "Back",
  className,
  /**
   * Where to point a visitor with no JavaScript, in which there is no history to
   * consult and no session to read. Rendered inside `<noscript>`, so it never
   * competes with the button above it.
   */
  noJsHref,
}: {
  variant?: "floating" | "plain";
  label?: string;
  className?: string;
  noJsHref?: string;
}) {
  const router = useRouter();

  const goBack = useCallback(() => {
    if (canGoBackWithinApp()) {
      /*
        The real thing: one step back through the tab's own history, whatever is
        in it. Handles "came from a genre page" and "came from episode 4"
        without this component knowing anything about either.
      */
      window.history.back();
      return;
    }

    const returnTo = internalReturnToFromReferrer();
    if (returnTo) {
      router.replace(returnTo);
      return;
    }

    router.replace(HOME_FALLBACK);
  }, [router]);

  return (
    <>
      <button
        type="button"
        onClick={goBack}
        aria-label={label}
        title="Go back to the previous page"
        className={backButtonClass(variant, className)}
      >
        <ArrowLeft className="size-3.5 shrink-0" />
        {label}
      </button>

      {/*
        Without JavaScript there is no history to read, so the control degrades to
        the static link it effectively always was. A plain `<a>` rather than
        `next/link`: nothing inside `<noscript>` is hydrated, so a router link
        would only add machinery to a branch that navigates by full load anyway.
      */}
      {noJsHref ? (
        <noscript>
          <a href={noJsHref} className={backButtonClass(variant, className)}>
            <ArrowLeft className="size-3.5 shrink-0" />
            {label}
          </a>
        </noscript>
      ) : null}
    </>
  );
}
