/**
 * IconPickerModal — Professional icon picker for Jalpi Page Builder.
 * Supports 5+ libraries: Builtin SVGs, Font Awesome, Bootstrap Icons, Material Symbols, Tabler Icons.
 */

import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { IconValue } from '../../types';
import { iconRegistry, PickerIcon, LIBRARIES } from '../../utils/iconRegistry';

// ── Icon Renderer (single icon tile) ─────────────────────────────────────────

function IconTile({ icon, isActive, isFav, onClick, onFav }: {
  icon: PickerIcon;
  isActive: boolean;
  isFav: boolean;
  onClick: () => void;
  onFav: (e: React.MouseEvent) => void;
}) {
  return (
    <button
      type="button"
      title={icon.label}
      className={`jalpi-ip__tile${isActive ? ' is-active' : ''}`}
      onClick={onClick}
    >
      <span className="jalpi-ip__tile-icon" aria-hidden="true">
        <IconDisplay icon={icon} />
      </span>
      {isFav && <span className="jalpi-ip__tile-fav" onClick={onFav} title="Remove from favorites">★</span>}
      {!isFav && <span className="jalpi-ip__tile-fav jalpi-ip__tile-fav--add" onClick={onFav} title="Add to favorites">☆</span>}
      <span className="jalpi-ip__tile-label">{icon.label}</span>
    </button>
  );
}

export function IconDisplay({ icon, style }: { icon: PickerIcon; style?: React.CSSProperties }) {
  if (icon.type === 'svg' && icon.svg) {
    return <span style={style} dangerouslySetInnerHTML={{ __html: icon.svg }} />;
  }
  if (icon.type === 'font') {
    if (icon.lib === 'material') {
      return <span className={icon.cls} style={style}>{icon.name}</span>;
    }
    return <i className={icon.cls} style={style} />;
  }
  return null;
}

// ── Render stored IconValue in the canvas / trigger ──────────────────────────

export function RenderIconValue({ value, style }: { value?: string | IconValue; style?: React.CSSProperties }) {
  if (!value) return null;
  if (typeof value === 'string') {
    // Legacy string key
    const found = iconRegistry.getAll('builtin').find((i) => i.name === value);
    if (found) return <IconDisplay icon={found} style={style} />;
    return null;
  }
  if (value.type === 'svg') {
    // Prefer the SVG cached at pick time; but a seeded default (e.g.
    // { type:'svg', lib:'builtin', name:'star' }) may have no cached svg —
    // resolve it from the built-in registry by name so it still renders.
    if (value.svg) {
      return <span style={style} dangerouslySetInnerHTML={{ __html: value.svg }} />;
    }
    const found = iconRegistry.getAll('builtin').find((i) => i.name === value.name);
    if (found?.svg) {
      return <span style={style} dangerouslySetInnerHTML={{ __html: found.svg }} />;
    }
    return null;
  }
  if (value.type === 'font' && value.lib === 'material') {
    return <span className={value.cls || 'material-symbols-outlined'} style={style}>{value.name}</span>;
  }
  if (value.type === 'font' && value.cls) {
    return <i className={value.cls} style={style} />;
  }
  if (value.type === 'img' && value.url) {
    return <img src={value.url} alt={value.alt || ''} style={style} />;
  }
  return null;
}

// ── Main Picker Modal ─────────────────────────────────────────────────────────

const PAGE_SIZE = 60;

interface Props {
  value?: string | IconValue;
  onChange: (v: IconValue) => void;
  onClear?: () => void;
  onClose: () => void;
}

