"use client";

import {
  useEffect,
  useRef,
  useState,
  type ReactNode,
  type MouseEvent as ReactMouseEvent,
} from "react";
import Link from "next/link";
import Image from "next/image";
import { ArrowRight, Sparkles, Star } from "lucide-react";
import { m, useMotionValue, useSpring, useTransform } from "framer-motion";
import { useRouter } from "next/navigation";
import { Container } from "@/components/common/Container";
import { CalculatorWidget } from "@/components/calculator/CalculatorWidget";
import type { CalculatorContinueParams } from "@/components/calculator/CalculatorWidget";
import { Counter } from "@/components/motion/Counter";
import { Reveal } from "@/components/motion/Reveal";
import { useTranslation } from "@/hooks/useTranslation";
import { useCurrencyInfo } from "@/hooks/queries/useSettings";
import type { CurrencyInfoData } from "@/api/settings.api";
import { sendRemittanceApi } from "@/api/sendRemittance.api";
import type { TransferMethod } from "@/types";
import { cn, formatNumber } from "@/lib/utils";

const TX_TYPE_SLUG: Record<TransferMethod, string> = {
  bank: "bank-transfer",
  cash: "cash-pickup",
  mobile: "mobile_money",
};

const EASE: [number, number, number, number] = [0.16, 1, 0.3, 1];

// Featured corridors for the hero ticker — real rates come from the public
// currency-info API; a pair silently drops if either currency isn't in the
// live response (never a fake fallback number).
const FX_PAIRS: Array<{ senderCode: string; receiverCode: string }> = [
  { senderCode: "USD", receiverCode: "BDT" },
  { senderCode: "USD", receiverCode: "INR" },
  { senderCode: "USD", receiverCode: "PKR" },
  { senderCode: "USD", receiverCode: "PHP" },
  { senderCode: "EUR", receiverCode: "MXN" },
];

const REVIEWER_AVATARS = [
  "/avatars/user-1.jpg",
  "/avatars/user-2.jpg",
  "/avatars/user-3.jpg",
  "/avatars/user-4.jpg",
];

const STATS = [
  { to: 2, suffix: "M+", labelKey: "hero.stat1" },
  { to: 80, suffix: "+", labelKey: "hero.stat2" },
  { to: 12, suffix: "B+", labelKey: "hero.stat3", prefix: "$" },
];

