"use client";

import Image from "next/image";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { CSSProperties } from "react";

import type { SliderPhoto } from "@/lib/slider-photos";

const ROTATE_MS = 5500;

function PromoStripSingleSlide({
  photos,
  activeIndex,
}: {
  photos: SliderPhoto[];
  activeIndex: number;
}) {
  const [ratioBySrc, setRatioBySrc] = useState<Record<string, number>>({});
  const lastKnownRatioRef = useRef(16 / 9);

  const active = photos[activeIndex];
  const activeRatio = active ? ratioBySrc[active.src] : undefined;

  const displayRatio =
    activeRatio != null && activeRatio > 0 ? activeRatio : photos.length > 0 ? lastKnownRatioRef.current : undefined;

  useEffect(() => {
    if (activeRatio != null && activeRatio > 0) {
      lastKnownRatioRef.current = activeRatio;
    }
  }, [activeRatio]);

  const containerStyle = useMemo((): CSSProperties => {
    if (photos.length === 0) {
      return { minHeight: "10rem" };
    }
    if (displayRatio != null) {
      return { aspectRatio: displayRatio };
    }
    return { minHeight: "10rem" };
  }, [photos.length, displayRatio]);

  const handleImageLoad = useCallback((src: string, naturalWidth: number, naturalHeight: number) => {
    if (naturalHeight <= 0) return;
    setRatioBySrc((prev) => {
      const next = naturalWidth / naturalHeight;
      if (prev[src] === next) return prev;
      return { ...prev, [src]: next };
    });
  }, []);

  const n = photos.length;

  return (
    <div
      className="relative w-full bg-neutral-100 dark:bg-neutral-900"
      style={containerStyle}
    >
      {n > 0 ? (
        photos.map((photo, i) => (
          <Image
            key={photo.src}
            src={photo.src}
            alt={photo.alt}
            fill
            priority={i === 0}
            className={`object-cover object-center transition-opacity duration-[900ms] ease-in-out ${
              i === activeIndex ? "z-[1] opacity-100" : "pointer-events-none z-0 opacity-0"
            }`}
            sizes="100vw"
            aria-hidden={i !== activeIndex}
            onLoad={(e) => handleImageLoad(photo.src, e.currentTarget.naturalWidth, e.currentTarget.naturalHeight)}
          />
        ))
      ) : (
        <div className="absolute inset-0 bg-neutral-200 dark:bg-neutral-800" aria-hidden />
      )}
    </div>
  );
}

function useSliderPhotos(): { photos: SliderPhoto[]; loading: boolean } {
  const [photos, setPhotos] = useState<SliderPhoto[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    fetch("/api/slider-photos", { cache: "no-store" })
      .then((r) => (r.ok ? r.json() : []))
      .then((data: unknown) => {
        if (cancelled) return;
        if (Array.isArray(data)) {
          setPhotos(
            data.filter(
              (x): x is SliderPhoto =>
                typeof x === "object" &&
                x !== null &&
                "src" in x &&
                typeof (x as SliderPhoto).src === "string" &&
                "alt" in x &&
                typeof (x as SliderPhoto).alt === "string",
            ),
          );
        } else {
          setPhotos([]);
        }
      })
      .catch(() => {
        if (!cancelled) setPhotos([]);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  return { photos, loading };
}

/** Slider: one image at a time; container height follows each image aspect ratio (no fixed empty band). */
export function TvonePromoStrip() {
  const { photos, loading } = useSliderPhotos();
  const [index, setIndex] = useState(0);
  const [reduceMotion, setReduceMotion] = useState(false);

  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const sync = () => setReduceMotion(mq.matches);
    sync();
    mq.addEventListener("change", sync);
    return () => mq.removeEventListener("change", sync);
  }, []);

  const advance = useCallback(() => {
    if (photos.length <= 1) return;
    setIndex((i) => (i + 1) % photos.length);
  }, [photos.length]);

  useEffect(() => {
    if (photos.length <= 1 || reduceMotion) return;
    const id = window.setInterval(advance, ROTATE_MS);
    return () => window.clearInterval(id);
  }, [photos.length, reduceMotion, advance]);

  useEffect(() => {
    setIndex((prev) => (photos.length === 0 ? 0 : Math.min(prev, photos.length - 1)));
  }, [photos.length]);

  const current = photos.length > 0 ? photos[index] : null;
  const regionLabel = loading ? "A carregar galeria" : current?.alt ?? "Galeria";

  return (
    <div
      className="relative w-full overflow-hidden  bg-neutral-100  dark:bg-neutral-900"
      role="region"
      aria-roledescription="carrossel"
      aria-label={regionLabel}
    >
      <span className="sr-only" aria-live="polite">
        {current ? current.alt : loading ? "A carregar" : "Sem imagens"}
      </span>

      <div className="relative w-full">
        <PromoStripSingleSlide photos={photos} activeIndex={index} />
      </div>
    </div>
  );
}
