// FilterPanel — 9 filtergroepen, collapsible, met counters uit de server-facets.
// Filters zijn AND-gestapeld. URL-state via parent.
//
// Counters komen sinds de API-omzetting uit /v1/vergunningen/facets (props.facets).
// De facets respecteren ALLE actieve filters — een gedeselecteerde waarde uit
// dezelfde groep krijgt count=0 en verdwijnt uit de facet-array. Dat is een
// bewuste API-keuze (v1).

const { useState: useStateFP, useMemo: useMemoFP } = React;

function Section({ title, defaultOpen = true, count, action, loading, children }) {
  const [open, setOpen] = useStateFP(defaultOpen);
  return (
    <section className="border-b border-slate-200">
      <button
        type="button"
        onClick={() => setOpen(!open)}
        className="w-full flex items-center justify-between px-4 py-2.5 text-left hover:bg-slate-50 focus:outline-none focus:bg-slate-50"
        aria-expanded={open}
      >
        <div className="flex items-center gap-2">
          <span className="text-[12px] uppercase tracking-wider text-slate-700 font-medium">{title}</span>
          {count != null && (
            <span className="text-[11px] text-slate-400 tabular-nums">({fmt.number(count)})</span>
          )}
          {loading && open && (
            <span
              aria-label="Counters worden bijgewerkt"
              className="inline-block w-1.5 h-1.5 rounded-full bg-emerald-900/60 animate-pulse"
            ></span>
          )}
        </div>
        <div className="flex items-center gap-2">
          {action}
          <svg viewBox="0 0 12 12" className={`w-3 h-3 text-slate-400 transition-transform ${open ? '' : '-rotate-90'}`} aria-hidden>
            <path d="M3 4.5 L6 7.5 L9 4.5" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </div>
      </button>
      {open && <div className="px-4 pb-3">{children}</div>}
    </section>
  );
}

function CountedCheckbox({ label, checked, onChange, count, maxCount, color, dim }) {
  const pct = maxCount > 0 ? (count / maxCount) * 100 : 0;
  return (
    <label className={`relative flex items-center gap-2.5 py-1 px-1.5 cursor-pointer text-[13px] hover:bg-slate-50 group rounded-sm ${dim ? 'text-slate-400' : 'text-slate-800'}`}>
      <span
        aria-hidden
        className="absolute inset-y-1 left-1.5 rounded-sm pointer-events-none"
        style={{
          width: `calc(${pct}% - 0.375rem)`,
          background: '#F1EFE9',
          maxWidth: 'calc(100% - 0.75rem)',
        }}
      ></span>
      <input
        type="checkbox"
        checked={checked}
        onChange={onChange}
        className="relative z-10 w-3.5 h-3.5 rounded-sm border-slate-300 text-emerald-900 focus:ring-emerald-900/20 focus:ring-2"
      />
      <span className="relative z-10 flex-1 truncate flex items-center gap-2">
        {color && (
          <span className="inline-block w-2 h-2 rounded-full" style={{ background: color }}></span>
        )}
        <span>{label}</span>
      </span>
      <span className={`relative z-10 text-[11px] tabular-nums shrink-0 ${dim ? 'text-slate-400' : 'text-slate-500'}`}>{fmt.number(count)}</span>
    </label>
  );
}

function DateInput({ value, onChange, label }) {
  return (
    <label className="flex flex-col gap-1 flex-1">
      <span className="text-[10px] uppercase tracking-wider text-slate-500">{label}</span>
      <input
        type="date"
        value={value || ''}
        onChange={(e) => onChange(e.target.value || null)}
        className="text-[12px] bg-white border border-slate-200 rounded px-2 py-1 text-slate-900 focus:outline-none focus:border-emerald-900 focus:ring-2 focus:ring-emerald-900/10 font-mono"
      />
    </label>
  );
}

