"use client";

import { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from "react";
import { Check, Copy, Ticket } from "lucide-react";
import { useAllCoupons } from "@/hooks/queries/useCoupon";
import { useTranslation } from "@/hooks/useTranslation";
import { notify } from "@/lib/notify";
import { cn, formatCurrency } from "@/lib/utils";

const AUTOPLAY_MS = 5000;
const SWIPE_THRESHOLD_PX = 40;

export function CouponSlider() {
  const { dir, t } = useTranslation();
  const { coupons } = useAllCoupons();
  const [index, setIndex] = useState(0);
  const [paused, setPaused] = useState(false);
  const [dragging, setDragging] = useState(false);
  const [copiedId, setCopiedId] = useState<string | null>(null);
  const dragStartX = useRef(0);
  const dragDeltaX = useRef(0);

  async function copyCode(id: string, code: string) {
    try {
      await navigator.clipboard.writeText(code);
      setCopiedId(id);
      notify(t("app.couponSlider.copiedToast").replace("{code}", code), "success");
      setTimeout(() => setCopiedId(null), 2000);
    } catch {
      notify(t("app.couponSlider.copyFailedToast"), "error");
    }
  }

  // Clamp index if the list shrinks (e.g. a coupon runs out while viewing it).
  useEffect(() => {
    if (index >= coupons.length) setIndex(0);
  }, [coupons.length, index]);

  useEffect(() => {
    if (paused || dragging || coupons.length < 2) return;
    const id = setInterval(() => {
      setIndex((i) => (i + 1) % coupons.length);
    }, AUTOPLAY_MS);
    return () => clearInterval(id);
  }, [paused, dragging, coupons.length]);

  if (coupons.length === 0) return null;

  const coupon = coupons[index];
  const isPercent = coupon.coupon_type.toLowerCase().includes("percent");
  const canDrag = coupons.length > 1;

  function goTo(next: number) {
    setIndex(((next % coupons.length) + coupons.length) % coupons.length);
  }

  function handlePointerDown(e: ReactPointerEvent<HTMLDivElement>) {
    if (!canDrag) return;
    setDragging(true);
    dragStartX.current = e.clientX;
    dragDeltaX.current = 0;
    e.currentTarget.setPointerCapture(e.pointerId);
  }

  function handlePointerMove(e: ReactPointerEvent<HTMLDivElement>) {
    if (!dragging) return;
    dragDeltaX.current = e.clientX - dragStartX.current;
  }

  function handlePointerUp() {
    if (!dragging) return;
    setDragging(false);
    const delta = dragDeltaX.current;
    dragDeltaX.current = 0;
    if (Math.abs(delta) < SWIPE_THRESHOLD_PX) return;
    const swipedForward = dir === "rtl" ? delta > 0 : delta < 0;
    goTo(index + (swipedForward ? 1 : -1));
  }

  return (
    <div
      className="px-4 pb-3"
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
      onFocus={() => setPaused(true)}
      onBlur={() => setPaused(false)}
    >
      <div
        onPointerDown={handlePointerDown}
        onPointerMove={handlePointerMove}
        onPointerUp={handlePointerUp}
        onPointerCancel={handlePointerUp}
        className={cn(
          "relative touch-pan-y select-none overflow-hidden rounded-2xl border border-brand-200/60 bg-gradient-to-br from-brand-500/10 via-blue-500/5 to-transparent p-4 dark:border-brand-500/20 dark:from-brand-500/15 dark:via-blue-500/5",
          canDrag && "cursor-grab active:cursor-grabbing",
        )}
      >
        <div key={coupon.id} className="relative motion-safe:animate-fade-in">
          {/* Header — icon box + eyebrow on left, remaining availability pill on right */}
          <div className="flex items-center justify-between gap-2">
            <div className="flex min-w-0 items-center gap-2">
              <span className="grid h-7 w-7 shrink-0 place-items-center rounded-xl border border-brand-200 bg-white dark:border-brand-500/20 dark:bg-brand-500/10">
                <Ticket className="h-3.5 w-3.5 text-brand-600 dark:text-brand-300" aria-hidden />
              </span>
              <p className="truncate text-2xs font-semibold uppercase tracking-wider text-brand-700 dark:text-brand-300">
                {t("app.couponSlider.yourCoupon")}
              </p>
            </div>
            <span className="inline-flex shrink-0 items-center whitespace-nowrap rounded-full border border-brand-200/80 bg-white/80 px-2.5 py-0.5 text-2xs font-bold uppercase tracking-wider text-brand-700 dark:border-brand-500/30 dark:bg-brand-500/10 dark:text-brand-300">
              {t("app.couponSlider.remainingLabel").replace("{n}", String(coupon.remaining))}
            </span>
          </div>

          {/* Hero — discount is the loudest element on the card, with consistent 12px (mt-3) gap */}
          <div className="mt-3 flex items-baseline gap-1.5 leading-none">
            <span className="text-2xl font-bold tabular-nums tracking-tight text-slate-900 dark:text-white">
              {isPercent
                ? `${parseFloat(coupon.price).toFixed(2)}%`
                : formatCurrency(parseFloat(coupon.price), "USD")}
            </span>
            <span className="text-xs font-bold uppercase tracking-wider text-brand-600 dark:text-brand-400">
              {t("app.couponSlider.off")}
            </span>
          </div>

          {/* Divider — consistent 12px (my-3) breathing room above and below, dashed line */}
          <div className="my-3 border-t border-dashed border-brand-200/80 dark:border-brand-500/25" />

          {/* Footer — horizontal promo code row, balanced without vertical lines or height mismatches */}
          <div className="flex items-center justify-between gap-3">
            <span className="text-2xs font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400">
              {t("app.couponSlider.promoCode")}
            </span>
            <button
              type="button"
              onClick={() => copyCode(coupon.id, coupon.name)}
              aria-label={
                copiedId === coupon.id
                  ? t("app.couponSlider.copied")
                  : t("app.couponSlider.copyCodeAria").replace("{code}", coupon.name)
              }
              className="inline-flex items-center gap-1.5 rounded-lg border border-dashed border-brand-300 bg-brand-50/80 px-2.5 py-1 text-xs font-bold tracking-wider text-brand-700 shadow-2xs transition hover:bg-brand-100/80 dark:border-brand-500/40 dark:bg-brand-500/15 dark:text-brand-300 dark:hover:bg-brand-500/25"
            >
              {coupon.name}
              {copiedId === coupon.id ? (
                <Check className="h-3 w-3 text-accent-600 dark:text-accent-400" />
              ) : (
                <Copy className="h-3 w-3 opacity-70" />
              )}
            </button>
          </div>
        </div>

        {coupons.length > 1 && (
          <div className="relative mt-3 flex items-center justify-center gap-2">
            {coupons.map((c, i) => (
              <button
                key={c.id}
                type="button"
                onClick={() => goTo(i)}
                aria-label={t("app.couponSlider.showSlideAria")
                  .replace("{n}", String(i + 1))
                  .replace("{total}", String(coupons.length))}
                aria-current={i === index}
                className="grid h-4 w-4 place-items-center"
              >
                <span
                  className={cn(
                    "h-1.5 rounded-full bg-brand-500 transition-all duration-300 dark:bg-brand-400",
                    i === index ? "w-3 bg-brand-600 dark:bg-brand-300 opacity-100" : "w-1.5 opacity-30",
                  )}
                />
              </button>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}