export function IconPickerModal({ value, onChange, onClear, onClose }: Props) {
  const [activeLib,  setActiveLib]  = useState<string>('builtin');
  const [activecat,  setActiveCat]  = useState<string>('');
  const [query,      setQuery]      = useState('');
  const [page,       setPage]       = useState(1);
  const [cssLoading, setCssLoading] = useState(false);
  const [cssReady,   setCssReady]   = useState(false);
  const [favs,       setFavs]       = useState<string[]>([]);
  const [recent,     setRecent]     = useState<PickerIcon[]>([]);
  const [tab,        setTab]        = useState<'all' | 'recent' | 'favorites'>('all');

  const searchRef = useRef<HTMLInputElement>(null);
  const gridRef   = useRef<HTMLDivElement>(null);

  // Active icon value for highlighting
  const activeVal: IconValue | null = useMemo(() => {
    if (!value) return null;
    if (typeof value === 'object') return value;
    const found = iconRegistry.getAll('builtin').find((i) => i.name === value);
    return found ? iconRegistry.toIconValue(found) : null;
  }, [value]);

  const isActive = (icon: PickerIcon) =>
    activeVal?.lib === icon.lib && activeVal?.name === icon.name;

  // Load recent + favs on mount
  useEffect(() => {
    setRecent(iconRegistry.getRecent());
    refreshFavs();
  }, []);

  const refreshFavs = () => {
    const f = iconRegistry.getFavorites().map((i) => `${i.lib}:${i.name}`);
    setFavs(f);
  };

  const isFav = (icon: PickerIcon) => favs.includes(`${icon.lib}:${icon.name}`);

  const handleFav = (e: React.MouseEvent, icon: PickerIcon) => {
    e.stopPropagation();
    iconRegistry.toggleFavorite(icon);
    refreshFavs();
  };

  // Load CDN CSS when switching libraries
  useEffect(() => {
    if (activeLib === 'builtin') { setCssReady(true); return; }
    if (iconRegistry.isCssLoaded(activeLib)) { setCssReady(true); return; }
    setCssLoading(true);
    setCssReady(false);
    iconRegistry.loadLibraryCss(activeLib).then((ok) => {
      setCssLoading(false);
      setCssReady(ok);
    });
  }, [activeLib]);

  // Reset page + category on lib/query change
  useEffect(() => {
    setPage(1);
    setActiveCat('');
    if (gridRef.current) gridRef.current.scrollTop = 0;
  }, [activeLib, query, tab]);

  useEffect(() => {
    setPage(1);
    if (gridRef.current) gridRef.current.scrollTop = 0;
  }, [activecat]);

  // Focus search on open
  useEffect(() => {
    setTimeout(() => searchRef.current?.focus(), 80);
  }, []);

  // Keyboard: Esc closes
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onClose]);

  const handleLibClick = (libId: string) => {
    setActiveLib(libId);
    setQuery('');
    setTab('all');
  };

  const handleSelect = (icon: PickerIcon) => {
    const v = iconRegistry.toIconValue(icon);
    onChange(v);
    iconRegistry.addRecent(icon);
    setRecent(iconRegistry.getRecent());
    onClose();
  };

  // Get icons for current view
  const currentIcons: PickerIcon[] = useMemo(() => {
    if (tab === 'recent')    return iconRegistry.getRecent();
    if (tab === 'favorites') return iconRegistry.getFavorites();
    if (query.trim())        return iconRegistry.search(query, activeLib);
    return iconRegistry.getAll(activeLib, activecat || undefined);
  }, [tab, query, activeLib, activecat, favs, recent]);

  const totalPages = Math.ceil(currentIcons.length / PAGE_SIZE);
  const pageIcons  = currentIcons.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

  const categories = useMemo(() =>
    iconRegistry.getCategories(activeLib),
    [activeLib]
  );

  const libDef = LIBRARIES.find((l) => l.id === activeLib);

  // Close on outside click
  const overlayRef = useRef<HTMLDivElement>(null);
  const handleOverlayClick = (e: React.MouseEvent) => {
    if (e.target === overlayRef.current) onClose();
  };

  return (
    <div className="jalpi-ip__overlay" ref={overlayRef} onClick={handleOverlayClick}>
      <div className="jalpi-ip__modal" role="dialog" aria-label="Icon Picker">

        {/* Header */}
        <div className="jalpi-ip__header">
          <span className="jalpi-ip__title">Icon Picker</span>
          <div className="jalpi-ip__header-tabs">
            <button type="button" className={`jalpi-ip__htab${tab === 'all' ? ' is-active' : ''}`} onClick={() => setTab('all')}>All</button>
            <button type="button" className={`jalpi-ip__htab${tab === 'recent' ? ' is-active' : ''}`} onClick={() => setTab('recent')}>Recent</button>
            <button type="button" className={`jalpi-ip__htab${tab === 'favorites' ? ' is-active' : ''}`} onClick={() => setTab('favorites')}>★ Favs</button>
          </div>
          {onClear && (
            <button type="button" className="jalpi-ip__clear" onClick={() => { onClear(); onClose(); }} title="Remove icon">✕ None</button>
          )}
          <button type="button" className="jalpi-ip__close" onClick={onClose} aria-label="Close">✕</button>
        </div>

        {/* Search */}
        <div className="jalpi-ip__search-bar">
          <svg className="jalpi-ip__search-ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
          <input
            ref={searchRef}
            type="text"
            className="jalpi-ip__search"
            placeholder={`Search${libDef ? ` in ${libDef.label}` : ''}…`}
            value={query}
            onChange={(e) => { setQuery(e.target.value); setTab('all'); }}
          />
          {query && (
            <button type="button" className="jalpi-ip__search-clr" onClick={() => setQuery('')}>✕</button>
          )}
        </div>

        <div className="jalpi-ip__body">
          {/* Library sidebar */}
          <div className="jalpi-ip__libs">
            {LIBRARIES.map((lib) => (
              <button
                key={lib.id}
                type="button"
                className={`jalpi-ip__lib${activeLib === lib.id ? ' is-active' : ''}`}
                onClick={() => handleLibClick(lib.id)}
                title={lib.label}
              >
                <span className="jalpi-ip__lib-name">{lib.label}</span>
                <span className="jalpi-ip__lib-count">{lib.count.toLocaleString()}</span>
              </button>
            ))}
          </div>

          {/* Category + grid */}
          <div className="jalpi-ip__main">
            {tab === 'all' && !query && categories.length > 1 && (
              <div className="jalpi-ip__cats">
                <button type="button" className={`jalpi-ip__cat${!activecat ? ' is-active' : ''}`} onClick={() => setActiveCat('')}>All</button>
                {categories.map((cat) => (
                  <button key={cat} type="button" className={`jalpi-ip__cat${activecat === cat ? ' is-active' : ''}`} onClick={() => setActiveCat(cat)}>{cat}</button>
                ))}
              </div>
            )}

            {/* Grid */}
            <div className="jalpi-ip__grid-wrap" ref={gridRef}>
              {cssLoading && (
                <div className="jalpi-ip__loading">
                  <span className="jalpi-ip__spinner" />
                  Loading {libDef?.label}…
                </div>
              )}
              {!cssLoading && (tab === 'all' || tab === 'recent' || tab === 'favorites') && (
                <>
                  {pageIcons.length === 0 ? (
                    <div className="jalpi-ip__empty">
                      {tab === 'recent'    && 'No recently used icons yet.'}
                      {tab === 'favorites' && 'No favorites yet — hover an icon to add ★.'}
                      {tab === 'all'       && (query ? `No icons matching "${query}"` : 'No icons in this library.')}
                    </div>
                  ) : (
                    <div className="jalpi-ip__grid">
                      {pageIcons.map((icon) => (
                        <IconTile
                          key={`${icon.lib}:${icon.name}`}
                          icon={icon}
                          isActive={isActive(icon)}
                          isFav={isFav(icon)}
                          onClick={() => handleSelect(icon)}
                          onFav={(e) => handleFav(e, icon)}
                        />
                      ))}
                    </div>
                  )}

                  {/* Pagination */}
                  {totalPages > 1 && (
                    <div className="jalpi-ip__pagination">
                      <button type="button" disabled={page <= 1} onClick={() => setPage(1)}>«</button>
                      <button type="button" disabled={page <= 1} onClick={() => setPage((p) => p - 1)}>‹</button>
                      <span>{page} / {totalPages}</span>
                      <button type="button" disabled={page >= totalPages} onClick={() => setPage((p) => p + 1)}>›</button>
                      <button type="button" disabled={page >= totalPages} onClick={() => setPage(totalPages)}>»</button>
                    </div>
                  )}
                </>
              )}
            </div>
          </div>
        </div>

        {/* Footer: icon count */}
        <div className="jalpi-ip__footer">
          <span className="jalpi-ip__count">
            {query ? `${currentIcons.length} result${currentIcons.length !== 1 ? 's' : ''}` : `${currentIcons.length.toLocaleString()} icons`}
          </span>
          {activeVal && (
            <span className="jalpi-ip__selected-label">
              Selected: <strong>{activeVal.name}</strong> ({activeVal.lib})
            </span>
          )}
        </div>
      </div>
    </div>
  );
}

