import React, { useState, useEffect, useRef } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { FocusContext, useFocusable, setFocus } from '@noriginmedia/norigin-spatial-navigation';
import { useInputMode } from '../context/InputModeContext';

interface Category {
  id: string | number;
  name: string;
}

interface AtelierExplorerProps<C extends Category, I extends { id: string }> {
  categoryName: string; // e.g., "PLATFORM" or "COLLECTION"
  categoryRoute: string; // e.g., "games" or "collections"
  categories: C[];
  items: I[];
  isLoadingCategories: boolean;
  isLoadingItems: boolean;
  
  renderCategory: (category: C, active: boolean, onSelect: () => void) => React.ReactNode;
  renderListItem: (item: I, active: boolean, onFocus: () => void) => React.ReactNode;
  renderDetails: (itemId: string, activeZone: string, setActiveZone: (z: string) => void) => React.ReactNode;
  
  // Modals / Overlays
  overlays?: React.ReactNode;
  
  // Optional alphabet scroller
  alphabet?: React.ReactNode;
  
  // Event overrides
  onBumperCycle?: (direction: 'next' | 'prev') => void;
}

export const AtelierExplorer = <C extends Category, I extends { id: string }>({
  categoryName,
  categoryRoute,
  categories,
  items,
  isLoadingCategories,
  isLoadingItems,
  renderCategory,
  renderListItem,
  renderDetails,
  overlays,
  alphabet,
  onBumperCycle
}: AtelierExplorerProps<C, I>) => {
  const { mode } = useInputMode();
  const { platformId, collectionId, romId } = useParams();
  const navigate = useNavigate();
  
  // Use either platformId or collectionId based on route
  const activeCategoryId = platformId || collectionId;

  const [activeZone, setActiveZone] = useState('games');
  const detailTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Refs for scrolling
  const categoriesRef = useRef<HTMLDivElement>(null);
  const itemsRef = useRef<HTMLDivElement>(null);
  const alphabetRef = useRef<HTMLDivElement>(null);
  const detailsRef = useRef<HTMLDivElement>(null);

  // Spatial Nav Keys
  const { ref: categoriesRefNav, focusKey: categoriesFocusKey } = useFocusable();
  const { ref: itemsRefNav, focusKey: itemsFocusKey } = useFocusable();
  const { ref: alphabetRefNav, focusKey: alphabetFocusKey } = useFocusable();
  const { ref: detailsRefNav, focusKey: detailsFocusKey } = useFocusable();

  // URL -> State Sync (Focus Only)
  useEffect(() => {
    if (mode !== 'mouse') {
      if (romId) {
        setFocus(`ITEM_${romId}`);
      } else if (activeCategoryId) {
        setFocus(`${categoryName}_${activeCategoryId}`);
      }
    }
  }, [activeCategoryId, romId, mode, categoryName]);

  // Initial Auto-select
  useEffect(() => {
    if (categories.length > 0 && !activeCategoryId) {
      navigate(`/${categoryRoute}/${categories[0].id}`, { replace: true });
    }
  }, [categories, activeCategoryId, navigate, categoryRoute]);

  useEffect(() => {
    if (mode !== 'mouse' && items.length > 0 && !romId && activeCategoryId) {
      navigate(`/${categoryRoute}/${activeCategoryId}/${items[0].id}`, { replace: true });
    }
  }, [items, romId, activeCategoryId, mode, navigate, categoryRoute]);

  const handleCategoryFocus = (id: string | number, options: { skipZoneChange?: boolean } = {}) => {
    if (mode !== 'mouse') {
      if (!options.skipZoneChange) setActiveZone('categories');
      if (detailTimeoutRef.current) clearTimeout(detailTimeoutRef.current);
      detailTimeoutRef.current = setTimeout(() => {
        navigate(`/${categoryRoute}/${id}`, { replace: true });
      }, 150);
    } else {
      navigate(`/${categoryRoute}/${id}`);
    }
  };

  const updateFocusFromScroll = (container: HTMLElement) => {
    const rect = container.getBoundingClientRect();
    const centerX = rect.left + rect.width / 2;
    const centerY = rect.top + rect.height / 2;

    const candidates = Array.from(container.querySelectorAll('[data-focusable-key]'));
    if (candidates.length === 0) return;

    let closestKey: string | null = null;
    let minDistance = Infinity;

    candidates.forEach((el) => {
      const elRect = el.getBoundingClientRect();
      const elCenterX = elRect.left + elRect.width / 2;
      const elCenterY = elRect.top + elRect.height / 2;

      const dist = Math.sqrt(Math.pow(centerX - elCenterX, 2) + Math.pow(centerY - elCenterY, 2));
      if (dist < minDistance) {
        minDistance = dist;
        closestKey = el.getAttribute('data-focusable-key');
      }
    });

    if (closestKey && mode !== 'mouse') {
      setFocus(closestKey);
    }
  };

  // Right analog stick scrolling
  const SCROLL_SPEED = 12;
  useEffect(() => {
    const onAnalogScroll = (e: Event) => {
      const { dx, dy } = (e as CustomEvent<{ dx: number; dy: number }>).detail;
      let target: HTMLElement | null = null;
      if (activeZone === 'categories') target = categoriesRef.current;
      else if (activeZone === 'games') target = itemsRef.current;
      else if (activeZone === 'alphabet')  target = alphabetRef.current;
      else if (activeZone === 'details') target = detailsRef.current;
      
      if (target) {
        target.scrollLeft += dx * SCROLL_SPEED;
        target.scrollTop  += dy * SCROLL_SPEED;
        
        if (activeZone !== 'details') {
          updateFocusFromScroll(target);
        }
      }
    };
    window.addEventListener('analogscroll', onAnalogScroll);
    return () => window.removeEventListener('analogscroll', onAnalogScroll);
  }, [activeZone]);

  // Bumper Navigation
  useEffect(() => {
    const onCycle = (direction: 'next' | 'prev') => {
      if (onBumperCycle) {
        onBumperCycle(direction);
      } else {
        if (categories.length <= 1) return;
        const currentIndex = categories.findIndex(c => String(c.id) === String(activeCategoryId));
        if (currentIndex === -1 && activeCategoryId) return;

        let nextIndex = direction === 'next' ? currentIndex + 1 : currentIndex - 1;
        if (nextIndex >= categories.length) nextIndex = 0;
        if (nextIndex < 0) nextIndex = categories.length - 1;
        
        const nextCat = categories[nextIndex];
        handleCategoryFocus(nextCat.id, { skipZoneChange: activeZone !== 'categories' });
        if (activeZone === 'categories') {
          setFocus(`${categoryName}_${nextCat.id}`);
        }
      }
    };

    const handlePrev = () => onCycle('prev');
    const handleNext = () => onCycle('next');
    window.addEventListener('previousplatform', handlePrev);
    window.addEventListener('nextplatform', handleNext);
    return () => {
      window.removeEventListener('previousplatform', handlePrev);
      window.removeEventListener('nextplatform', handleNext);
    };
  }, [categories, activeCategoryId, activeZone, mode, onBumperCycle]);

  if (isLoadingCategories) return <div className="h-full flex items-center justify-center text-white/50 geist-mono uppercase">Initializing Archives...</div>;

  return (
    <div className="h-full flex flex-col bg-[#10131f] overflow-hidden">
      {/* Header / Categories */}
      <div className="px-12 py-4 shrink-0 border-b border-white/5 bg-black/10">
        <FocusContext.Provider value={categoriesFocusKey}>
          <div ref={categoriesRefNav}>
            <div ref={categoriesRef} className={`flex gap-6 overflow-x-auto py-4 scrollbar-hoverable ${activeZone === 'categories' ? 'scrollbar-active' : ''}`}>
              {categories.map(c => renderCategory(c, String(activeCategoryId) === String(c.id), () => handleCategoryFocus(c.id, { skipZoneChange: false })))}
            </div>
          </div>
        </FocusContext.Provider>
      </div>

      {/* Main Split Layout */}
      <div className="flex-1 flex overflow-hidden">
        {/* Left Column: List + Alphabet */}
        <div className="w-[31.25rem] border-r border-white/5 flex overflow-hidden bg-black/20">
          <div className="flex-1 flex flex-col overflow-hidden">
            <FocusContext.Provider value={itemsFocusKey}>
              <div ref={itemsRefNav} className="flex-1 overflow-hidden">
                <div ref={itemsRef} className={`h-full overflow-y-auto scrollbar-hoverable ${activeZone === 'games' ? 'scrollbar-active' : ''}`}>
                  {isLoadingItems ? (
                    <div className="p-12 text-center text-white/20 geist-mono text-[0.625rem] uppercase tracking-widest">Retrieving index...</div>
                  ) : (
                    items.map(item => renderListItem(item, romId === item.id, () => {
                      if (mode !== 'mouse') {
                        setActiveZone('games');
                        if (detailTimeoutRef.current) clearTimeout(detailTimeoutRef.current);
                        detailTimeoutRef.current = setTimeout(() => {
                          navigate(`/${categoryRoute}/${activeCategoryId}/${item.id}`, { replace: true });
                        }, 150);
                      } else {
                        navigate(`/${categoryRoute}/${activeCategoryId}/${item.id}`);
                      }
                    }))
                  )}
                </div>
              </div>
            </FocusContext.Provider>
          </div>
          
          {alphabet && (
            <FocusContext.Provider value={alphabetFocusKey}>
              <div ref={alphabetRefNav}>
                <div ref={alphabetRef} className="h-full flex">
                  {alphabet}
                </div>
              </div>
            </FocusContext.Provider>
          )}
        </div>

        {/* Right Column: Details */}
        <FocusContext.Provider value={detailsFocusKey}>
          <div ref={detailsRefNav} className="flex-1 overflow-hidden">
            <div ref={detailsRef} className={`h-full overflow-y-auto relative scrollbar-hoverable ${activeZone === 'details' ? 'scrollbar-active' : ''}`}>
              {romId ? renderDetails(romId, activeZone, setActiveZone) : (
                <div className="h-full flex items-center justify-center p-20 text-center opacity-20">
                  <div>
                    <span className="material-symbols-outlined text-6xl mb-6">videogame_asset</span>
                    <p className="geist-mono uppercase tracking-[0.3em] font-black text-sm">Target selection required</p>
                  </div>
                </div>
              )}
            </div>
          </div>
        </FocusContext.Provider>
      </div>
      
      {overlays}
    </div>
  );
};
