"use client";

import { motion, useScroll, useSpring } from "motion/react";
import { Children, type ReactNode, useEffect, useMemo, useRef, useState } from "react";
import { cn } from "@/lib/utils";

export type SlideMeta = {
  id: string;
  block: "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H";
  title: string;
  status?: "complete" | "placeholder";
};

type DeckProps = {
  children: ReactNode;
  slides: SlideMeta[];
  className?: string;
};

export function Deck({ children, slides, className }: DeckProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const items = useMemo(() => Children.toArray(children), [children]);
  const [activeIndex, setActiveIndex] = useState(0);

  const { scrollYProgress } = useScroll();
  const progress = useSpring(scrollYProgress, {
    stiffness: 120,
    damping: 30,
    mass: 0.4,
  });

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;
    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            const index = Number((entry.target as HTMLElement).dataset.index);
            if (!Number.isNaN(index)) setActiveIndex(index);
          }
        }
      },
      { root: null, threshold: 0.55 },
    );
    const sections = container.querySelectorAll<HTMLElement>("[data-slide]");
    sections.forEach((section) => observer.observe(section));
    return () => observer.disconnect();
  }, [items.length]);

  useEffect(() => {
    function scrollToSlide(index: number) {
      const clamped = Math.max(0, Math.min(items.length - 1, index));
      const target = containerRef.current?.querySelector<HTMLElement>(
        `[data-slide][data-index="${clamped}"]`,
      );
      if (target) target.scrollIntoView({ behavior: "smooth", block: "start" });
    }

    function onKey(event: KeyboardEvent) {
      const tag = (event.target as HTMLElement | null)?.tagName;
      if (tag === "INPUT" || tag === "TEXTAREA") return;
      switch (event.key) {
        case "ArrowDown":
        case "ArrowRight":
        case "PageDown":
        case " ":
          event.preventDefault();
          scrollToSlide(activeIndex + 1);
          break;
        case "ArrowUp":
        case "ArrowLeft":
        case "PageUp":
          event.preventDefault();
          scrollToSlide(activeIndex - 1);
          break;
        case "Home":
          event.preventDefault();
          scrollToSlide(0);
          break;
        case "End":
          event.preventDefault();
          scrollToSlide(items.length - 1);
          break;
        case "f":
        case "F":
          if (!document.fullscreenElement) document.documentElement.requestFullscreen();
          else document.exitFullscreen();
          break;
      }
    }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [activeIndex, items.length]);

  const activeMeta = slides[activeIndex];
  const isFeatureSlide = (index: number) => {
    const item = items[index];
    if (!item || typeof item !== "object" || !("props" in item)) return false;
    const props = (item as { props?: { variant?: string } }).props;
    return props?.variant === "feature";
  };

  const indicatorInverse = isFeatureSlide(activeIndex);

  return (
    <div ref={containerRef} className={cn("relative", className)}>
      {/* Top scroll-progress bar */}
      <motion.div
        style={{ scaleX: progress }}
        className="fixed inset-x-0 top-0 z-50 h-[3px] origin-left bg-accent-500"
      />

      {/* Right-side block indicator dots */}
      <nav
        aria-label="Slide navigation"
        className="fixed right-4 top-1/2 z-40 hidden -translate-y-1/2 flex-col gap-2 md:flex"
      >
        {slides.map((slide, index) => {
          const isActive = index === activeIndex;
          const prevBlock = index > 0 ? slides[index - 1].block : null;
          const blockBreak = prevBlock && prevBlock !== slide.block;
          return (
            <div key={slide.id} className={cn("flex flex-col items-end gap-2", blockBreak && "mt-2")}>
              {blockBreak && (
                <span
                  className={cn(
                    "font-mono text-[9px] tracking-[0.2em]",
                    indicatorInverse ? "text-white/40" : "text-ink-400",
                  )}
                >
                  {slide.block}
                </span>
              )}
              <button
                type="button"
                aria-label={`${slide.id.toUpperCase()} · ${slide.title}`}
                aria-current={isActive}
                onClick={() => {
                  const target = containerRef.current?.querySelector<HTMLElement>(
                    `[data-slide][data-index="${index}"]`,
                  );
                  target?.scrollIntoView({ behavior: "smooth", block: "start" });
                }}
                className={cn(
                  "h-[6px] w-[18px] rounded-[2px] transition-all duration-300",
                  indicatorInverse
                    ? isActive
                      ? "bg-accent-500"
                      : "bg-white/20 hover:bg-white/40"
                    : isActive
                      ? "bg-ink-900"
                      : "bg-ink-200 hover:bg-ink-400",
                )}
              />
            </div>
          );
        })}
      </nav>

      {/* Top-left active-slide eyebrow */}
      {activeMeta && (
        <div
          className={cn(
            "pointer-events-none fixed left-[clamp(24px,6vw,128px)] top-6 z-40 font-mono text-[11px] tracking-[0.18em]",
            indicatorInverse ? "text-white/55" : "text-ink-400",
          )}
        >
          BLOCK {activeMeta.block} · {activeMeta.id.toUpperCase()}
        </div>
      )}

      {items.map((slide, index) => (
        <div key={index} data-slide data-index={index}>
          {slide}
        </div>
      ))}
    </div>
  );
}
