"use client";

import React, { useEffect, useMemo, useState } from "react";

function hasIdentifier(
  value: unknown
): value is {
  id: string | number;
} {
  if (typeof value !== "object" || value === null || !("id" in value)) {
    return false;
  }

  const candidate = (value as { id: unknown }).id;
  return typeof candidate === "string" || typeof candidate === "number";
}

interface SimpleCarouselProps<T> {
  items: T[];
  renderItem: (item: T, index: number, isActive: boolean) => React.ReactNode;
  keyExtractor?: (item: T, index: number) => string | number;
  className?: string;
  autoPlay?: boolean;
  interval?: number;
  showControls?: boolean;
  showIndicators?: boolean;
  // 是否已准备好开始自动播放（等待资源加载完成）
  isReady?: boolean;
}

export function SimpleCarousel<T>({
  items,
  renderItem,
  keyExtractor,
  className = "",
  autoPlay = true,
  interval = 5000,
  showControls = true,
  showIndicators = true,
  isReady = true,
}: SimpleCarouselProps<T>) {
  const slides = useMemo(() => items.filter(Boolean), [items]);
  const [activeIndex, setActiveIndex] = useState(0);

  useEffect(() => {
    // 只有当 isReady 为 true 时才开始自动播放
    if (!autoPlay || slides.length <= 1 || !isReady) return;
    const timer = window.setInterval(() => {
      setActiveIndex((prev) => (prev + 1) % slides.length);
    }, interval);
    return () => window.clearInterval(timer);
  }, [autoPlay, interval, slides.length, isReady]);

  useEffect(() => {
    if (activeIndex >= slides.length) {
      setActiveIndex(Math.max(slides.length - 1, 0));
    }
  }, [activeIndex, slides.length]);

  if (slides.length === 0) {
    return null;
  }

  const goTo = (index: number) => {
    setActiveIndex((prev) => {
      if (index < 0) {
        return slides.length - 1;
      }
      if (index >= slides.length) {
        return 0;
      }
      return index;
    });
  };

  return (
    <div className={`relative overflow-hidden ${className}`}>
      <div className="relative h-full w-full">
        {slides.map((item, index) => {
          const key =
            keyExtractor?.(item, index) ??
            (hasIdentifier(item) ? item.id : index);

          return (
            <div
              key={key}
              className={`absolute inset-0 transition-opacity duration-700 ease-in-out ${
                index === activeIndex
                  ? "opacity-100"
                  : "pointer-events-none opacity-0"
              }`}
              aria-hidden={index !== activeIndex}
            >
              {renderItem(item, index, index === activeIndex)}
            </div>
          );
        })}
      </div>

      {showControls && slides.length > 1 && (
        <>
          <button
            type="button"
            onClick={() => goTo(activeIndex - 1)}
            className="absolute left-4 top-1/2 z-10 flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 text-[#0f1f39] shadow-lg transition hover:bg-white"
            aria-label="Previous slide"
          >
            <span className="text-lg font-semibold">‹</span>
          </button>
          <button
            type="button"
            onClick={() => goTo(activeIndex + 1)}
            className="absolute right-4 top-1/2 z-10 flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 text-[#0f1f39] shadow-lg transition hover:bg-white"
            aria-label="Next slide"
          >
            <span className="text-lg font-semibold">›</span>
          </button>
        </>
      )}

      {showIndicators && slides.length > 1 && (
        <div className="absolute bottom-5 left-1/2 z-10 flex -translate-x-1/2 items-center gap-2">
          {slides.map((_, index) => (
            <button
              key={index}
              type="button"
              onClick={() => goTo(index)}
              className={`h-2.5 w-2.5 rounded-full transition ${
                index === activeIndex
                  ? "bg-[#118af4]"
                  : "bg-white/70 hover:bg-white"
              }`}
              aria-label={`Go to slide ${index + 1}`}
            />
          ))}
        </div>
      )}
    </div>
  );
}


