"use client";

import { useRef, useEffect, useState, useCallback } from "react";
import { UI_CONFIG } from "@/lib/config";

interface ShowcaseLayoutProps<T> {
  items: T[];
  activeIndex: number;
  onSelect: (index: number) => void;
  onHoverChange?: (hovering: boolean) => void;
  renderDetail: (item: T, index: number) => React.ReactNode;
  renderSelectorItem: (item: T, index: number, isActive: boolean) => React.ReactNode;
  counter?: boolean;
}

export function ShowcaseLayout<T>({
  items,
  activeIndex,
  onSelect,
  onHoverChange,
  renderDetail,
  renderSelectorItem,
  counter = false,
}: ShowcaseLayoutProps<T>) {
  const selectorRef = useRef<HTMLDivElement>(null);
  const activeItemRef = useRef<HTMLButtonElement>(null);
  const detailRef = useRef<HTMLDivElement>(null);
  const detailWrapRef = useRef<HTMLDivElement>(null);
  const [minHeight, setMinHeight] = useState<number | undefined>(undefined);
  const measuredHeights = useRef<number[]>([]);
  const [isUserInteracting, setIsUserInteracting] = useState(false);
  const [displayIndex, setDisplayIndex] = useState(activeIndex);
  const [fading, setFading] = useState(false);

  // Track max height across all seen items to prevent shrinking
  useEffect(() => {
    if (!detailRef.current || fading) return;
    const h = detailRef.current.offsetHeight;
    measuredHeights.current[displayIndex] = h;
    const maxH = Math.max(...measuredHeights.current.filter(Boolean));
    if (maxH > (minHeight ?? 0)) {
      setMinHeight(maxH);
    }
  }, [displayIndex, fading]);

  useEffect(() => {
    if (activeIndex === displayIndex) return;
    setFading(true);
    const timeout = setTimeout(() => {
      setDisplayIndex(activeIndex);
      setFading(false);
    }, UI_CONFIG.showcase.fadeMs);
    return () => clearTimeout(timeout);
  }, [activeIndex, displayIndex]);

  // Auto-scroll selector only when item is out of view
  useEffect(() => {
    if (isUserInteracting) return;

    const container = selectorRef.current;
    const activeEl = activeItemRef.current;
    if (!container || !activeEl) return;

    const isHorizontal = window.innerWidth < 1024;

    if (isHorizontal) {
      const elLeft = activeEl.offsetLeft;
      const elRight = elLeft + activeEl.offsetWidth;
      const scrollLeft = container.scrollLeft;
      const viewRight = scrollLeft + container.offsetWidth;

      if (elLeft < scrollLeft || elRight > viewRight) {
        const left = elLeft - container.offsetWidth / 2 + activeEl.offsetWidth / 2;
        container.scrollTo({ left, behavior: "smooth" });
      }
    } else {
      const elTop = activeEl.offsetTop;
      const elBottom = elTop + activeEl.offsetHeight;
      const scrollTop = container.scrollTop;
      const viewBottom = scrollTop + container.offsetHeight;

      if (elTop < scrollTop || elBottom > viewBottom) {
        const top = elTop - container.offsetHeight / 2 + activeEl.offsetHeight / 2;
        container.scrollTo({ top, behavior: "smooth" });
      }
    }
  }, [activeIndex, isUserInteracting]);

  // Swipe support on detail area
  const touchStart = useRef<{ x: number; y: number } | null>(null);

  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    touchStart.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
  }, []);

  const handleTouchEnd = useCallback(
    (e: React.TouchEvent) => {
      if (!touchStart.current) return;
      const dx = e.changedTouches[0].clientX - touchStart.current.x;
      const dy = e.changedTouches[0].clientY - touchStart.current.y;
      touchStart.current = null;

      if (Math.abs(dx) > UI_CONFIG.showcase.swipeThreshold && Math.abs(dx) > Math.abs(dy) * 1.5) {
        if (dx < 0 && activeIndex < items.length - 1) {
          onSelect(activeIndex + 1);
        } else if (dx > 0 && activeIndex > 0) {
          onSelect(activeIndex - 1);
        }
      }
    },
    [activeIndex, items.length, onSelect],
  );

  function handleMouseEnter() {
    setIsUserInteracting(true);
    onHoverChange?.(true);
  }

  function handleMouseLeave() {
    setIsUserInteracting(false);
    onHoverChange?.(false);
  }

  return (
    <div
      className="flex flex-col-reverse gap-6 lg:flex-row lg:gap-8"
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      {/* Detail area */}
      <div className="lg:w-[60%]">
        <div
          ref={detailWrapRef}
          style={minHeight != null ? { minHeight } : undefined}
        >
          <div
            ref={detailRef}
            className={`transition-all duration-300 ease-out ${
              fading
                ? "opacity-0 translate-y-2"
                : "opacity-100 translate-y-0"
            }`}
            onTouchStart={handleTouchStart}
            onTouchEnd={handleTouchEnd}
          >
            {renderDetail(items[displayIndex], displayIndex)}
          </div>
        </div>

        {/* Counter */}
        {counter && (
          <div className="mt-3 flex items-center justify-center gap-2 lg:justify-start">
            <span className="text-xs font-medium tabular-nums text-gold">
              {String(activeIndex + 1).padStart(2, "0")}
            </span>
            <span className="h-[1px] w-8 bg-white/10" />
            <span className="text-xs tabular-nums text-neutral-500">
              {String(items.length).padStart(2, "0")}
            </span>
          </div>
        )}
      </div>

      {/* Selector */}
      <div className="lg:w-[40%]">
        <div
          ref={selectorRef}
          className="grid grid-cols-2 gap-2 lg:grid-cols-1 lg:gap-3 lg:max-h-[600px] lg:overflow-y-auto lg:pr-1 styled-scrollbar"
        >
          {items.map((item, i) => (
            <button
              key={i}
              ref={i === activeIndex ? activeItemRef : null}
              onClick={() => onSelect(i)}
              className={`cursor-pointer rounded-xl border-2 text-left transition-all duration-300 ${
                i === activeIndex
                  ? "border-gold/60 bg-gold/10 dark:bg-gold/5"
                  : "border-transparent bg-neutral-100 hover:bg-neutral-200 dark:bg-white/[0.03] dark:hover:bg-white/[0.06]"
              }`}
            >
              {renderSelectorItem(item, i, i === activeIndex)}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}
