import { useEffect, useMemo, useRef, useState } from "react";
import { Sparkles, X } from "lucide-react";
import butterflyAsset from "@/assets/neon-butterfly.png.asset.json";
import { useAccount } from "@/hooks/useAccount";
import { useI18n } from "@/i18n";
import { formatBDT } from "@/data/packages";

type Phase = "hidden" | "flying" | "burst" | "reward";

const MIN_DELAY = 12_000;
const MAX_DELAY = 45_000;
const FLY_IN = 5200;
const HOLD = 13_000;
const FLY_OUT = 3200;

function reducedMotion() {
  return (
    typeof window !== "undefined" &&
    window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true
  );
}

/** Cubic bezier point for the flight curve. */
function bezier(t: number, p: number[]) {
  const [a, b, c, d] = p as [number, number, number, number];
  const u = 1 - t;
  return u * u * u * a + 3 * u * u * t * b + 3 * u * t * t * c + t * t * t * d;
}

const SPARKS = Array.from({ length: 12 }, (_, i) => {
  const angle = (i / 12) * Math.PI * 2;
  return { x: Math.cos(angle) * 70, y: Math.sin(angle) * 70 };
});

export function ButterflyBonus() {
  const { t } = useI18n();
  const { session, claimedToday, ready, claimBonus, profile } = useAccount();
  const [phase, setPhase] = useState<Phase>("hidden");
  const [reward, setReward] = useState<number | null>(null);
  const [claiming, setClaiming] = useState(false);
  const [round, setRound] = useState(0);
  const wrapRef = useRef<HTMLDivElement | null>(null);
  const frameRef = useRef<number | null>(null);
  const startRef = useRef<number>(0);

  const eligible = ready && Boolean(session) && !claimedToday;

  const debug = useMemo(() => {
    if (typeof window === "undefined") return false;
    return new URLSearchParams(window.location.search).get("butterfly") === "now";
  }, []);

  // Schedule the appearance (and every later re-appearance while unclaimed).
  useEffect(() => {
    if (!eligible || phase !== "hidden") return;
    const delay = debug ? 1200 : MIN_DELAY + Math.random() * (MAX_DELAY - MIN_DELAY);
    const timer = window.setTimeout(() => setPhase("flying"), delay);
    return () => window.clearTimeout(timer);
  }, [debug, eligible, phase, round]);

  // Flight animation: curved fly-in, gentle hover, then it flies away again.
  useEffect(() => {
    if (phase !== "flying") return;
    const el = wrapRef.current;
    if (!el) return;

    const w = window.innerWidth;
    const h = window.innerHeight;
    const fromLeft = Math.random() < 0.5;
    const size = Math.min(150, Math.max(96, w * 0.28));
    const topLimit = Math.max(90, h * 0.12);
    const bottomLimit = Math.min(h * 0.62, h - size - 40);

    const xs = fromLeft
      ? [-size, w * 0.35, w * 0.2, Math.min(w - size - 16, w * 0.55)]
      : [w, w * 0.55, w * 0.75, Math.max(16, w * 0.22)];
    const ys = [
      bottomLimit,
      topLimit,
      bottomLimit * 0.8,
      topLimit + (bottomLimit - topLimit) * 0.35,
    ];
    const endX = xs[3]!;
    const endY = ys[3]!;
    const exitX = fromLeft ? w + size : -size;

    el.style.width = `${size}px`;
    el.style.opacity = "1";

    if (reducedMotion()) {
      el.style.transform = `translate3d(${endX}px, ${endY}px, 0)`;
      const away = window.setTimeout(() => {
        setPhase("hidden");
        setRound((r) => r + 1);
      }, HOLD);
      return () => window.clearTimeout(away);
    }

    startRef.current = performance.now();

    const step = (now: number) => {
      const elapsed = now - startRef.current;
      let x: number;
      let y = endY;
      if (elapsed <= FLY_IN) {
        const raw = elapsed / FLY_IN;
        x = bezier(raw, xs);
        y = bezier(raw, ys);
      } else if (elapsed <= FLY_IN + HOLD) {
        x = endX + Math.sin(elapsed / 900) * 14;
        y = endY + Math.sin(elapsed / 700) * 12;
      } else {
        const raw = Math.min(1, (elapsed - FLY_IN - HOLD) / FLY_OUT);
        x = endX + (exitX - endX) * raw;
        y = endY - raw * 80;
        el.style.opacity = String(1 - raw);
        if (raw >= 1) {
          setPhase("hidden");
          setRound((r) => r + 1);
          return;
        }
      }
      const tilt = Math.sin(elapsed / 420) * 8;
      el.style.transform = `translate3d(${x}px, ${y}px, 0) rotate(${tilt}deg)`;
      frameRef.current = requestAnimationFrame(step);
    };
    frameRef.current = requestAnimationFrame(step);
    return () => {
      if (frameRef.current) cancelAnimationFrame(frameRef.current);
    };
  }, [phase]);

  async function handleCatch() {
    if (claiming || phase !== "flying") return;
    setClaiming(true);
    setPhase("burst");
    const result = await claimBonus();
    window.setTimeout(() => {
      if (result.claimed && typeof result.reward === "number") {
        setReward(result.reward);
        setPhase("reward");
      } else {
        setPhase("hidden");
      }
      setClaiming(false);
    }, 480);
  }

  if (!eligible && phase !== "reward") return null;

  return (
    <>
      {(phase === "flying" || phase === "burst") && (
        <div className="pointer-events-none fixed inset-0 z-30 overflow-hidden" aria-hidden={false}>
          <div
            ref={wrapRef}
            className="absolute top-0 left-0 opacity-0 will-change-transform"
            style={{ transition: "opacity 400ms ease" }}
          >
            <button
              type="button"
              onClick={handleCatch}
              aria-label={t("bonus.aria")}
              className="pointer-events-auto relative block w-full appearance-none bg-transparent p-0 focus-visible:outline-none"
            >
              <span
                className="absolute inset-0 -z-10 rounded-full blur-2xl"
                style={{
                  background:
                    "radial-gradient(circle, rgba(192,64,255,0.55), rgba(0,229,255,0.25) 55%, transparent 72%)",
                  animation: "cv-bfly-glow 2.4s ease-in-out infinite",
                }}
              />
              {phase === "burst" &&
                SPARKS.map((s, i) => (
                  <span
                    key={i}
                    className="absolute top-1/2 left-1/2 size-1.5 rounded-full"
                    style={
                      {
                        background: i % 2 ? "rgb(0,229,255)" : "rgb(226,120,255)",
                        boxShadow: "0 0 10px currentColor",
                        "--sx": `${s.x}px`,
                        "--sy": `${s.y}px`,
                        animation: "cv-spark 520ms ease-out forwards",
                      } as React.CSSProperties
                    }
                  />
                ))}
              <img
                src={butterflyAsset.url}
                alt=""
                className="w-full select-none drop-shadow-[0_0_18px_rgba(180,80,255,0.7)]"
                style={{
                  animation:
                    phase === "burst"
                      ? "cv-bfly-burst 480ms ease-out forwards"
                      : "cv-bfly-flap 320ms ease-in-out infinite",
                }}
                draggable={false}
              />
            </button>
          </div>
        </div>
      )}

      {phase === "reward" && reward !== null && (
        <div
          className="fixed inset-0 z-50 grid place-items-center bg-background/80 p-4 backdrop-blur-sm"
          role="dialog"
          aria-modal="true"
          aria-label={t("bonus.win.title")}
        >
          <div
            className="panel relative w-full max-w-sm rounded-3xl p-6 text-center"
            style={{ animation: "cv-bfly-pop 260ms ease-out", boxShadow: "0 0 60px rgba(150,60,255,0.35)" }}
          >
            <button
              type="button"
              onClick={() => setPhase("hidden")}
              aria-label={t("account.close")}
              className="absolute top-3 right-3 grid size-9 place-items-center rounded-xl text-muted-foreground hover:text-foreground"
            >
              <X className="size-4" aria-hidden />
            </button>
            <img src={butterflyAsset.url} alt="" className="mx-auto w-28" />
            <p className="mt-2 flex items-center justify-center gap-1.5 text-sm text-muted-foreground">
              <Sparkles className="size-4 text-primary" aria-hidden /> {t("bonus.win.title")}
            </p>
            <p className="neon-text mt-1 font-display text-4xl font-bold">+{formatBDT(reward)}</p>
            <p className="mt-3 text-sm text-muted-foreground">{t("bonus.win.sub")}</p>
            {profile && (
              <p className="mt-1 text-sm font-semibold">
                {t("account.balance")}: {formatBDT(Number(profile.balance))}
              </p>
            )}
            <button
              type="button"
              onClick={() => setPhase("hidden")}
              className="mt-5 h-12 w-full rounded-xl bg-primary font-display font-semibold text-primary-foreground hover:opacity-90 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
            >
              {t("bonus.win.ok")}
            </button>
          </div>
        </div>
      )}
    </>
  );
}