export function Hero() {
  const { t, dir } = useTranslation();
  const router = useRouter();
  const { data: apiData } = useCurrencyInfo();

  async function handleContinue({ sendAmount, from, to, method, coupon }: CalculatorContinueParams) {
    if (!apiData) { router.push("/send"); return; }
    const senderCur = apiData.sender_currency.find((c) => c.code === from);
    const receiverCur = apiData.receiver_currency.find((c) => c.code === to);
    const slug = TX_TYPE_SLUG[method];
    const txType = apiData.transaction_type.find((tx) => tx.slug === slug) ?? apiData.transaction_type[0];
    if (!senderCur || !receiverCur || !txType) { router.push("/send"); return; }
    try {
      const data = (await sendRemittanceApi.store({
        type: txType.title,
        send_money: sendAmount,
        sender_currency: senderCur.id,
        receiver_currency: receiverCur.id,
        ...(coupon ? { coupon } : {}),
      })) as { temporary_data?: { identifier?: string } };
      const identifier: string = data?.temporary_data?.identifier ?? "";
      if (identifier) localStorage.setItem("send_identifier", identifier);
      router.push("/send?step=2");
    } catch {
      router.push("/send");
    }
  }
  const headline = t("hero.title");
  const headlineWords = headline.split(" ");
  const accentWords = 2;

  return (
    <section className="relative isolate overflow-hidden pt-10 pb-20 lg:pb-28">
      <DriftBlobs />
      <m.div
        aria-hidden
        className="absolute inset-0 -z-10 grid-pattern opacity-50 dark:opacity-25"
        animate={{ backgroundPositionX: ["0px", "48px"] }}
        transition={{ duration: 18, ease: "linear", repeat: Infinity }}
      />

      <Container>
        <FxTicker apiData={apiData} />

        <div className="mt-10 grid items-center gap-12 lg:grid-cols-2 lg:gap-16">
          <div>
            <Reveal>
              <span className="eyebrow">
                <Sparkles className="h-3.5 w-3.5" />
                {t("hero.badge")}
              </span>
            </Reveal>

            <h1 className="mt-6 text-balance text-display-xl tracking-tight text-slate-900 dark:text-white sm:text-display-2xl">
              <m.span
                initial="hidden"
                animate="visible"
                variants={{
                  hidden: {},
                  visible: {
                    transition: { staggerChildren: 0.04, delayChildren: 0.05 },
                  },
                }}
                className="inline"
              >
                {headlineWords.map((word, i) => {
                  const isAccent = i >= headlineWords.length - accentWords;
                  return (
                    <m.span
                      key={`${word}-${i}`}
                      variants={{
                        hidden: { opacity: 0, y: 12, filter: "blur(4px)" },
                        visible: {
                          opacity: 1,
                          y: 0,
                          filter: "blur(0px)",
                          transition: { duration: 0.5, ease: EASE },
                        },
                      }}
                      className={cn(
                        "inline-block",
                        isAccent && "gradient-text-animated",
                      )}
                    >
                      {word}
                      {i < headlineWords.length - 1 ? " " : ""}
                    </m.span>
                  );
                })}
              </m.span>
            </h1>

            <Reveal delay={0.35}>
              <p className="mt-6 max-w-xl text-pretty text-base leading-[1.7] text-slate-600 dark:text-slate-300 sm:text-lg">
                {t("hero.subtitle")}
              </p>
            </Reveal>

            <Reveal
              delay={0.45}
              className="mt-6 flex flex-wrap items-center gap-3"
            >
              <MagneticLink
                href="/register"
                className="group inline-flex items-center justify-center gap-2 rounded-full bg-brand-600 px-7 py-3 text-base font-semibold text-white shadow-soft transition-all duration-200 ease-snappy hover:bg-brand-700 hover:shadow-glow"
              >
                {t("hero.ctaPrimary")}
                <ArrowRight
                  className="h-4 w-4 transition-transform duration-200 group-hover:translate-x-0.5"
                  style={{
                    transform: dir === "rtl" ? "scaleX(-1)" : undefined,
                  }}
                />
              </MagneticLink>
              <MagneticLink
                href="/how-it-works"
                className="inline-flex items-center justify-center gap-2 rounded-full border border-slate-200 px-7 py-3 text-base font-semibold text-slate-900 transition-all duration-200 hover:border-slate-300 hover:bg-slate-50 dark:border-white/[0.08] dark:text-white dark:hover:border-white/[0.16] dark:hover:bg-white/[0.04]"
              >
                {t("hero.ctaSecondary")}
              </MagneticLink>
            </Reveal>

            <Reveal delay={0.55} className="mt-6 flex items-center gap-3">
              <div className="flex -space-x-2">
                {REVIEWER_AVATARS.map((src) => (
                  <Image
                    key={src}
                    src={src}
                    alt=""
                    width={32}
                    height={32}
                    className="h-8 w-8 rounded-full object-cover shadow-soft"
                  />
                ))}
              </div>
              <div className="flex items-center gap-1">
                <div className="flex items-center">
                  {[1, 2, 3, 4, 5].map((i) => (
                    <Star
                      key={i}
                      className="h-3.5 w-3.5 fill-amber-400 text-amber-400"
                    />
                  ))}
                </div>
                <span className="ms-1 text-sm font-semibold text-slate-700 dark:text-slate-200">
                  4.9
                </span>
                <span className="text-sm text-slate-500 dark:text-slate-400">
                  · {t("hero.reviewsCount")}
                </span>
              </div>
            </Reveal>

            <Reveal
              delay={0.65}
              className="mt-10 grid grid-cols-3 gap-6 border-t border-slate-200/70 pt-8 dark:border-white/[0.06]"
            >
              {STATS.map((s) => (
                <div key={s.labelKey}>
                  <p className="text-2xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-3xl">
                    {s.prefix ?? ""}
                    <Counter to={s.to} />
                    {s.suffix}
                  </p>
                  <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                    {restOfLabel(t(s.labelKey))}
                  </p>
                </div>
              ))}
            </Reveal>
          </div>

          <Reveal delay={0.2} className="min-w-0">
            <div className="relative w-full">
              <div
                aria-hidden
                className="pointer-events-none absolute -inset-6 -z-10 rounded-[2.5rem] bg-gradient-to-br from-brand-500/20 via-accent-500/10 to-transparent blur-3xl"
              />
              <CalculatorWidget variant="hero" apiData={apiData} onContinue={apiData ? handleContinue : undefined} />
            </div>
          </Reveal>
        </div>
      </Container>
    </section>
  );
}

function restOfLabel(label: string): string {
  const parts = label.split(" ");
  return parts.slice(1).join(" ");
}

