"use client";

import { ChevronLeft, ChevronRight, X } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import type { GallerySlide } from "@/lib/product-galleries";
import { ProductTechSpecs } from "@/components/product/ProductTechSpecs";

type Props = {
  slides: GallerySlide[];
  alt: string;
  className?: string;
  resetKey?: string;
};

function slideImages(s: GallerySlide): string[] {
  if (s.kind === "specs") return [];
  if (s.mosaic?.length) return s.mosaic;
  return s.src ? [s.src] : [];
}

function isFichaSrc(src: string) {
  return /ficha/i.test(src);
}

const MOSAIC_CAPTIONS = [
  "Cuerpo y cierre frontal.",
  "Cuello camisero con vivo en contraste.",
  "Falda integrada con logo OT.",
  "Ficha técnica",
];

function pointOrigin(
  clientX: number,
  clientY: number,
  el: HTMLElement | null
) {
  if (!el) return { x: 50, y: 50 };
  const rect = el.getBoundingClientRect();
  if (!rect.width || !rect.height) return { x: 50, y: 50 };
  return {
    x: Math.min(100, Math.max(0, ((clientX - rect.left) / rect.width) * 100)),
    y: Math.min(100, Math.max(0, ((clientY - rect.top) / rect.height) * 100)),
  };
}

function MosaicTile({
  src,
  alt,
  label,
  className = "",
  onOpen,
}: {
  src: string;
  alt: string;
  label: string;
  className?: string;
  onOpen: () => void;
}) {
  const ref = useRef<HTMLButtonElement>(null);
  const [zoom, setZoom] = useState(false);
  const [origin, setOrigin] = useState({ x: 50, y: 50 });
  const ficha = isFichaSrc(src);

  return (
    <button
      ref={ref}
      type="button"
      className={`relative h-full w-full overflow-hidden bg-ot-cream-dark focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ot-gold ${className}`}
      onClick={onOpen}
      aria-label={label}
      onMouseEnter={() => setZoom(true)}
      onMouseLeave={() => setZoom(false)}
      onMouseMove={(e) => {
        setZoom(true);
        setOrigin(pointOrigin(e.clientX, e.clientY, ref.current));
      }}
    >
      {/* eslint-disable-next-line @next/next/no-img-element */}
      <img
        src={src}
        alt={alt}
        className={`h-full w-full select-none will-change-transform ${
          ficha ? "object-contain bg-white p-2" : "object-cover"
        }`}
        style={{
          transform: zoom && !ficha ? "scale(2.2)" : "scale(1)",
          transformOrigin: `${origin.x}% ${origin.y}%`,
          transition: zoom ? "none" : "transform 0.2s ease-out",
        }}
        draggable={false}
      />
    </button>
  );
}

