"use client";

import {
  useRef,
  useEffect,
  useState,
  type ReactNode,
  type CSSProperties,
} from "react";
import { gsap } from "gsap";

const DEFAULT_PARTICLE_COUNT = 12;
const DEFAULT_SPOTLIGHT_RADIUS = 400;
const DEFAULT_GLOW_COLOR = "220, 68, 22";
const MOBILE_BREAKPOINT = 768;

/* ---------- types ---------- */

type CardData = {
  title: string;
  description: string;
  label: string;
  children?: ReactNode;
};

type MagicBentoSectionProps = {
  eyebrow: string;
  heading: string;
  description: string;
  cards: CardData[];
  glowColor?: string;
  spotlightRadius?: number;
  particleCount?: number;
  enableStars?: boolean;
  enableSpotlight?: boolean;
  enableBorderGlow?: boolean;
  enableTilt?: boolean;
  enableMagnetism?: boolean;
  clickEffect?: boolean;
  textAutoHide?: boolean;
};

/* ---------- helpers ---------- */

function useMobileDetection() {
  const [isMobile, setIsMobile] = useState(false);
  useEffect(() => {
    const check = () => setIsMobile(window.innerWidth <= MOBILE_BREAKPOINT);
    check();
    window.addEventListener("resize", check);
    return () => window.removeEventListener("resize", check);
  }, []);
  return isMobile;
}

function calculateSpotlightValues(radius: number) {
  return { proximity: radius * 0.5, fadeDistance: radius * 0.75 };
}

function updateCardGlow(
  card: HTMLElement,
  mx: number,
  my: number,
  glow: number,
  radius: number,
) {
  const r = card.getBoundingClientRect();
  card.style.setProperty("--glow-x", `${((mx - r.left) / r.width) * 100}%`);
  card.style.setProperty("--glow-y", `${((my - r.top) / r.height) * 100}%`);
  card.style.setProperty("--glow-intensity", glow.toString());
  card.style.setProperty("--glow-radius", `${radius}px`);
}

/* ---------- ParticleCard ---------- */