// ── IconInput — drop-in replacement for old pickers ──────────────────────────

interface IconInputProps {
  value?: string | IconValue;
  onChange: (v: IconValue | '') => void;
  placeholder?: string;
}

export function IconInput({ value, onChange, placeholder = 'Choose icon…' }: IconInputProps) {
  const [open, setOpen] = useState(false);

  // Build a PickerIcon from the current value (for display in the trigger)
  const currentIcon: PickerIcon | null = useMemo(() => {
    if (!value) return null;
    if (typeof value === 'string') {
      return iconRegistry.getAll('builtin').find((i) => i.name === value) ?? null;
    }
    if (value.type === 'svg') {
      return { lib: value.lib, name: value.name, label: value.name, category: '', type: 'svg', svg: value.svg };
    }
    if (value.type === 'font') {
      return { lib: value.lib, name: value.name, label: value.name, category: '', type: 'font', cls: value.cls };
    }
    return null;
  }, [value]);

  return (
    <>
      <div className="jalpi-icon-input">
        <button
          type="button"
          className={`jalpi-icon-input__trigger${currentIcon ? ' has-icon' : ''}`}
          onClick={() => setOpen(true)}
        >
          {currentIcon ? (
            <span className="jalpi-icon-input__preview">
              <IconDisplay icon={currentIcon} />
            </span>
          ) : (
            <span className="jalpi-icon-input__placeholder">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="8" r="5"/><path d="M3 21a9 9 0 0 1 18 0"/></svg>
            </span>
          )}
          <span className="jalpi-icon-input__label">{currentIcon ? currentIcon.label : placeholder}</span>
          <svg className="jalpi-icon-input__caret" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="6 9 12 15 18 9"/></svg>
        </button>

        {value && (
          <button
            type="button"
            className="jalpi-icon-input__clear"
            onClick={() => onChange('')}
            title="Remove icon"
          >✕</button>
        )}
      </div>

      {open && (
        <IconPickerModal
          value={value}
          onChange={(v) => { onChange(v); }}
          onClear={value ? () => onChange('') : undefined}
          onClose={() => setOpen(false)}
        />
      )}
    </>
  );
}