export function ImageSlider({
  slides,
  alt,
  className = "",
  resetKey,
}: Props) {
  const [index, setIndex] = useState(0);
  const [zooming, setZooming] = useState(false);
  const [origin, setOrigin] = useState({ x: 50, y: 50 });
  const [lightbox, setLightbox] = useState(false);
  const [lbSrc, setLbSrc] = useState<string | null>(null);
  const [lbZoom, setLbZoom] = useState(false);
  const [lbOrigin, setLbOrigin] = useState({ x: 50, y: 50 });
  const mainRef = useRef<HTMLDivElement>(null);
  const lbImgRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    setIndex(0);
    setZooming(false);
    setLightbox(false);
    setLbSrc(null);
    setLbZoom(false);
  }, [resetKey, slides]);

  useEffect(() => {
    if (index >= slides.length) setIndex(0);
  }, [slides.length, index]);

  const select = useCallback(
    (i: number) => {
      if (i < 0 || i >= slides.length) return;
      setIndex(i);
      setZooming(false);
    },
    [slides.length]
  );

  const openLightbox = (src?: string) => {
    const slide = slides[index];
    if (slide?.kind === "specs") return;
    setLbSrc(src || slide?.src || null);
    setLbZoom(false);
    setLbOrigin({ x: 50, y: 50 });
    setLightbox(true);
  };

  const closeLightbox = () => {
    setLightbox(false);
    setLbZoom(false);
  };

  const flatLightbox = slides.flatMap((s) => {
    if (s.kind === "specs") return [];
    const imgs = slideImages(s);
    return imgs.map((src, mi) => ({
      src,
      caption:
        imgs.length > 1 ? MOSAIC_CAPTIONS[mi] || s.caption : s.caption,
      fit: isFichaSrc(src) ? ("contain" as const) : s.fit || "cover",
    }));
  });

  const lbIndex = Math.max(
    0,
    flatLightbox.findIndex((f) => f.src === lbSrc)
  );
  const lbItem = flatLightbox[lbIndex] || flatLightbox[0];

  const selectLb = (i: number) => {
    const item = flatLightbox[i];
    if (!item) return;
    setLbSrc(item.src);
    setLbZoom(false);
    setLbOrigin({ x: 50, y: 50 });
    const slideIdx = slides.findIndex((s) => slideImages(s).includes(item.src));
    if (slideIdx >= 0) setIndex(slideIdx);
  };

  useEffect(() => {
    if (!lightbox) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") closeLightbox();
      if (e.key === "ArrowLeft") selectLb(Math.max(0, lbIndex - 1));
      if (e.key === "ArrowRight")
        selectLb(Math.min(flatLightbox.length - 1, lbIndex + 1));
    };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [lightbox, lbIndex, flatLightbox.length]);

  if (!slides.length) return null;

  const slide = slides[index] || slides[0];
  const isSpecs = slide.kind === "specs";
  const fit = slide.fit || "cover";
  const isFicha = slide.caption === "Ficha técnica";
  const caption = slide.caption;
  const mosaic = !isSpecs && slide.mosaic?.length ? slide.mosaic : null;
  const mosaicLayout =
    slide.mosaicLayout ||
    (mosaic && mosaic.length === 3 ? "feature3" : "grid");

  const thumbBtn = (s: GallerySlide, i: number) => {
    const active = i === index;
    if (s.kind === "specs") {
      return (
        <button
          key={`specs-thumb-${i}`}
          type="button"
          onClick={() => select(i)}
          aria-label="Ver especificaciones"
          aria-current={active ? "true" : undefined}
          className={`shrink-0 overflow-hidden border bg-white transition grid place-items-center px-1 ${
            active
              ? "border-ot-ink ring-1 ring-ot-ink"
              : "border-black/10 opacity-75 hover:opacity-100"
          } w-16 h-20 md:w-[4.5rem] md:h-[5.75rem]`}
        >
          <span className="text-[9px] tracking-[0.12em] uppercase text-ot-ink/70 text-center leading-tight">
            Specs
          </span>
        </button>
      );
    }
    const imgs = slideImages(s);
    const layout =
      s.mosaicLayout || (imgs.length === 3 ? "feature3" : "grid");
    return (
      <button
        key={`${s.src}-thumb-${i}`}
        type="button"
        onClick={() => select(i)}
        aria-label={`Ver imagen ${i + 1}${s.caption ? `: ${s.caption}` : ""}`}
        aria-current={active ? "true" : undefined}
        className={`shrink-0 overflow-hidden border bg-[#ebe6dc] transition ${
          active
            ? "border-ot-ink ring-1 ring-ot-ink"
            : "border-black/10 opacity-75 hover:opacity-100"
        } w-16 h-20 md:w-[4.5rem] md:h-[5.75rem]`}
      >
        {imgs.length > 1 ? (
          <div
            className={`grid h-full w-full gap-px bg-[#ebe6dc] ${
              layout === "feature3"
                ? "grid-cols-2 grid-rows-[1.05fr_1fr]"
                : imgs.length === 4
                  ? "grid-cols-2 grid-rows-2"
                  : "grid-cols-3"
            }`}
          >
            {imgs.map((src, mi) => (
              // eslint-disable-next-line @next/next/no-img-element
              <img
                key={src}
                src={src}
                alt=""
                className={`${
                  layout === "feature3" && mi === 0 ? "col-span-2" : ""
                } h-full w-full object-cover ${
                  isFichaSrc(src) ? "object-contain bg-white" : ""
                }`}
              />
            ))}
          </div>
        ) : (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={s.src}
            alt=""
            className={
              (s.fit || "cover") === "contain"
                ? "h-full w-full object-contain bg-ot-cream"
                : "h-full w-full object-cover object-top"
            }
          />
        )}
      </button>
    );
  };

  return (
    <div className={`relative ${className}`}>
      <div className="flex flex-col md:flex-row gap-3 md:gap-4">
        {slides.length > 1 && (
          <div
            className="order-2 md:order-1 flex md:flex-col gap-2 overflow-x-auto md:overflow-y-auto md:overflow-x-visible md:max-h-[min(68vh,620px)] pb-1 md:pb-0 shrink-0 -mx-1 px-1"
            role="listbox"
            aria-label="Galería del producto"
          >
            {slides.map((s, i) => thumbBtn(s, i))}
          </div>
        )}

        <div className="order-1 md:order-2 flex-1 min-w-0">
          <div
            ref={mainRef}
            className={`relative border border-black/5 group ${
              isSpecs
                ? "aspect-[3/4] overflow-hidden bg-ot-cream"
                : mosaic
                  ? mosaicLayout === "feature3"
                    ? "aspect-[4/5] overflow-hidden bg-[#ebe6dc]"
                    : "aspect-square overflow-hidden bg-[#ebe6dc]"
                  : fit === "contain" && isFicha
                    ? "aspect-[4/3] overflow-hidden bg-white"
                    : fit === "contain"
                      ? "h-[min(52vh,480px)] sm:h-[min(68vh,620px)] w-fit max-w-full mx-auto overflow-hidden bg-ot-cream"
                      : "aspect-[3/4] overflow-hidden bg-ot-cream-dark"
            }`}
            onMouseEnter={() =>
              !mosaic && !isSpecs && !(fit === "contain" && isFicha) && setZooming(true)
            }
            onMouseLeave={() => setZooming(false)}
            onMouseMove={
              !mosaic && !isSpecs && !(fit === "contain" && isFicha)
                ? (e) =>
                    setOrigin(pointOrigin(e.clientX, e.clientY, mainRef.current))
                : undefined
            }
            onTouchStart={
              !mosaic && !isSpecs && !(fit === "contain" && isFicha)
                ? (e) => {
                    const t = e.touches[0];
                    if (!t) return;
                    setZooming(true);
                    setOrigin(
                      pointOrigin(t.clientX, t.clientY, mainRef.current)
                    );
                  }
                : undefined
            }
            onTouchMove={
              !mosaic && !isSpecs && !(fit === "contain" && isFicha)
                ? (e) => {
                    const t = e.touches[0];
                    if (!t) return;
                    setZooming(true);
                    setOrigin(
                      pointOrigin(t.clientX, t.clientY, mainRef.current)
                    );
                  }
                : undefined
            }
            onTouchEnd={() => setZooming(false)}
            onTouchCancel={() => setZooming(false)}
          >
            {isSpecs ? (
              <div className="absolute inset-0 overflow-y-auto px-5 py-5 md:px-8 md:py-6">
                <ProductTechSpecs items={slide.specs} />
              </div>
            ) : mosaic ? (
              <div
                className={`absolute inset-0 grid gap-[3px] bg-[#ebe6dc] p-[3px] ${
                  mosaicLayout === "feature3"
                    ? "grid-cols-2 grid-rows-[1.15fr_1fr]"
                    : mosaic.length === 4
                      ? "grid-cols-2 grid-rows-2"
                      : "grid-cols-3"
                }`}
              >
                {mosaic.map((src, mi) => (
                  <MosaicTile
                    key={src}
                    src={src}
                    alt={`${alt} — ${MOSAIC_CAPTIONS[mi] || `detalle ${mi + 1}`}`}
                    label={MOSAIC_CAPTIONS[mi] || `Detalle ${mi + 1}`}
                    className={
                      mosaicLayout === "feature3" && mi === 0
                        ? "col-span-2"
                        : ""
                    }
                    onOpen={() => openLightbox(src)}
                  />
                ))}
              </div>
            ) : (
              <div
                className={
                  fit === "contain"
                    ? isFicha
                      ? "absolute inset-0 grid place-items-center p-4 md:p-6"
                      : "h-full w-fit max-w-full"
                    : "contents"
                }
              >
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src={slide.src}
                  alt={caption ? `${alt} — ${caption}` : alt}
                  className={`select-none will-change-transform cursor-zoom-in block ${
                    fit === "contain"
                      ? isFicha
                        ? "max-h-full max-w-full w-auto h-auto object-contain"
                        : "h-full w-auto max-w-full object-contain"
                      : "h-full w-full object-cover object-top"
                  }`}
                  style={{
                    transform:
                      zooming && !(fit === "contain" && isFicha)
                        ? "scale(2.15)"
                        : "scale(1)",
                    transformOrigin: `${origin.x}% ${origin.y}%`,
                    transition: zooming ? "none" : "transform 0.2s ease-out",
                  }}
                  draggable={false}
                  onClick={() => openLightbox()}
                />
              </div>
            )}

            {slides.length > 1 && !isSpecs && (
              <>
                <button
                  type="button"
                  aria-label="Anterior"
                  onClick={(e) => {
                    e.stopPropagation();
                    select(index === 0 ? slides.length - 1 : index - 1);
                  }}
                  className="absolute left-2 top-1/2 z-10 -translate-y-1/2 w-9 h-9 grid place-items-center bg-ot-cream/95 border border-black/10 hover:bg-white shadow-sm opacity-90 md:opacity-0 md:group-hover:opacity-100 transition"
                >
                  <ChevronLeft size={16} />
                </button>
                <button
                  type="button"
                  aria-label="Siguiente"
                  onClick={(e) => {
                    e.stopPropagation();
                    select(index === slides.length - 1 ? 0 : index + 1);
                  }}
                  className="absolute right-2 top-1/2 z-10 -translate-y-1/2 w-9 h-9 grid place-items-center bg-ot-cream/95 border border-black/10 hover:bg-white shadow-sm opacity-90 md:opacity-0 md:group-hover:opacity-100 transition"
                >
                  <ChevronRight size={16} />
                </button>
              </>
            )}
          </div>

          {caption ? (
            <p className="mt-3 font-serif text-[1.05rem] leading-snug text-ot-ink/90">
              {caption}
            </p>
          ) : null}
        </div>
      </div>

      {lightbox && lbItem && (
        <div
          className="fixed inset-0 z-[80] bg-black/90 flex flex-col"
          role="dialog"
          aria-modal="true"
          aria-label="Vista ampliada"
          onClick={(e) => {
            if (e.target === e.currentTarget) closeLightbox();
          }}
        >
          <div className="flex items-center justify-between gap-3 px-4 py-3 text-white/90 shrink-0">
            <p className="text-xs tracking-[0.16em] uppercase truncate">
              {lbIndex + 1} / {flatLightbox.length}
              {lbItem.caption ? ` · ${lbItem.caption}` : ""}
            </p>
            <button
              type="button"
              onClick={closeLightbox}
              className="w-10 h-10 grid place-items-center hover:bg-white/10"
              aria-label="Cerrar"
            >
              <X size={22} />
            </button>
          </div>

          <div
            className="relative flex-1 min-h-0 flex items-center justify-center px-4 md:px-12"
            onClick={(e) => {
              if (e.target === e.currentTarget) {
                setLbZoom(false);
              }
            }}
          >
            {flatLightbox.length > 1 && (
              <>
                <button
                  type="button"
                  aria-label="Anterior"
                  onClick={() => selectLb(Math.max(0, lbIndex - 1))}
                  className="absolute left-3 md:left-6 top-1/2 z-10 -translate-y-1/2 w-11 h-11 grid place-items-center bg-white/10 hover:bg-white/20 text-white"
                >
                  <ChevronLeft size={22} />
                </button>
                <button
                  type="button"
                  aria-label="Siguiente"
                  onClick={() =>
                    selectLb(Math.min(flatLightbox.length - 1, lbIndex + 1))
                  }
                  className="absolute right-3 md:right-6 top-1/2 z-10 -translate-y-1/2 w-11 h-11 grid place-items-center bg-white/10 hover:bg-white/20 text-white"
                >
                  <ChevronRight size={22} />
                </button>
              </>
            )}

            <div
              ref={lbImgRef}
              className="relative max-h-full max-w-full overflow-hidden cursor-zoom-in"
              onMouseEnter={() => setLbZoom(true)}
              onMouseLeave={() => setLbZoom(false)}
              onMouseMove={(e) => {
                setLbZoom(true);
                setLbOrigin(
                  pointOrigin(e.clientX, e.clientY, lbImgRef.current)
                );
              }}
              onTouchStart={(e) => {
                const t = e.touches[0];
                if (!t) return;
                setLbZoom(true);
                setLbOrigin(
                  pointOrigin(t.clientX, t.clientY, lbImgRef.current)
                );
              }}
              onTouchMove={(e) => {
                const t = e.touches[0];
                if (!t) return;
                setLbZoom(true);
                setLbOrigin(
                  pointOrigin(t.clientX, t.clientY, lbImgRef.current)
                );
              }}
              onTouchEnd={() => setLbZoom(false)}
              onTouchCancel={() => setLbZoom(false)}
            >
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={lbItem.src}
                alt={lbItem.caption ? `${alt} — ${lbItem.caption}` : alt}
                className="block max-h-[min(78vh,900px)] max-w-full w-auto h-auto object-contain select-none will-change-transform"
                style={{
                  transform: lbZoom ? "scale(2.6)" : "scale(1)",
                  transformOrigin: `${lbOrigin.x}% ${lbOrigin.y}%`,
                  transition: lbZoom ? "none" : "transform 0.2s ease-out",
                }}
                draggable={false}
              />
            </div>
          </div>

          {flatLightbox.length > 1 && (
            <div className="flex gap-0 justify-center overflow-x-auto shrink-0 border-t border-white/10">
              {flatLightbox.map((item, i) => (
                <button
                  key={`${item.src}-lb-${i}`}
                  type="button"
                  onClick={() => selectLb(i)}
                  className={`shrink-0 w-[4.5rem] h-20 overflow-hidden border-0 ${
                    i === lbIndex
                      ? "opacity-100 ring-2 ring-inset ring-white"
                      : "opacity-50 hover:opacity-90"
                  }`}
                >
                  {/* eslint-disable-next-line @next/next/no-img-element */}
                  <img
                    src={item.src}
                    alt=""
                    className={
                      item.fit === "contain" || isFichaSrc(item.src)
                        ? "h-full w-full object-contain bg-white"
                        : "h-full w-full object-cover"
                    }
                  />
                </button>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