function ParticleCard({
  children,
  className = "",
  style,
  disabled,
  particleCount,
  glowColor,
  enableTilt,
  enableMagnetism,
  clickEffect,
}: {
  children: ReactNode;
  className?: string;
  style?: CSSProperties;
  disabled: boolean;
  particleCount: number;
  glowColor: string;
  enableTilt: boolean;
  enableMagnetism: boolean;
  clickEffect: boolean;
}) {
  const cardRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (disabled || !cardRef.current) return;

    const el = cardRef.current;
    const particles: HTMLDivElement[] = [];
    const timeouts: ReturnType<typeof setTimeout>[] = [];
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let magnetAnim: any = null;
    let hovered = false;

    const spawnParticles = () => {
      const { width, height } = el.getBoundingClientRect();
      for (let i = 0; i < particleCount; i++) {
        const tid = setTimeout(() => {
          if (!hovered) return;
          const p = document.createElement("div");
          p.style.cssText = `
            position:absolute;width:4px;height:4px;border-radius:50%;
            background:rgba(${glowColor},0.9);
            box-shadow:0 0 6px rgba(${glowColor},0.5);
            pointer-events:none;z-index:100;
            left:${Math.random() * width}px;top:${Math.random() * height}px;
          `;
          el.appendChild(p);
          particles.push(p);
          gsap.fromTo(p, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.3, ease: "back.out(1.7)" });
          gsap.to(p, { x: (Math.random() - 0.5) * 100, y: (Math.random() - 0.5) * 100, rotation: Math.random() * 360, duration: 2 + Math.random() * 2, ease: "none", repeat: -1, yoyo: true });
          gsap.to(p, { opacity: 0.3, duration: 1.5, ease: "power2.inOut", repeat: -1, yoyo: true });
        }, i * 100);
        timeouts.push(tid);
      }
    };

    const clearParticles = () => {
      timeouts.forEach(clearTimeout);
      timeouts.length = 0;
      magnetAnim?.kill();
      particles.forEach((p) =>
        gsap.to(p, { scale: 0, opacity: 0, duration: 0.3, ease: "back.in(1.7)", onComplete: () => p.remove() }),
      );
      particles.length = 0;
    };

    const onEnter = () => {
      hovered = true;
      spawnParticles();
      if (enableTilt) {
        gsap.to(el, { rotateX: 5, rotateY: 5, duration: 0.3, ease: "power2.out", transformPerspective: 1000 });
      }
    };

    const onLeave = () => {
      hovered = false;
      clearParticles();
      if (enableTilt) gsap.to(el, { rotateX: 0, rotateY: 0, duration: 0.3, ease: "power2.out" });
      if (enableMagnetism) gsap.to(el, { x: 0, y: 0, duration: 0.3, ease: "power2.out" });
    };

    const onMove = (e: MouseEvent) => {
      if (!enableTilt && !enableMagnetism) return;
      const rect = el.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      const cx = rect.width / 2;
      const cy = rect.height / 2;
      if (enableTilt) {
        gsap.to(el, { rotateX: ((y - cy) / cy) * -10, rotateY: ((x - cx) / cx) * 10, duration: 0.1, ease: "power2.out", transformPerspective: 1000 });
      }
      if (enableMagnetism) {
        magnetAnim = gsap.to(el, { x: (x - cx) * 0.05, y: (y - cy) * 0.05, duration: 0.3, ease: "power2.out" });
      }
    };

    const onClick = (e: MouseEvent) => {
      if (!clickEffect) return;
      const rect = el.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      const maxD = Math.max(
        Math.hypot(x, y),
        Math.hypot(x - rect.width, y),
        Math.hypot(x, y - rect.height),
        Math.hypot(x - rect.width, y - rect.height),
      );
      const ripple = document.createElement("div");
      ripple.style.cssText = `
        position:absolute;width:${maxD * 2}px;height:${maxD * 2}px;border-radius:50%;
        background:radial-gradient(circle,rgba(${glowColor},0.4) 0%,rgba(${glowColor},0.2) 30%,transparent 70%);
        left:${x - maxD}px;top:${y - maxD}px;pointer-events:none;z-index:1000;
      `;
      el.appendChild(ripple);
      gsap.fromTo(ripple, { scale: 0, opacity: 1 }, { scale: 1, opacity: 0, duration: 0.8, ease: "power2.out", onComplete: () => ripple.remove() });
    };

    el.addEventListener("mouseenter", onEnter);
    el.addEventListener("mouseleave", onLeave);
    el.addEventListener("mousemove", onMove);
    el.addEventListener("click", onClick);

    return () => {
      hovered = false;
      el.removeEventListener("mouseenter", onEnter);
      el.removeEventListener("mouseleave", onLeave);
      el.removeEventListener("mousemove", onMove);
      el.removeEventListener("click", onClick);
      clearParticles();
    };
  }, [disabled, particleCount, glowColor, enableTilt, enableMagnetism, clickEffect]);

  return (
    <div ref={cardRef} className={className} style={{ ...style, position: "relative", overflow: "hidden" }}>
      {children}
    </div>
  );
}

/* ---------- GlobalSpotlight ---------- */