export function DriftBlobs() {
  return (
    <>
      <div aria-hidden className="absolute inset-0 -z-10 bg-mesh" />
      <m.div
        aria-hidden
        className="pointer-events-none absolute -top-24 start-1/4 -z-10 h-72 w-72 rounded-full bg-brand-400/30 blur-3xl dark:bg-brand-500/20"
        animate={{ x: [0, 40, -20, 0], y: [0, -20, 15, 0] }}
        transition={{ duration: 12, ease: "easeInOut", repeat: Infinity }}
      />
      <m.div
        aria-hidden
        className="pointer-events-none absolute bottom-0 end-1/4 -z-10 h-96 w-96 rounded-full bg-accent-400/25 blur-3xl dark:bg-accent-500/12"
        animate={{ x: [0, -30, 20, 0], y: [0, 20, -10, 0] }}
        transition={{
          duration: 12,
          ease: "easeInOut",
          repeat: Infinity,
          delay: 1,
        }}
      />
      <m.div
        aria-hidden
        className="pointer-events-none absolute top-1/3 -end-20 -z-10 h-72 w-72 rounded-full bg-purple-400/15 blur-3xl dark:bg-purple-500/10"
        animate={{ x: [0, -20, 0], y: [0, 15, 0] }}
        transition={{
          duration: 16,
          ease: "easeInOut",
          repeat: Infinity,
          delay: 2,
        }}
      />
    </>
  );
}

function FxTicker({ apiData }: { apiData: CurrencyInfoData | undefined }) {
  const fadeMask =
    "linear-gradient(to right, transparent 0%, black 6%, black 94%, transparent 100%)";

  const rates = FX_PAIRS.flatMap(({ senderCode, receiverCode }) => {
    const senderCur = apiData?.sender_currency.find((c) => c.code === senderCode);
    const receiverCur = apiData?.receiver_currency.find((c) => c.code === receiverCode);
    if (!senderCur || !receiverCur) return [];
    return [
      {
        pair: `${senderCode} → ${receiverCode}`,
        rate: formatNumber(parseFloat(receiverCur.rate) / parseFloat(senderCur.rate), undefined, 2),
      },
    ];
  });

  if (rates.length === 0) return null;

  return (
    <Reveal className="mx-auto max-w-3xl">
      <div
        className="group relative overflow-hidden"
        style={{
          WebkitMaskImage: fadeMask,
          maskImage: fadeMask,
        }}
      >
        <div className="flex w-max items-center gap-4 py-1 animate-marquee group-hover:[animation-play-state:paused]">
          {[...rates, ...rates].map((t, i) => (
            <div
              key={`${t.pair}-${i}`}
              className="inline-flex items-center gap-2 whitespace-nowrap rounded-full border border-slate-200/50 bg-white/60 px-3 py-1.5 backdrop-blur dark:border-slate-800/50 dark:bg-slate-900/60"
              dir="ltr"
            >
              <span className="text-xs font-semibold text-slate-600 dark:text-slate-300">
                {t.pair}
              </span>
              <span className="text-xs font-semibold tabular-nums text-slate-900 dark:text-white">
                {t.rate}
              </span>
            </div>
          ))}
        </div>
      </div>
    </Reveal>
  );
}

export function MagneticLink({
  href,
  className,
  children,
}: {
  href: string;
  className?: string;
  children: ReactNode;
}) {
  const ref = useRef<HTMLSpanElement>(null);
  const x = useMotionValue(0);
  const y = useMotionValue(0);
  const springX = useSpring(x, { stiffness: 250, damping: 18, mass: 0.6 });
  const springY = useSpring(y, { stiffness: 250, damping: 18, mass: 0.6 });
  const tx = useTransform(springX, (v) => v);
  const ty = useTransform(springY, (v) => v);
  const [enabled, setEnabled] = useState(false);

  useEffect(() => {
    if (typeof window === "undefined") return;
    const mq = window.matchMedia("(hover: hover) and (pointer: fine)");
    setEnabled(mq.matches);
  }, []);

  function onMove(e: ReactMouseEvent<HTMLSpanElement>) {
    if (!enabled || !ref.current) return;
    const r = ref.current.getBoundingClientRect();
    const cx = r.left + r.width / 2;
    const cy = r.top + r.height / 2;
    const dx = e.clientX - cx;
    const dy = e.clientY - cy;
    const max = 8;
    x.set(Math.max(-max, Math.min(max, dx * 0.25)));
    y.set(Math.max(-max, Math.min(max, dy * 0.25)));
  }
  function onLeave() {
    x.set(0);
    y.set(0);
  }

  return (
    <m.span
      ref={ref}
      style={{ x: tx, y: ty, display: "inline-block" }}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
    >
      <Link href={href} className={className}>
        {children}
      </Link>
    </m.span>
  );
}
