import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input } from '@learnitive/ui-components';
import { Search, X } from 'lucide-react';
import React from 'react';

const RECENT_KEY = 'learnitive.admin.template-category-icons.recent';
const PAGE_SIZE = 96;
const CATALOG_URL = '/learnitive-icons/lucide-category-icons.json';
const SPRITE_URL = '/learnitive-icons/lucide-category-icons.svg';

type IconEntry = { name: string; id: string };

function readRecent(): string[] {
  try {
    const value = JSON.parse(localStorage.getItem(RECENT_KEY) || '[]');
    return Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string').slice(0, 18) : [];
  } catch { return []; }
}

function groupFor(name: string) {
  const value = name.toLowerCase();
  if (/file|book|notebook|newspaper|scroll|clipboard|letter|mail/u.test(value)) return 'Documents';
  if (/graduation|school|library|badge|award/u.test(value)) return 'Education';
  if (/flask|atom|microscope|dna|testtube|brain|calculator/u.test(value)) return 'Science';
  if (/code|terminal|git|database|server|cpu|binary/u.test(value)) return 'Development';
  if (/briefcase|building|wallet|dollar|chart|receipt/u.test(value)) return 'Business';
  if (/presentation|image|video|music|camera|panel/u.test(value)) return 'Media';
  if (/message|phone|send|inbox|contact/u.test(value)) return 'Communication';
  return 'Other';
}

function IconTile({ icon, selected, onChoose }: { icon: IconEntry; selected: boolean; onChoose: (name: string) => void }) {
  return <button type="button" role="option" aria-selected={selected} aria-label={icon.name} className="interactive-category-icon-tile" data-selected={selected} onClick={() => onChoose(icon.name)} title={icon.name}>
    <svg className="size-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><use href={`${SPRITE_URL}#${icon.id}`}/></svg>
    <span>{icon.name}</span>
  </button>;
}

export function TemplateCategoryIconBrowser({ open, value, onSelect, onClose }: { open: boolean; value?: string; onSelect: (name: string) => void; onClose: () => void }) {
  const [icons, setIcons] = React.useState<IconEntry[]>([]);
  const [loadError, setLoadError] = React.useState('');
  const [query, setQuery] = React.useState('');
  const [group, setGroup] = React.useState('All');
  const [limit, setLimit] = React.useState(PAGE_SIZE);
  const [recent, setRecent] = React.useState<string[]>([]);

  React.useEffect(() => {
    if (!open) return;
    setRecent(readRecent());
    setLimit(PAGE_SIZE);
    if (icons.length) return;
    let cancelled = false;
    void fetch(CATALOG_URL, { cache: 'force-cache' })
      .then(async (response) => {
        if (!response.ok) throw new Error(`Icon catalog request failed (${response.status})`);
        const payload = await response.json() as unknown;
        if (!Array.isArray(payload)) throw new Error('Invalid icon catalog');
        const next = payload.filter((item): item is IconEntry => Boolean(item && typeof item === 'object' && typeof (item as IconEntry).name === 'string' && typeof (item as IconEntry).id === 'string'));
        if (!cancelled) setIcons(next);
      })
      .catch((error) => { if (!cancelled) setLoadError(error instanceof Error ? error.message : 'Unable to load icon catalog'); });
    return () => { cancelled = true; };
  }, [icons.length, open]);

  const groups = React.useMemo(() => ['All', 'Recent', 'Documents', 'Education', 'Science', 'Development', 'Business', 'Media', 'Communication', 'Other'], []);
  const filtered = React.useMemo(() => {
    const needle = query.trim().toLowerCase();
    let source = group === 'Recent' ? icons.filter((icon) => recent.includes(icon.name)) : icons;
    if (group !== 'All' && group !== 'Recent') source = source.filter((icon) => groupFor(icon.name) === group);
    if (needle) source = source.filter((icon) => icon.name.toLowerCase().includes(needle) || icon.id.includes(needle));
    return source;
  }, [group, icons, query, recent]);
  const visible = filtered.slice(0, limit);
  const choose = (name: string) => {
    const next = [name, ...recent.filter((item) => item !== name)].slice(0, 18);
    setRecent(next);
    try { localStorage.setItem(RECENT_KEY, JSON.stringify(next)); } catch {}
    onSelect(name);
    onClose();
  };

  return <Dialog open={open} onOpenChange={(next) => { if (!next) onClose(); }}><DialogContent className="interactive-category-icon-dialog">
    <DialogHeader><DialogTitle>Choose Lucide icon</DialogTitle><DialogDescription>Search and visually browse the Lucide icon library. The browser uses static SVG assets so it does not retain the Lucide React module graph.</DialogDescription></DialogHeader>
    <div className="interactive-category-icon-search"><Search className="size-4"/><Input value={query} onChange={(event) => { const next = event.currentTarget.value; setQuery(next); setLimit(PAGE_SIZE); }} aria-label="Search Lucide icons" placeholder="Search icons, e.g. book, flask, presentation…" autoFocus/><Button size="sm" variant="ghost" onClick={() => setQuery('')} aria-label="Clear icon search"><X className="size-4"/></Button></div>
    <div className="interactive-category-icon-groups" role="tablist" aria-label="Icon groups">{groups.map((item) => <button type="button" role="tab" aria-selected={group === item} key={item} data-active={group === item} onClick={() => { setGroup(item); setLimit(PAGE_SIZE); }}>{item}</button>)}</div>
    {loadError ? <div className="interactive-empty-state" role="alert"><p>{loadError}</p></div> : null}
    {!loadError && !icons.length ? <div className="interactive-category-icon-loading" role="status">Loading icon catalog…</div> : null}
    <div className="interactive-category-icon-grid" role="listbox" aria-label="Lucide icons">{visible.map((icon) => <IconTile key={icon.name} icon={icon} selected={value === icon.name} onChoose={choose}/>)}</div>
    {icons.length > 0 && !visible.length ? <div className="interactive-empty-state"><p>No Lucide icons match this search.</p></div> : null}
    {visible.length < filtered.length ? <Button variant="outline" onClick={() => setLimit((current) => current + PAGE_SIZE)}>Show more icons ({filtered.length - visible.length} remaining)</Button> : null}
    <DialogFooter><Button variant="outline" onClick={() => { onSelect(''); onClose(); }}>Clear icon</Button><Button variant="outline" onClick={onClose}>Close</Button></DialogFooter>
  </DialogContent></Dialog>;
}
