import type { FunctionalComponent } from 'preact';
import { useEffect, useMemo, useRef } from 'preact/hooks';
import { ScrollArea } from './ScrollArea';
import { Tooltip } from './Tooltip';
import { getI18n } from '../../core/i18n';

export interface CarouselItem {
  id: string;
  label: string;
  thumbnailDataUrl?: string | null;
}

export type CarouselPaginationMode = 'thumbnails' | 'dots' | 'numbers';

export interface CarouselProps {
  items: CarouselItem[];
  activeId: string | null;
  onSelect: (id: string) => void;
  label?: string;
  /**
   * Thumbnails: preview images + optional labels
   * Dots: compact dots
   * Numbers: compact numbered pills
   */
  paginationMode?: CarouselPaginationMode;
  /**
   * In thumbnails mode, show the item labels below the preview.
   * Default: true.
   */
  showLabels?: boolean;
  /**
   * Allow grab/drag on the pagination bar to switch items.
   * Default: false.
   */
  enableGrabNavigation?: boolean;
}

/**
 * Carousel (generic)
 * ------------------
 * This component is intentionally "light": it only renders a pagination bar.
 * It's used for Views, but can be reused for any list of items.
 */
export const Carousel: FunctionalComponent<CarouselProps> = ({
  items,
  activeId,
  onSelect,
  label,
  paginationMode = 'thumbnails',
  showLabels = false,
  enableGrabNavigation = false,
}) => {
  const t = getI18n().t;
  const activeIndex = useMemo(() => items.findIndex((i) => i.id === activeId), [items, activeId]);

  // --- Grab navigation (drag left/right to change selection) ---
  const grabRef = useRef<HTMLDivElement | null>(null);
  const pointerRef = useRef<{
    active: boolean;
    startX: number;
    startY: number;
    baseIndex: number;
    consumed: boolean;
  }>({ active: false, startX: 0, startY: 0, baseIndex: -1, consumed: false });

  useEffect(() => {
    if (!enableGrabNavigation) return;

    const el = grabRef.current;
    if (!el) return;

    const onPointerDown = (e: PointerEvent) => {
      if (e.button !== 0 && e.pointerType === 'mouse') return;
      if (items.length <= 1) return;

      pointerRef.current = {
        active: true,
        startX: e.clientX,
        startY: e.clientY,
        baseIndex: activeIndex >= 0 ? activeIndex : 0,
        consumed: false,
      };
      try {
        (e.target as HTMLElement | null)?.setPointerCapture?.(e.pointerId);
      } catch {
        // ignore
      }
    };

    const onPointerMove = (e: PointerEvent) => {
      const st = pointerRef.current;
      if (!st.active) return;

      const dx = e.clientX - st.startX;
      const dy = e.clientY - st.startY;

      if (!st.consumed && Math.abs(dy) > Math.abs(dx) && Math.abs(dy) > 10) {
        st.consumed = true;
        return;
      }

      const threshold = 45;
      if (Math.abs(dx) < threshold) return;

      const direction = dx > 0 ? -1 : 1;
      const nextIndex = Math.max(0, Math.min(items.length - 1, st.baseIndex + direction));
      const next = items[nextIndex];
      if (next && next.id !== activeId) {
        st.baseIndex = nextIndex;
        st.startX = e.clientX;
        onSelect(next.id);
      }
    };

    const onPointerUp = () => {
      pointerRef.current.active = false;
    };

    el.addEventListener('pointerdown', onPointerDown, { passive: true });
    el.addEventListener('pointermove', onPointerMove, { passive: true });
    el.addEventListener('pointerup', onPointerUp, { passive: true });
    el.addEventListener('pointercancel', onPointerUp, { passive: true });

    return () => {
      el.removeEventListener('pointerdown', onPointerDown);
      el.removeEventListener('pointermove', onPointerMove);
      el.removeEventListener('pointerup', onPointerUp);
      el.removeEventListener('pointercancel', onPointerUp);
    };
  }, [enableGrabNavigation, items, activeId, activeIndex, onSelect]);

  const renderThumbnails = () => (
    <ScrollArea
      axis="horizontal"
      viewportClassName="ask-px-3 ask-py-2"
      contentClassName="ask-inline-flex ask-items-start ask-gap-3 ask-min-w-max"
    >
      {items.map((item, idx) => {
        const isActive = item.id === activeId;
        const tooltipContent = (
          <div class="ask-flex ask-flex-col ask-gap-0.5">
            <span class="ask-font-medium">{item.label}</span>
            <span class="ask-text-[11px] ask-text-textMuted">{t('carousel.page', 'Page {page}', { page: idx + 1 })}</span>
          </div>
        );

        return (
          <Tooltip key={item.id} content={tooltipContent} direction="top">
            <button
              type="button"
              onClick={() => onSelect(item.id)}
              aria-label={item.label}
              class={`ask-theme-carousel-page ${isActive ? 'is-active' : ''}`}
            >
              <div class="ask-theme-carousel-page__preview">
                {item.thumbnailDataUrl ? (
                  <img src={item.thumbnailDataUrl} alt={item.label} class="ask-w-full ask-h-full ask-object-cover" />
                ) : (
                  <div class="ask-w-full ask-h-full ask-flex ask-items-center ask-justify-center ask-text-[10px] ask-text-textMuted">
                    {t('common.noPreview', 'No preview')}
                  </div>
                )}
                <span class="ask-theme-carousel-page__badge">{idx + 1}</span>
              </div>
              {showLabels ? <span class="ask-theme-carousel-page__label">{item.label}</span> : null}
            </button>
          </Tooltip>
        );
      })}
    </ScrollArea>
  );

  const renderDots = () => (
    <ScrollArea
      axis="horizontal"
      viewportClassName="ask-px-3 ask-py-1"
      contentClassName="ask-inline-flex ask-items-center ask-gap-1.5 ask-min-w-max"
    >
      {items.map((item) => {
        const isActive = item.id === activeId;
        return (
          <button
            key={item.id}
            type="button"
            onClick={() => onSelect(item.id)}
            aria-label={item.label}
            class={`ask-w-2.5 ask-h-2.5 ask-rounded-full ask-border ask-transition-colors ${
              isActive ? 'ask-bg-primary ask-border-primary' : 'ask-bg-surface ask-border-borderSubtle hover:ask-bg-surfaceAlt'
            }`}
          />
        );
      })}
    </ScrollArea>
  );

  const renderNumbers = () => (
    <ScrollArea
      axis="horizontal"
      viewportClassName="ask-px-3 ask-py-1"
      contentClassName="ask-inline-flex ask-items-center ask-gap-1 ask-min-w-max"
    >
      {items.map((item, idx) => {
        const isActive = item.id === activeId;
        return (
          <Tooltip key={item.id} content={item.label} direction="top">
            <button
              type="button"
              onClick={() => onSelect(item.id)}
              class={`ask-text-[11px] ask-leading-none ask-px-2 ask-py-1 ask-rounded-lg ask-border ask-transition-colors ${
                isActive ? 'ask-bg-primarySoft ask-border-primary ask-text-primary' : 'ask-bg-surface ask-border-borderSubtle hover:ask-bg-surfaceAlt'
              }`}
              aria-label={item.label}
            >
              {idx + 1}
            </button>
          </Tooltip>
        );
      })}
    </ScrollArea>
  );

  const renderPagination = () => {
    if (paginationMode === 'dots') return renderDots();
    if (paginationMode === 'numbers') return renderNumbers();
    return renderThumbnails();
  };

  return (
    <div class="ask-theme-carousel ask-flex ask-items-center ask-justify-between ask-gap-3 ask-w-full ask-px-2">
      <div class="ask-flex ask-items-center ask-gap-2 ask-min-w-0 ask-flex-1">
        {label && <span class="ask-theme-carousel__label">{label}</span>}
        <div
          ref={grabRef}
          class={enableGrabNavigation ? 'ask-theme-carousel__track ask-cursor-grab active:ask-cursor-grabbing' : 'ask-theme-carousel__track'}
        >
          {renderPagination()}
        </div>
      </div>

      <div class="ask-theme-carousel__counter ask-shrink-0">
        <span>
          {activeIndex >= 0 ? activeIndex + 1 : 0} / {items.length}
        </span>
      </div>
    </div>
  );
};

export default Carousel;