function GlobalSpotlight({
  gridRef,
  disabled,
  spotlightRadius,
  glowColor,
}: {
  gridRef: React.RefObject<HTMLDivElement | null>;
  disabled: boolean;
  spotlightRadius: number;
  glowColor: string;
}) {
  useEffect(() => {
    if (disabled || !gridRef.current) return;

    const spotlight = document.createElement("div");
    spotlight.style.cssText = `
      position:fixed;width:800px;height:800px;border-radius:50%;pointer-events:none;
      background:radial-gradient(circle,
        rgba(${glowColor},0.15) 0%,rgba(${glowColor},0.08) 15%,
        rgba(${glowColor},0.04) 25%,rgba(${glowColor},0.02) 40%,
        rgba(${glowColor},0.01) 65%,transparent 70%);
      z-index:200;opacity:0;transform:translate(-50%,-50%);
      mix-blend-mode:screen;will-change:transform,opacity;
    `;
    document.body.appendChild(spotlight);

    const grid = gridRef.current;

    const onMove = (e: MouseEvent) => {
      const rect = grid.getBoundingClientRect();
      const inside = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
      const cards = grid.querySelectorAll<HTMLElement>(".mb-card");

      if (!inside) {
        gsap.to(spotlight, { opacity: 0, duration: 0.3, ease: "power2.out" });
        cards.forEach((c) => c.style.setProperty("--glow-intensity", "0"));
        return;
      }

      const { proximity, fadeDistance } = calculateSpotlightValues(spotlightRadius);
      let minDist = Infinity;

      cards.forEach((card) => {
        const cr = card.getBoundingClientRect();
        const cx = cr.left + cr.width / 2;
        const cy = cr.top + cr.height / 2;
        const dist = Math.max(0, Math.hypot(e.clientX - cx, e.clientY - cy) - Math.max(cr.width, cr.height) / 2);
        minDist = Math.min(minDist, dist);
        const intensity = dist <= proximity ? 1 : dist <= fadeDistance ? (fadeDistance - dist) / (fadeDistance - proximity) : 0;
        updateCardGlow(card, e.clientX, e.clientY, intensity, spotlightRadius);
      });

      gsap.to(spotlight, { left: e.clientX, top: e.clientY, duration: 0.1, ease: "power2.out" });
      const opacity = minDist <= proximity ? 0.8 : minDist <= fadeDistance ? ((fadeDistance - minDist) / (fadeDistance - proximity)) * 0.8 : 0;
      gsap.to(spotlight, { opacity, duration: opacity > 0 ? 0.2 : 0.5, ease: "power2.out" });
    };

    const onLeave = () => {
      grid.querySelectorAll<HTMLElement>(".mb-card").forEach((c) => c.style.setProperty("--glow-intensity", "0"));
      gsap.to(spotlight, { opacity: 0, duration: 0.3, ease: "power2.out" });
    };

    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseleave", onLeave);
    return () => {
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseleave", onLeave);
      spotlight.remove();
    };
  }, [disabled, gridRef, spotlightRadius, glowColor]);

  return null;
}

/* ---------- MagicBentoSection ---------- */

export function MagicBentoSection({
  eyebrow,
  heading,
  description,
  cards,
  glowColor = DEFAULT_GLOW_COLOR,
  spotlightRadius = DEFAULT_SPOTLIGHT_RADIUS,
  particleCount = DEFAULT_PARTICLE_COUNT,
  enableStars = true,
  enableSpotlight = true,
  enableBorderGlow = true,
  enableTilt = true,
  enableMagnetism = true,
  clickEffect = true,
  textAutoHide = true,
}: MagicBentoSectionProps) {
  const gridRef = useRef<HTMLDivElement>(null);
  const isMobile = useMobileDetection();
  const disabled = isMobile;

  return (
    <section className="magic-bento-wrapper space-y-8">
      {/* Section heading — matches project's SectionHeading pattern */}
      <div className="space-y-3">
        <p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">
          {eyebrow}
        </p>
        <div className="space-y-2">
          <h2 className="text-2xl font-semibold tracking-[-0.05em] text-foreground sm:text-3xl">
            {heading}
          </h2>
          <p className="max-w-2xl text-sm leading-7 text-muted-foreground">
            {description}
          </p>
        </div>
      </div>

      {enableSpotlight && (
        <GlobalSpotlight
          gridRef={gridRef}
          disabled={disabled}
          spotlightRadius={spotlightRadius}
          glowColor={glowColor}
        />
      )}

      <div ref={gridRef} className="mb-grid" style={{ userSelect: "none" }}>
        {cards.map((card, index) => {
          const cls = [
            "mb-card",
            textAutoHide ? "mb-card--autohide" : "",
            enableBorderGlow ? "mb-card--glow" : "",
          ]
            .filter(Boolean)
            .join(" ");

          const cardStyle: CSSProperties = {
            "--glow-color": glowColor,
          } as CSSProperties;

          const content = (
            <>
              <div className="mb-card__header">
                <span className="mb-card__label">{card.label}</span>
              </div>
              <div className="mb-card__body">
                <h3 className="mb-card__title">{card.title}</h3>
                {card.description && (
                  <p className="mb-card__desc">{card.description}</p>
                )}
                {card.children && (
                  <div className="mb-card__extra">{card.children}</div>
                )}
              </div>
            </>
          );

          if (enableStars) {
            return (
              <ParticleCard
                key={index}
                className={cls}
                style={cardStyle}
                disabled={disabled}
                particleCount={particleCount}
                glowColor={glowColor}
                enableTilt={enableTilt}
                enableMagnetism={enableMagnetism}
                clickEffect={clickEffect}
              >
                {content}
              </ParticleCard>
            );
          }

          return (
            <div key={index} className={cls} style={cardStyle}>
              {content}
            </div>
          );
        })}
      </div>
    </section>
  );
}
