"use client";

import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
import Image from "next/image";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { Project } from "@/lib/data";
import {
  ArrowLeft,
  ArrowRight,
  AwardIcon,
  CloseIcon,
  DownloadIcon,
  CartIcon,
  ArrowUpRight,
  PlayIcon,
} from "@/components/icons";

type SlideItem = { type: "image"; src: string } | { type: "video"; src: string };

function toSlides(project: Project): SlideItem[] {
  const items: SlideItem[] = project.images.map(
    (src) => ({ type: "image", src }) as SlideItem,
  );
  if (project.videoUrl) items.push({ type: "video", src: project.videoUrl });
  return items;
}

const AUTOPLAY_MS = 5500;

export default function Slideshow({
  project,
  onClose,
  onPrevProject,
  onNextProject,
}: {
  project: Project | null;
  onClose: () => void;
  onPrevProject: (currentSlug: string) => void;
  onNextProject: (currentSlug: string) => void;
}) {
  const [index, setIndex] = useState(0);
  const [infoOpen, setInfoOpen] = useState(true);
  const [playing, setPlaying] = useState(true);
  const [zoomed, setZoomed] = useState(false);
  const touchStart = useRef<number | null>(null);
  const slides = useMemo(() => (project ? toSlides(project) : []), [project]);
  const reduceMotion = useReducedMotion();

  /** Stores the page's overflow so the scroll lock can never get stuck. */
  const lockRef = useRef<string | null>(null);

  const goto = useCallback(
    (i: number) => setIndex(slides.length ? (i + slides.length) % slides.length : 0),
    [slides.length],
  );
  const next = useCallback(() => setIndex((i) => (slides.length ? (i + 1) % slides.length : 0)), [slides.length]);
  const prev = useCallback(() => setIndex((i) => (slides.length ? (i - 1 + slides.length) % slides.length : 0)), [slides.length]);

  /* ---- scroll lock (isolated: only tied to open/close) ---- */
  useEffect(() => {
    if (!project) return;
    if (lockRef.current === null) {
      lockRef.current = document.body.style.overflow;
    }
    document.body.style.overflow = "hidden";
    return () => {
      document.body.style.overflow = lockRef.current ?? "";
      lockRef.current = null;
    };
  }, [project]);

  /* ---- keyboard ---- */
  useEffect(() => {
    if (!project) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") {
        if (zoomed) setZoomed(false);
        else onClose();
        return;
      }
      if (e.key === "ArrowRight") next();
      if (e.key === "ArrowLeft") prev();
      if (e.key === " " || e.key === "Spacebar") {
        e.preventDefault();
        setPlaying((v) => !v);
      }
      if (e.key.toLowerCase() === "i") setInfoOpen((v) => !v);
      if (e.key.toLowerCase() === "z") setZoomed((v) => !v);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [project, next, prev, onClose, zoomed]);

  /* ---- true slideshow auto-advance ---- */
  useEffect(() => {
    if (!project || !playing || zoomed || reduceMotion) return;
    if (slides.length < 2) return;
    const t = window.setTimeout(next, AUTOPLAY_MS);
    return () => window.clearTimeout(t);
  }, [project, playing, zoomed, index, next, slides.length, reduceMotion]);

  if (!project) return null;
  const slide = slides[index];

  return (
    <AnimatePresence>
      <motion.div
        key={project.slug}
        className="fixed inset-0 z-[85] flex flex-col bg-white pt-[4.5rem]"
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        transition={{ duration: 0.35 }}
        role="dialog"
        aria-modal="true"
        aria-label={`${project.title} slideshow`}
      >
        {/* ---------- top bar ---------- */}
        <div className="flex shrink-0 items-center justify-between gap-4 border-b border-[#ededed] px-5 py-3 md:px-10">
          <div className="min-w-0">
            <AnimatePresence mode="wait">
              <motion.h2
                key={project.slug}
                initial={{ opacity: 0, y: 8 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -8 }}
                transition={{ duration: 0.35 }}
                className="truncate text-[15px] font-medium tracking-tight md:text-lg"
              >
                {project.title}
              </motion.h2>
            </AnimatePresence>
            <p className="mt-0.5 text-[11px] uppercase tracking-[0.22em] text-faint">
              {project.category} · {project.year}
            </p>
          </div>

          <div className="flex items-center gap-1.5">
            <button
              type="button"
              onClick={() => setPlaying((v) => !v)}
              aria-label={playing ? "Pause slideshow" : "Play slideshow"}
              className="icon-grey hidden rounded-full border border-[#ececec] px-3.5 py-2 text-[11px] uppercase tracking-[0.18em] sm:flex sm:items-center sm:gap-2"
            >
              <PlayIcon className="h-3.5 w-3.5" />
              {playing ? "Pause" : "Play"}
            </button>
            <button
              type="button"
              onClick={() => setInfoOpen((v) => !v)}
              className="icon-grey hidden rounded-full border border-[#ececec] px-3.5 py-2 text-[11px] uppercase tracking-[0.18em] sm:block"
            >
              {infoOpen ? "Hide info" : "Project info"}
            </button>
            <button
              type="button"
              onClick={() => onPrevProject(project.slug)}
              aria-label="Previous project"
              className="icon-grey rounded-full p-2.5 hover:bg-[#f5f5f5]"
            >
              <ArrowLeft className="h-5 w-5" />
            </button>
            <button
              type="button"
              onClick={() => onNextProject(project.slug)}
              aria-label="Next project"
              className="icon-grey rounded-full p-2.5 hover:bg-[#f5f5f5]"
            >
              <ArrowRight className="h-5 w-5" />
            </button>
            <button
              type="button"
              onClick={onClose}
              aria-label="Close slideshow"
              className="icon-grey rounded-full p-2.5 hover:bg-[#f5f5f5]"
            >
              <CloseIcon className="h-5 w-5" />
            </button>
          </div>
        </div>

        {/* ---------- body: stage + info (scrolls, never overlapped) ---------- */}
        <div className="flex min-h-0 flex-1 flex-col overflow-y-auto lg:flex-row lg:overflow-hidden">
          {/* stage */}
          <div
            className="relative flex h-[52vh] shrink-0 items-center justify-center overflow-hidden bg-white lg:h-auto lg:min-h-0 lg:flex-1"
            onTouchStart={(e) => {
              touchStart.current = e.touches[0]?.clientX ?? null;
            }}
            onTouchEnd={(e) => {
              if (touchStart.current === null) return;
              const dx = (e.changedTouches[0]?.clientX ?? 0) - touchStart.current;
              if (Math.abs(dx) > 55) (dx < 0 ? next : prev)();
              touchStart.current = null;
            }}
          >
            <AnimatePresence mode="wait">
              <motion.div
                key={`${project.slug}-${index}`}
                className="relative h-full w-full"
                initial={{ opacity: 0, scale: 0.985 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.985 }}
                transition={{ duration: 0.45, ease: [0.16, 1, 0.3, 1] }}
              >
                {slide?.type === "video" ? (
                  <div className="absolute inset-4 flex items-center justify-center md:inset-8">
                    <div className="aspect-video w-full max-w-5xl overflow-hidden bg-[#0b0b0b] shadow-[0_30px_80px_-40px_rgba(0,0,0,0.5)]">
                      <iframe
                        src={slide.src}
                        title={`${project.title} video`}
                        className="h-full w-full"
                        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                        allowFullScreen
                        loading="lazy"
                      />
                    </div>
                  </div>
                ) : (
                  <button
                    type="button"
                    onClick={() => setZoomed(true)}
                    aria-label={`Enlarge ${project.title} view ${index + 1}`}
                    className="absolute inset-4 block cursor-zoom-in md:inset-8"
                  >
                    <Image
                      src={slide?.src ?? project.cover}
                      alt={`${project.title} — view ${(index ?? 0) + 1}`}
                      fill
                      sizes="(max-width: 1024px) 100vw, 70vw"
                      priority={index === 0}
                      className="object-contain"
                      quality={92}
                    />
                  </button>
                )}
              </motion.div>
            </AnimatePresence>

            <button
              type="button"
              onClick={prev}
              aria-label="Previous image"
              className="icon-grey absolute left-2 top-1/2 hidden -translate-y-1/2 rounded-full bg-white/85 p-3 backdrop-blur md:block"
            >
              <ArrowLeft className="h-6 w-6" />
            </button>
            <button
              type="button"
              onClick={next}
              aria-label="Next image"
              className="icon-grey absolute right-2 top-1/2 hidden -translate-y-1/2 rounded-full bg-white/85 p-3 backdrop-blur md:block"
            >
              <ArrowRight className="h-6 w-6" />
            </button>

            <span className="pointer-events-none absolute bottom-3 left-4 rounded-full bg-white/90 px-3 py-1 text-[10px] uppercase tracking-[0.2em] text-faint backdrop-blur md:left-8">
              Click image to enlarge
            </span>
          </div>

          {/* info rail — own scroll, cannot be covered by the thumbnail strip */}
          <AnimatePresence initial={false}>
            {infoOpen && (
              <motion.aside
                key="info"
                className="min-h-0 w-full shrink-0 border-t border-[#ededed] bg-white px-6 py-7 lg:w-[380px] lg:shrink lg:overflow-y-auto lg:border-l lg:border-t-0 lg:px-8 lg:py-10"
                initial={{ x: 40, opacity: 0 }}
                animate={{ x: 0, opacity: 1 }}
                exit={{ x: 40, opacity: 0 }}
                transition={{ duration: 0.45, ease: [0.16, 1, 0.3, 1] }}
              >
                <p className="text-[11px] uppercase tracking-[0.28em] text-faint">
                  {project.category}
                </p>
                <h3 className="mt-2 text-2xl font-medium tracking-display">
                  {project.title}
                </h3>
                {project.location ? (
                  <p className="mt-1 text-sm text-mute">{project.location}</p>
                ) : null}

                <p className="mt-5 text-[15px] leading-relaxed text-ink-soft">
                  {project.description}
                </p>

                {project.specs.length > 0 && (
                  <>
                    <h4 className="mt-8 text-[11px] uppercase tracking-[0.24em] text-faint">
                      Specifications
                    </h4>
                    <ul className="mt-3 space-y-2 text-sm text-ink-soft">
                      {project.specs.map((spec) => (
                        <li key={spec} className="flex gap-2.5">
                          <span className="mt-2 h-[3px] w-[3px] shrink-0 rounded-full bg-[#c6c6c6]" />
                          <span className="leading-relaxed">{spec}</span>
                        </li>
                      ))}
                    </ul>
                  </>
                )}

                {project.awards.length > 0 && (
                  <>
                    <h4 className="mt-8 flex items-center gap-2 text-[11px] uppercase tracking-[0.24em] text-faint">
                      <AwardIcon className="h-4 w-4" /> Awards
                    </h4>
                    <ul className="mt-3 space-y-2 text-sm text-ink-soft">
                      {project.awards.map((award) => (
                        <li key={award.label}>
                          {award.url ? (
                            <a
                              href={award.url}
                              target="_blank"
                              rel="noopener noreferrer"
                              className="link-underline decoration-from-font"
                            >
                              {award.label}
                            </a>
                          ) : (
                            <span>{award.label}</span>
                          )}
                        </li>
                      ))}
                    </ul>
                  </>
                )}

                {project.credits.length > 0 && (
                  <>
                    <h4 className="mt-8 text-[11px] uppercase tracking-[0.24em] text-faint">
                      Credits
                    </h4>
                    <dl className="mt-3 space-y-1.5 text-sm">
                      {project.credits.map((credit) => (
                        <div key={credit.role} className="flex gap-3">
                          <dt className="w-24 shrink-0 text-mute">{credit.role}</dt>
                          <dd className="text-ink-soft">
                            {credit.url ? (
                              <a
                                href={credit.url}
                                target="_blank"
                                rel="noopener noreferrer"
                                className="link-underline"
                              >
                                {credit.value}
                              </a>
                            ) : (
                              credit.value
                            )}
                          </dd>
                        </div>
                      ))}
                    </dl>
                  </>
                )}

                {project.buyUrl && (
                  <a
                    href={project.buyUrl}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="group mt-9 flex items-center justify-between gap-3 rounded-full bg-[#0a0a0a] px-6 py-4 text-[12px] font-medium uppercase tracking-[0.2em] text-white transition-all hover:bg-[#262626]"
                  >
                    <span className="flex items-center gap-2.5">
                      <CartIcon className="h-4 w-4" />
                      {project.buyLabel ?? "Buy now"}
                    </span>
                    <ArrowUpRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5" />
                  </a>
                )}

                {project.externalLinks.map((link) => (
                  <a
                    key={link.url}
                    href={link.url}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="mt-3 flex items-center justify-between gap-3 rounded-full border border-[#e4e4e4] px-6 py-4 text-[12px] uppercase tracking-[0.18em] text-ink-soft transition-colors hover:border-[#111]"
                  >
                    <span className="flex items-center gap-2.5">
                      <DownloadIcon className="h-4 w-4" />
                      {link.label}
                    </span>
                    <ArrowUpRight className="h-4 w-4" />
                  </a>
                ))}

                {/* bottom spacer so the last line is never hidden behind the strip */}
                <div className="h-2" />
              </motion.aside>
            )}
          </AnimatePresence>
        </div>

        {/* ---------- thumbnail strip: always pinned, jumps to that slide ---------- */}
        <div className="shrink-0 border-t border-[#ededed] bg-white px-4 py-3">
          <div className="flex items-center gap-2.5 overflow-x-auto pb-1">
            {slides.map((item, i) => (
              <button
                key={`${item.type}-${item.src}-${i}`}
                type="button"
                onClick={() => {
                  setPlaying(false);
                  setIndex(i);
                }}
                aria-label={`Show view ${i + 1} large`}
                className={`relative h-16 w-24 shrink-0 overflow-hidden rounded-[3px] border transition-all duration-300 ${
                  i === index
                    ? "border-[#0a0a0a] opacity-100 shadow-sm"
                    : "border-transparent opacity-45 hover:opacity-90"
                }`}
              >
                {item.type === "video" ? (
                  <span className="flex h-full w-full items-center justify-center bg-[#111] text-[10px] uppercase tracking-widest text-white">
                    Video
                  </span>
                ) : (
                  <Image
                    src={item.src}
                    alt=""
                    fill
                    sizes="96px"
                    className="object-contain"
                    quality={70}
                  />
                )}
              </button>
            ))}
            <span className="ml-auto shrink-0 pl-4 text-[11px] tabular-nums tracking-[0.2em] text-faint">
              {String(index + 1).padStart(2, "0")} /{" "}
              {String(slides.length).padStart(2, "0")}
            </span>
          </div>
        </div>

        {/* ---------- zoom overlay: this is where the picture really gets bigger ---------- */}
        <AnimatePresence>
          {zoomed && slide?.type === "image" && (
            <motion.div
              key="zoom"
              className="fixed inset-0 z-[95] flex items-center justify-center bg-white/95 px-4 pb-4 pt-[5.5rem] backdrop-blur-sm md:px-10 md:pb-10 md:pt-[6.5rem]"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.3 }}
              onClick={() => setZoomed(false)}
              role="dialog"
              aria-label={`Zoomed ${project.title} view ${index + 1}`}
            >
              <motion.div
                className="relative h-full w-full"
                initial={{ scale: 0.94 }}
                animate={{ scale: 1 }}
                exit={{ scale: 0.94 }}
                transition={{ duration: 0.4, ease: [0.16, 1, 0.3, 1] }}
              >
                <Image
                  src={slide.src}
                  alt={`${project.title} — enlarged view ${index + 1}`}
                  fill
                  sizes="100vw"
                  className="object-contain"
                  quality={92}
                />
              </motion.div>
              <button
                type="button"
                onClick={() => setZoomed(false)}
                aria-label="Close zoom"
                className="icon-grey absolute right-5 top-[5.5rem] rounded-full border border-[#e4e4e4] bg-white p-3 shadow-sm hover:bg-[#f5f5f5]"
              >
                <CloseIcon className="h-5 w-5" />
              </button>
            </motion.div>
          )}
        </AnimatePresence>
      </motion.div>
    </AnimatePresence>
  );
}