function FilterPanel({ state, setState, facets, facetsLoading, filteredCount, onReset }) {
  // Lookup-map per facet-groep voor snelle count-aflezing.
  // Tijdens loading (facets===null) tonen we 0 en dimmen via `dim`.
  const lookupMap = useMemoFP(() => {
    const out = {};
    if (!facets) return out;
    for (const k of ['type_besluit', 'activiteit_code', 'bg_naam', 'organisatietype', 'subject_taxonomie', 'publicatieblad']) {
      out[k] = {};
      const arr = facets[k] || [];
      for (const f of arr) out[k][f.value] = f.count;
    }
    return out;
  }, [facets]);

  const maxMap = useMemoFP(() => {
    const out = {};
    for (const k of Object.keys(lookupMap)) {
      out[k] = Math.max(1, ...Object.values(lookupMap[k]));
    }
    return out;
  }, [lookupMap]);

  const countOf = (group, value) => (lookupMap[group] && lookupMap[group][value]) || 0;
  const maxOf = (group) => maxMap[group] || 1;

  const toggleArr = (key, val) => {
    const next = state[key].includes(val) ? state[key].filter((x) => x !== val) : [...state[key], val];
    setState({ ...state, [key]: next });
  };

  const setField = (k, v) => setState({ ...state, [k]: v });

  // BG-lijst komt nu uit facets (top 100 server-side). Gefilterd op zoektypje
  // en aangevuld met al-geselecteerde waardes die buiten top-100 vallen,
  // zodat een selectie niet zomaar uit het scherm verdwijnt.
  const [bgQuery, setBgQuery] = useStateFP('');
  const bgList = useMemoFP(() => {
    const fromFacets = (facets && facets.bg_naam) || [];
    const known = new Set(fromFacets.map((f) => f.value));
    const extras = state.bg.filter((v) => !known.has(v)).map((v) => ({ value: v, count: 0 }));
    const all = fromFacets.concat(extras);
    const needle = bgQuery.toLowerCase();
    return needle ? all.filter((f) => f.value.toLowerCase().includes(needle)) : all;
  }, [facets, state.bg, bgQuery]);

  const dim = !facets;

  return (
    <aside className="w-[320px] shrink-0 border-r border-slate-200 bg-[#FAFAF7] overflow-y-auto flex flex-col">
      {/* Top result count */}
      <div className="px-4 py-3 border-b border-slate-200 bg-white sticky top-0 z-10">
        <div className="flex items-baseline justify-between gap-2">
          <div className="font-serif text-[15px] text-slate-900 leading-tight">
            <span className="tabular-nums font-medium">{fmt.number(filteredCount)}</span>{' '}
            <span className="text-slate-600">{filteredCount === 1 ? 'vergunning' : 'vergunningen'}</span>
          </div>
          <button
            onClick={onReset}
            className="text-[11px] text-slate-500 hover:text-emerald-900 hover:underline focus:outline-none focus:text-emerald-900"
          >
            reset filters
          </button>
        </div>
        <div className="text-[11px] text-slate-500 mt-0.5">voldoen aan filters</div>
      </div>

      <div className="flex-1">
        {/* LOCATIE */}
        <Section title="Locatie" defaultOpen={true}>
          <label className="flex items-center gap-2 text-[13px] text-slate-800 py-1.5 cursor-pointer">
            <input
              type="checkbox"
              checked={state.binnen}
              onChange={(e) => setField('binnen', e.target.checked)}
              className="w-3.5 h-3.5 rounded-sm border-slate-300 text-emerald-900 focus:ring-emerald-900/20 focus:ring-2"
            />
            <span>Alleen binnen huidig kaartbeeld</span>
          </label>
          <div className="mt-1 text-[11px] text-slate-500">
            Pan of zoom op de kaart om dit gebied te wijzigen.
          </div>
        </Section>

        {/* PERIODE */}
        <Section title="Periode" defaultOpen={true}>
          <div className="flex gap-2">
            <DateInput value={state.vanaf} onChange={(v) => setField('vanaf', v)} label="van" />
            <DateInput value={state.totd} onChange={(v) => setField('totd', v)} label="tot en met" />
          </div>
          <div className="mt-2 flex flex-wrap gap-1">
            {[
              { lbl: 'Laatste 7 dagen', days: 7 },
              { lbl: 'Laatste maand', days: 30 },
              { lbl: 'Laatste jaar', days: 365 },
              { lbl: 'Sinds inwerkingtreding Ow', date: '2024-01-01' },
            ].map((p) => (
              <button
                key={p.lbl}
                onClick={() => {
                  const today = new Date();
                  const toIso = (d) => d.toISOString().slice(0, 10);
                  setState({
                    ...state,
                    totd: toIso(today),
                    vanaf: p.date || toIso(new Date(today.getTime() - p.days * 86400000)),
                  });
                }}
                className="text-[11px] px-2 py-0.5 border border-slate-200 rounded-sm bg-white hover:bg-slate-50 hover:border-slate-300 text-slate-700"
              >
                {p.lbl}
              </button>
            ))}
          </div>
        </Section>

        {/* TYPE BESLUIT */}
        <Section title="Type besluit" defaultOpen={true} loading={facetsLoading}>
          {WAARDELIJSTEN.type_besluit.map((tb) => (
            <CountedCheckbox
              key={tb.code}
              label={tb.label}
              color={tb.color}
              checked={state.tb.includes(tb.code)}
              onChange={() => toggleArr('tb', tb.code)}
              count={countOf('type_besluit', tb.code)}
              maxCount={maxOf('type_besluit')}
              dim={dim}
            />
          ))}
        </Section>

        {/* ACTIVITEIT */}
        <Section title="Activiteit" defaultOpen={true} loading={facetsLoading}>
          {WAARDELIJSTEN.activiteit_code.map((a) => (
            <CountedCheckbox
              key={a.code}
              label={a.label}
              checked={state.ac.includes(a.code)}
              onChange={() => toggleArr('ac', a.code)}
              count={countOf('activiteit_code', a.code)}
              maxCount={maxOf('activiteit_code')}
              dim={dim}
            />
          ))}
        </Section>

        {/* BEVOEGD GEZAG */}
        <Section title="Bevoegd gezag" defaultOpen={false} count={state.bg.length || null} loading={facetsLoading}>
          <input
            type="text"
            value={bgQuery}
            onChange={(e) => setBgQuery(e.target.value)}
            placeholder="Zoek bevoegd gezag…"
            className="w-full text-[12px] bg-white border border-slate-200 rounded px-2 py-1 mb-2 focus:outline-none focus:border-emerald-900"
          />
          <div className="max-h-64 overflow-y-auto -mx-1">
            {bgList.length === 0 && (
              <div className="text-[11px] text-slate-400 px-1.5 py-1">
                {facets ? 'Geen treffers binnen huidige filters.' : 'Bezig met laden…'}
              </div>
            )}
            {bgList.map((f) => (
              <CountedCheckbox
                key={f.value}
                label={f.value}
                checked={state.bg.includes(f.value)}
                onChange={() => toggleArr('bg', f.value)}
                count={f.count}
                maxCount={maxOf('bg_naam')}
                dim={dim}
              />
            ))}
          </div>
          {facets && facets.bg_naam && facets.bg_naam.length === 100 && (
            <div className="text-[10px] text-slate-400 mt-1 px-1.5">
              Top 100 getoond — verfijn andere filters om scherper te zoeken.
            </div>
          )}
        </Section>

        {/* ORGANISATIETYPE */}
        <Section title="Organisatietype" defaultOpen={false} loading={facetsLoading}>
          {WAARDELIJSTEN.organisatietype.map((o) => (
            <CountedCheckbox
              key={o.code}
              label={o.label}
              checked={state.org.includes(o.code)}
              onChange={() => toggleArr('org', o.code)}
              count={countOf('organisatietype', o.code)}
              maxCount={maxOf('organisatietype')}
              dim={dim}
            />
          ))}
        </Section>

        {/* BELEIDSTHEMA */}
        <Section title="Beleidsthema" defaultOpen={false} loading={facetsLoading}>
          {WAARDELIJSTEN.subject_taxonomie.map((s) => (
            <CountedCheckbox
              key={s.code}
              label={s.label}
              checked={state.th.includes(s.label)}
              onChange={() => toggleArr('th', s.label)}
              count={countOf('subject_taxonomie', s.label)}
              maxCount={maxOf('subject_taxonomie')}
              dim={dim}
            />
          ))}
        </Section>

        {/* DATA-EIGENSCHAPPEN */}
        <Section title="Data-eigenschappen" defaultOpen={false}>
          <label className="flex items-center gap-2 text-[13px] text-slate-800 py-1 cursor-pointer">
            <input
              type="checkbox"
              checked={state.geom}
              onChange={(e) => setField('geom', e.target.checked)}
              className="w-3.5 h-3.5 rounded-sm border-slate-300 text-emerald-900 focus:ring-emerald-900/20 focus:ring-2"
            />
            <span>Alleen records met locatie</span>
          </label>
          <label className="flex items-center gap-2 text-[13px] text-slate-800 py-1 cursor-pointer">
            <input
              type="checkbox"
              checked={state.ontv}
              onChange={(e) => setField('ontv', e.target.checked)}
              className="w-3.5 h-3.5 rounded-sm border-slate-300 text-emerald-900 focus:ring-emerald-900/20 focus:ring-2"
            />
            <span>Aanvraagdatum bekend</span>
          </label>
        </Section>

        {/* ZAAKNUMMER */}
        <Section title="Zaaknummer" defaultOpen={false}>
          <input
            type="text"
            value={state.zaak}
            onChange={(e) => setField('zaak', e.target.value)}
            placeholder="bv. Z-2026-001234"
            className="w-full text-[12px] bg-white border border-slate-200 rounded px-2 py-1 focus:outline-none focus:border-emerald-900 font-mono"
          />
        </Section>
      </div>

      <footer className="px-4 py-3 border-t border-slate-200 text-[11px] text-slate-500 leading-snug bg-white">
        Bron: officielebekendmakingen.nl (KOOP) — geen persoonsgegevens, geen cookies, alle data is openbaar.
      </footer>
    </aside>
  );
}

// matchesQ wordt sinds de API-omzetting niet meer client-side gebruikt
// (de server doet ILIKE). Behouden voor compat als de mock-fallback weer
// wordt aangezet.
function matchesQ(r, q) {
  const needle = (q || '').toLowerCase().trim();
  if (!needle) return true;
  return (
    (r.koop_id || '').toLowerCase().includes(needle) ||
    (r.zaaknummer_bg || '').toLowerCase().includes(needle) ||
    (r.postcode || '').toLowerCase().replace(/\s+/g, '').includes(needle.replace(/\s+/g, '')) ||
    (r.titel || '').toLowerCase().includes(needle) ||
    (r.straatnaam || '').toLowerCase().includes(needle) ||
    (r.woonplaats || '').toLowerCase().includes(needle)
  );
}

Object.assign(window, { FilterPanel, matchesQ });
