/** Catalog checklist helpers for ConditionGroup repeated field #2 (fixed32 IDs). Load after React + d4-filter-shared.js */
(function (global) {
  'use strict';
  const { useMemo, useState, useEffect } = React;
  const { fixed32FromU32LE, fixed32ToU32LE } = window.D4Filter;

  function normalizeCatalog(raw) {
    if (!raw || typeof raw !== 'object') return { categories: [] };
    const cats = Array.isArray(raw.categories) ? raw.categories : [];
    return {
      categories: cats.map((c, i) => ({
        id: String(c.id || `cat-${i}`),
        label: String(c.label || c.name || `Category ${i + 1}`),
        entries: (Array.isArray(c.entries) ? c.entries : Array.isArray(c.items) ? c.items : [])
          .map((e, j) => {
            const id = Number(e.id !== undefined ? e.id : e.u32 !== undefined ? e.u32 : e.u);
            const name = String(e.name || e.label || `Type ${j}`);
            return { id: id >>> 0, name };
          })
          .filter(e => e.id > 0),
      })),
    };
  }

  function extractConditionU32s(cgMessage) {
    const out = [];
    for (const c of cgMessage.children || []) {
      if (c.fieldNum === 2 && c.kind === 'fixed32') out.push(fixed32ToU32LE(c.value) >>> 0);
    }
    return out;
  }

  function catalogIdSet(catalog) {
    const s = new Set();
    for (const cat of catalog.categories || []) {
      for (const e of cat.entries || []) s.add(e.id >>> 0);
    }
    return s;
  }

  function rebuildConditionWithIds(prevCg, selectedU32Set) {
    const ch = prevCg.children || [];
    const preserved = ch.filter(c => !(c.fieldNum === 2 && c.kind === 'fixed32'));
    const typeEnt = preserved.filter(c => c.fieldNum === 1);
    const rest = preserved.filter(c => c.fieldNum !== 1);
    const sorted = [...selectedU32Set].map(u => u >>> 0).sort((a, b) => a - b);
    const idFields = sorted.map(u => ({
      fieldNum: 2,
      wireType: 5,
      kind: 'fixed32',
      value: fixed32FromU32LE(u >>> 0),
    }));
    return { ...prevCg, children: [...typeEnt, ...idFields, ...rest] };
  }

  function ConditionIdChecklist({ conditionGroup, catalog, onApply, searchPlaceholder, emptyHint }) {
    const norm = useMemo(() => normalizeCatalog(catalog), [catalog]);
    const catIdSet = useMemo(() => catalogIdSet(norm), [norm]);
    const [filter, setFilter] = useState('');
    const [selected, setSelected] = useState(() => new Set(extractConditionU32s(conditionGroup)));

    useEffect(() => {
      setSelected(new Set(extractConditionU32s(conditionGroup)));
    }, [conditionGroup]);

    const unknownIds = useMemo(() =>
      [...new Set(extractConditionU32s(conditionGroup).filter(u => !catIdSet.has(u >>> 0)))],
    [conditionGroup, catIdSet]);

    const applySet = (next) => {
      setSelected(next);
      if (typeof onApply === 'function') onApply(next);
    };

    const toggle = (u32, on) => {
      const u = u32 >>> 0;
      const next = new Set(selected);
      if (on) next.add(u); else next.delete(u);
      applySet(next);
    };

    const filt = (name) => {
      if (!filter.trim()) return true;
      return name.toLowerCase().includes(filter.toLowerCase());
    };

    const totalCatalogEntries = useMemo(() =>
      norm.categories.reduce((n, c) => n + c.entries.length, 0), [norm]);

    return (
      <div className="item-type-checklist text-left">
        <div className="mb-2 flex flex-wrap items-center gap-2">
          <input
            type="search"
            value={filter}
            onChange={e => setFilter(e.target.value)}
            placeholder={searchPlaceholder || 'Search…'}
            className="flex-1 min-w-[8rem] rounded border border-red-950/40 bg-black/50 px-2 py-1.5 text-xs text-stone-200 placeholder:text-stone-600"
          />
          <span className="text-[10px] text-stone-500 font-mono whitespace-nowrap">
            {selected.size} selected
          </span>
        </div>

        {totalCatalogEntries === 0 ? (
          <p className="rounded border border-amber-900/40 bg-amber-950/25 px-3 py-2 text-xs text-amber-100/90 leading-relaxed">
            {emptyHint || <>No catalog entries yet. Add categories with <span className="font-mono">entries: [&#123; &quot;id&quot;: u32, &quot;name&quot;: &quot;…&quot; &#125;]</span>.</>}
          </p>
        ) : (
          <div className="max-h-[min(52vh,28rem)] overflow-y-auto rounded border border-stone-800/80 bg-black/30 pr-1">
            {norm.categories.map(cat => {
              const visible = cat.entries.filter(e => filt(e.name));
              if (!visible.length && filter.trim()) return null;
              const selInCat = visible.filter(e => selected.has(e.id >>> 0)).length;
              const allOn = visible.length > 0 && visible.every(e => selected.has(e.id >>> 0));
              return (
                <details key={cat.id} className="border-b border-stone-800/60 last:border-0 group" open>
                  <summary className="cursor-pointer list-none flex flex-wrap items-center gap-2 px-2 py-2 bg-stone-950/60 font-d4-banner text-[0.58rem] uppercase tracking-[0.14em] text-stone-400">
                    <span className="text-stone-300">{cat.label}</span>
                    <span className="font-mono text-[10px] text-stone-600">{selInCat} / {cat.entries.length}</span>
                    <button type="button"
                      className="ml-auto text-[10px] uppercase tracking-wide text-red-300/90 hover:text-red-200 px-2 py-0.5 rounded border border-red-950/50"
                      onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        const next = new Set(selected);
                        if (allOn) visible.forEach(e => next.delete(e.id >>> 0));
                        else visible.forEach(e => next.add(e.id >>> 0));
                        applySet(next);
                      }}>
                      {allOn ? 'Clear section' : 'Select section'}
                    </button>
                  </summary>
                  <ul className="list-none pl-0 py-1 space-y-0.5">
                    {cat.entries.map(e => {
                      if (!filt(e.name)) return null;
                      const id = e.id >>> 0;
                      const on = selected.has(id);
                      return (
                        <li key={cat.id + '-' + id}>
                          <label className="flex items-center gap-2 px-3 py-1.5 rounded hover:bg-red-950/20 cursor-pointer text-sm text-stone-200">
                            <input type="checkbox" className="accent-red-700 shrink-0" checked={on} onChange={ev => toggle(id, ev.target.checked)} />
                            <span className="flex-1">{e.name}</span>
                            <span className="font-mono text-[10px] text-stone-600">{id}</span>
                          </label>
                        </li>
                      );
                    })}
                  </ul>
                </details>
              );
            })}
          </div>
        )}

        {unknownIds.length > 0 ? (
          <div className="mt-3 rounded border border-stone-700/80 bg-stone-950/50 px-2 py-2">
            <div className="text-[10px] font-d4-banner uppercase tracking-wider text-stone-500 mb-1">Other IDs in this condition</div>
            <p className="text-[10px] text-stone-600 mb-2">Not listed in your catalog — uncheck to remove.</p>
            <ul className="list-none pl-0 space-y-1 max-h-40 overflow-y-auto">
              {unknownIds.map(u => (
                <li key={'unk-' + u}>
                  <label className="flex items-center gap-2 text-xs text-amber-200/90 cursor-pointer px-2 py-1 rounded hover:bg-black/35">
                    <input type="checkbox" className="accent-amber-700" checked={selected.has(u)} onChange={ev => toggle(u, ev.target.checked)} />
                    <span className="font-mono">Unknown · {u} (0x{(u >>> 0).toString(16)})</span>
                  </label>
                </li>
              ))}
            </ul>
          </div>
        ) : null}

      </div>
    );
  }

  function ItemTypeMatchChecklist(props) {
    return (
      <ConditionIdChecklist
        {...props}
        searchPlaceholder={props.searchPlaceholder || 'Search item types…'}
        emptyHint={props.emptyHint || <>No item types in <span className="font-mono">item-types.json</span> yet.</>}
      />
    );
  }

  global.D4FilterItemTypes = {
    normalizeCatalog,
    extractConditionU32s,
    rebuildConditionWithIds,
    catalogIdSet,
    ConditionIdChecklist,
    ItemTypeMatchChecklist,
  };
})(typeof window !== 'undefined' ? window : globalThis);
