"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { motion, useReducedMotion } from "motion/react";
import { ArrowRight, Home } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Container } from "@/components/container";

// How long the automatic return-home timeline runs before navigating.
const REDIRECT_SECONDS = 6;
const REDIRECT_MS = REDIRECT_SECONDS * 1000;

/**
 * Explicit redirect state machine (§19):
 *  - "active"      → countdown running, will navigate home when it reaches 0
 *  - "cancelled"   → user pressed Skip; timer torn down; user stays indefinitely
 *  - "redirecting" → countdown finished; navigation to "/" is in flight
 */
type RedirectStatus = "active" | "cancelled" | "redirecting";

export function ThankYouContent() {
  const prefersReduced = useReducedMotion();
  const router = useRouter();

  const [mounted, setMounted] = useState(false);
  const [from, setFrom] = useState<string | null>(null);
  const [status, setStatus] = useState<RedirectStatus>("active");
  const [secondsLeft, setSecondsLeft] = useState(REDIRECT_SECONDS);
  const [progress, setProgress] = useState(0); // 0..1 (smooth, motion users)
  const [paused, setPaused] = useState(false);

  const pausedRef = useRef(false);
  const elapsedRef = useRef(0);
  useEffect(() => {
    pausedRef.current = paused;
  }, [paused]);

  // useReducedMotion() is null on the server and resolves on the client. Gate on
  // mount so the first client render matches the SSR output (no hydration drift).
  const reduce = mounted ? !!prefersReduced : false;

  useEffect(() => {
    // Intentional mount-time sync: settle the reduced-motion branch and read the
    // ?from query param on the client only (SSR-safe). Runs once.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setMounted(true);
    try {
      setFrom(new URLSearchParams(window.location.search).get("from"));
    } catch {
      /* ignore */
    }
  }, []);

  // ── Single auto-return timeline (§19–§22) ──────────────────────────────────
  // ONE requestAnimationFrame loop, and it exists ONLY while status === "active".
  // The effect's cleanup cancels the frame whenever status changes (Skip →
  // "cancelled", completion → "redirecting") or the component unmounts. Because
  // the loop lives in an effect keyed on `status`, re-renders from setProgress /
  // setSecondsLeft never spawn a second loop, and there is no setTimeout that
  // could fire after the user opts out. This is the guarantee the spec requires:
  // no stale timer can navigate the user after Skip.
  useEffect(() => {
    if (status !== "active") return;
    let raf = 0;
    let last: number | null = null;

    const tick = (t: number) => {
      if (last === null) last = t;
      const dt = Math.min(t - last, 100); // clamp long frames (background-tab resume)
      last = t;

      if (!pausedRef.current) {
        elapsedRef.current += dt;
        const remaining = Math.max(0, REDIRECT_MS - elapsedRef.current);
        setSecondsLeft(Math.ceil(remaining / 1000));
        setProgress(Math.min(1, elapsedRef.current / REDIRECT_MS));

        if (remaining <= 0) {
          setStatus("redirecting");
          router.push("/");
          return; // stop the loop — do not schedule another frame
        }
      }
      raf = requestAnimationFrame(tick);
    };

    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [status, router]);

  // Skip = CANCEL the auto-redirect (NOT "go home now"). Flipping status tears
  // down the rAF loop above; the user then stays until they choose to leave.
  const cancelAutoRedirect = useCallback(() => {
    setStatus((s) => (s === "active" ? "cancelled" : s));
  }, []);

  const support =
    from === "contact"
      ? "Your message has reached our team. There's nothing more to do — we'll review it and reply from a real person, not a bot."
      : "Your request has been received. There's nothing more you need to submit — our team takes it from here.";

  // aria-live text changes ONLY on status change — never once per second — so
  // screen readers announce the countdown intent and its cancellation, not a
  // per-tick stream (§23).
  const liveMessage =
    status === "cancelled"
      ? "Automatic return cancelled. You can stay on this page as long as you like."
      : status === "redirecting"
        ? "Returning you home now."
        : `Returning you home in about ${REDIRECT_SECONDS} seconds. Select Skip to stay on this page.`;

  // Under reduced motion the bar advances in discrete per-second steps (matches
  // the real timer, but avoids a continuously animating element).
  const barPct = reduce
    ? Math.round(((REDIRECT_SECONDS - secondsLeft) / REDIRECT_SECONDS) * 100)
    : Math.round(progress * 100);

  const reveal = (delay: number) =>
    reduce
      ? { initial: { opacity: 1, y: 0 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0 } }
      : {
          initial: { opacity: 0, y: 12 },
          animate: { opacity: 1, y: 0 },
          transition: { duration: 0.5, ease: [0.16, 1, 0.3, 1] as const, delay },
        };

  return (
    <Container className="flex min-h-[70vh] max-w-2xl flex-col items-center justify-center py-20 text-center md:py-28">
      {/* Animated success mark (replaces the old "Q") */}
      <motion.div {...reveal(0)}>
        <SuccessCheck reduce={reduce} />
      </motion.div>

      <motion.p
        className="mt-8 text-xs font-bold uppercase tracking-[0.2em] text-muted-foreground"
        {...reveal(0.12)}
      >
        MESSAGE RECEIVED
      </motion.p>

      <motion.h1
        className="mt-4 font-display text-3xl font-extrabold tracking-tight text-foreground text-balance sm:text-5xl"
        {...reveal(0.2)}
      >
        You&apos;re on the right signal.
      </motion.h1>

      <motion.p
        className="mt-4 max-w-lg text-pretty text-base leading-relaxed text-muted-foreground sm:text-lg"
        {...reveal(0.3)}
      >
        {support}
      </motion.p>

      {/* Primary next actions (real routes). Hovering/focusing this row pauses the
          countdown so a redirect never fires mid-reach; the bar pauses with it,
          so the progress always reflects the real remaining time (§22). */}
      <motion.div
        className="mt-9 flex w-full flex-col items-center gap-3 sm:w-auto sm:flex-row"
        {...reveal(0.4)}
        onMouseEnter={() => setPaused(true)}
        onMouseLeave={() => setPaused(false)}
        onFocusCapture={() => setPaused(true)}
        onBlurCapture={() => setPaused(false)}
      >
        <Button asChild variant="brand" size="pill" className="w-full sm:w-auto">
          <Link href="/">
            Continue to home
            <ArrowRight className="size-4" />
          </Link>
        </Button>
        <Button asChild variant="outline" size="pill" className="w-full sm:w-auto">
          <Link href="/#solutions">Explore solutions</Link>
        </Button>
        <Button asChild variant="outline" size="pill" className="w-full sm:w-auto">
          <Link href="/industries">Explore industries</Link>
        </Button>
      </motion.div>

      {/* Auto-return timeline / post-skip state */}
      <motion.div className="mt-10 w-full max-w-xs" {...reveal(0.5)}>
        {status === "cancelled" ? (
          <div className="flex flex-col items-center gap-3">
            <p className="text-sm text-muted-foreground">You can stay here as long as you like.</p>
            <Button asChild variant="outline" size="pill" className="w-full sm:w-auto">
              <Link href="/">
                <Home className="size-4" />
                Return home
              </Link>
            </Button>
          </div>
        ) : (
          <div>
            <div className="flex items-center justify-between text-[11px] font-medium text-muted-foreground">
              <span aria-hidden>
                {status === "redirecting"
                  ? "Taking you home…"
                  : paused
                    ? "Auto-return paused"
                    : `Returning you home in ${secondsLeft} second${secondsLeft === 1 ? "" : "s"}`}
              </span>
              {status === "active" && (
                <button
                  type="button"
                  onClick={cancelAutoRedirect}
                  aria-label="Skip — cancel the automatic return and stay on this page"
                  className="cursor-pointer font-semibold text-foreground underline-offset-2 hover:underline focus-visible:underline focus-visible:outline-none"
                >
                  Skip
                </button>
              )}
            </div>
            <div
              className="mt-2 h-1 overflow-hidden rounded-full bg-border"
              role="progressbar"
              aria-label="Time until automatic return home"
              aria-valuemin={0}
              aria-valuemax={REDIRECT_SECONDS}
              aria-valuenow={REDIRECT_SECONDS - secondsLeft}
            >
              <div
                className="h-full rounded-full bg-gradient-to-r from-sky-400 via-cyan-400 to-amber-400"
                style={{ width: `${barPct}%` }}
              />
            </div>
          </div>
        )}
      </motion.div>

      {/* Status announcements for assistive tech — updates only on state change. */}
      <p className="sr-only" role="status" aria-live="polite">
        {liveMessage}
      </p>
    </Container>
  );
}

/**
 * SuccessCheck — premium animated success mark.
 * Sequence (motion users): container springs in → gradient ring draws (top-start)
 * → checkmark strokes itself → soft glow settles. Under reduced motion the final
 * drawn state is shown immediately with no drawing/scale animation. The success
 * meaning never depends on the animation or on color alone: the checkmark shape,
 * the accessible label, and the "MESSAGE RECEIVED" copy all convey it (§13–§15).
 */
function SuccessCheck({ reduce }: { reduce: boolean }) {
  const draw = (delay: number, duration: number) =>
    reduce
      ? { initial: { pathLength: 1 }, animate: { pathLength: 1 }, transition: { duration: 0 } }
      : {
          initial: { pathLength: 0 },
          animate: { pathLength: 1 },
          transition: { duration, delay, ease: "easeInOut" as const },
        };

  return (
    <div
      className="relative flex size-24 items-center justify-center sm:size-28"
      role="img"
      aria-label="Success — message received"
    >
      {/* Soft brand glow (cyan → warm), settles at the end */}
      <motion.span
        aria-hidden
        className="absolute inset-2 rounded-full blur-xl"
        style={{
          background:
            "radial-gradient(circle, rgba(56,189,248,0.45) 0%, rgba(245,166,35,0.18) 55%, rgba(0,0,0,0) 72%)",
        }}
        initial={reduce ? { opacity: 0.5, scale: 1 } : { opacity: 0, scale: 0.5 }}
        animate={{ opacity: 0.55, scale: 1 }}
        transition={reduce ? { duration: 0 } : { duration: 0.8, delay: 0.5, ease: "easeOut" }}
      />

      <motion.svg
        viewBox="0 0 80 80"
        fill="none"
        className="relative size-full"
        initial={reduce ? { scale: 1, opacity: 1 } : { scale: 0.7, opacity: 0 }}
        animate={{ scale: 1, opacity: 1 }}
        transition={reduce ? { duration: 0 } : { type: "spring", stiffness: 260, damping: 20 }}
      >
        <defs>
          <linearGradient id="quto-check-grad" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%" stopColor="#38bdf8" />
            <stop offset="55%" stopColor="#22d3ee" />
            <stop offset="100%" stopColor="#f5a623" />
          </linearGradient>
        </defs>

        {/* Faint track ring for depth (not color-only signalling) */}
        <circle
          cx="40"
          cy="40"
          r="34"
          className="text-foreground"
          stroke="currentColor"
          strokeOpacity="0.12"
          strokeWidth="4"
        />

        {/* Animated gradient ring — drawn from the top */}
        <g transform="rotate(-90 40 40)">
          <motion.circle
            cx="40"
            cy="40"
            r="34"
            stroke="url(#quto-check-grad)"
            strokeWidth="4"
            strokeLinecap="round"
            {...draw(0, 0.6)}
          />
        </g>

        {/* Checkmark — strokes itself after the ring */}
        <motion.path
          d="M25 41.5 L35.5 52 L56 29.5"
          stroke="url(#quto-check-grad)"
          strokeWidth="5"
          strokeLinecap="round"
          strokeLinejoin="round"
          {...draw(0.55, 0.4)}
        />
      </motion.svg>
    </div>
  );
}
