"use client";
import { useMemo, useState } from "react";
import {
  bouwBibliotheekOverzicht,
  hoofdthemaLabels,
  onderdeelCategorieLabels,
  auditBibliotheek,
  telPerCode,
  type AuditBevinding,
  type Hoofdthema,
  type Modeldocument,
  type Modelonderdeel,
  type OnderdeelGebruik,
} from "@/data/modeldocumenten";
import { OnderdelenNetwerk } from "./OnderdelenNetwerk";

type Weergave = "netwerk" | "modellen" | "hergebruik" | "kwaliteit";

// Themakleuren — statische klassen zodat Tailwind ze meebundelt.
const themaKleur: Record<Hoofdthema, string> = {
  algemeen: "bg-slate-100 text-slate-600 border-slate-200",
  familie: "bg-rose-100 text-rose-700 border-rose-200",
  vastgoed: "bg-brand-100 text-brand-700 border-brand-200",
  vennootschappen: "bg-indigo-100 text-indigo-700 border-indigo-200",
  fiscaal: "bg-amber-100 text-amber-700 border-amber-200",
};

function themaBadgeKlasse(thema?: Hoofdthema): string {
  return thema ? themaKleur[thema] : "bg-slate-100 text-slate-500 border-slate-200";
}

export function OverzichtTab({
  alleModellen,
  alleOnderdelen,
}: {
  alleModellen: Modeldocument[];
  alleOnderdelen: Modelonderdeel[];
}) {
  const [weergave, setWeergave] = useState<Weergave>("netwerk");
  // Gemarkeerd onderdeel: licht al zijn voorkomens over alle modellen op.
  const [gemarkeerd, setGemarkeerd] = useState<string | null>(null);

  const overzicht = useMemo(
    () => bouwBibliotheekOverzicht(alleModellen, alleOnderdelen),
    [alleModellen, alleOnderdelen],
  );

  // onderdeelId → in hoeveel modellen gebruikt (voor de ×N-badges).
  const aantalPerOnderdeel = useMemo(() => {
    const m = new Map<string, number>();
    for (const g of overzicht.gebruikPerOnderdeel) m.set(g.onderdeelId, g.modellen.length);
    return m;
  }, [overzicht]);

  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-center gap-2">
        <div className="inline-flex rounded-lg border border-slate-200 overflow-hidden">
          {(
            [
              ["netwerk", "Netwerk"],
              ["modellen", "Per modeldocument"],
              ["hergebruik", "Hergebruik van onderdelen"],
              ["kwaliteit", "Kwaliteit"],
            ] as [Weergave, string][]
          ).map(([id, label]) => (
            <button
              key={id}
              onClick={() => setWeergave(id)}
              className={`text-sm px-4 py-2 transition-colors ${
                weergave === id
                  ? "bg-brand-600 text-white font-medium"
                  : "bg-white text-slate-500 hover:text-slate-700"
              }`}
            >
              {label}
            </button>
          ))}
        </div>
        {gemarkeerd && (
          <button
            onClick={() => setGemarkeerd(null)}
            className="text-xs px-3 py-1.5 rounded-lg border border-slate-300 text-slate-600 hover:border-slate-400"
          >
            ✕ Markering wissen
          </button>
        )}
      </div>

      <StatStrip overzicht={overzicht} />

      {weergave === "netwerk" && (
        <OnderdelenNetwerk alleModellen={alleModellen} alleOnderdelen={alleOnderdelen} />
      )}
      {weergave === "modellen" && (
        <ModellenRaster
          modellen={alleModellen}
          onderdelen={alleOnderdelen}
          aantalPerOnderdeel={aantalPerOnderdeel}
          gemarkeerd={gemarkeerd}
          onMarkeer={(id) => setGemarkeerd((huidig) => (huidig === id ? null : id))}
        />
      )}
      {weergave === "hergebruik" && (
        <HergebruikWeergave
          overzicht={overzicht}
          gemarkeerd={gemarkeerd}
          onMarkeer={(id) => setGemarkeerd((huidig) => (huidig === id ? null : id))}
        />
      )}
      {weergave === "kwaliteit" && (
        <KwaliteitWeergave alleModellen={alleModellen} alleOnderdelen={alleOnderdelen} />
      )}
    </div>
  );
}

// ── Kwaliteit: de bibliotheek-audit, live over seed- én eigen items ──────────
// Dezelfde auditmotor als de kwaliteitstest (bibliotheek-audit.test.ts) en de
// voorstel-controle in "Te valideren"; hier over de actuele bibliotheek
// inclusief de eigen (IndexedDB-)wijzigingen van het kantoor.

const AUDIT_CODE_LABELS: Record<string, string> = {
  "rol-mapping-ontbreekt": "Rollen-mapping ontbreekt",
  "ontbrekend-onderdeel": "Onbestaand onderdeel in structuur",
  "generatie-restfout": "Restfout in gegenereerd voorbeeld",
  "dode-declaratie": "Dode parameterdeclaratie",
  "te-vertalen-markering": "[TE VERTALEN]-markering",
  "onvertaalde-clausule": "Clausule niet in de taal van het model",
  "tegenhanger-ontbreekt": "NL/FR-tegenhanger ontbreekt",
  "parameter-nergens-gedeclareerd": "Parameter nergens gedeclareerd",
  "duplicaat-tekst": "Identieke tekst als ander onderdeel",
};

function KwaliteitWeergave({
  alleModellen,
  alleOnderdelen,
}: {
  alleModellen: Modeldocument[];
  alleOnderdelen: Modelonderdeel[];
}) {
  const bevindingen = useMemo(
    () => auditBibliotheek(alleModellen, alleOnderdelen),
    [alleModellen, alleOnderdelen]
  );
  const perCode = useMemo(() => telPerCode(bevindingen), [bevindingen]);
  const fouten = bevindingen.filter((b) => b.ernst === "fout");
  const [openCode, setOpenCode] = useState<string | null>(null);

  const codes = [...perCode.entries()].sort((a, b) => b[1] - a[1]);

  return (
    <div className="space-y-4">
      <div
        className={`rounded-xl border px-5 py-4 ${
          fouten.length === 0 ? "bg-emerald-50 border-emerald-200" : "bg-red-50 border-red-200"
        }`}
      >
        <p className={`text-sm font-semibold ${fouten.length === 0 ? "text-emerald-800" : "text-red-800"}`}>
          {fouten.length === 0
            ? "✓ Geen fouten — dezelfde controles als de CI-kwaliteitstest zijn groen"
            : `✕ ${fouten.length} fout${fouten.length === 1 ? "" : "en"} — deze blokkeren de kwaliteitstest`}
        </p>
        <p className="text-xs text-slate-500 mt-1">
          {bevindingen.length - fouten.length} waarschuwing
          {bevindingen.length - fouten.length === 1 ? "" : "en"} (geplafonneerd in
          bibliotheek-audit.test.ts — plafonds kunnen enkel dalen).
        </p>
      </div>

      <div className="space-y-2">
        {codes.map(([code, aantal]) => {
          const items = bevindingen.filter((b) => b.code === code);
          const isFout = items[0]?.ernst === "fout";
          const open = openCode === code;
          return (
            <div key={code} className="bg-white border border-slate-200 rounded-xl overflow-hidden">
              <button
                onClick={() => setOpenCode(open ? null : code)}
                className="w-full text-left px-4 py-2.5 flex items-center gap-3"
              >
                <span
                  className={`text-xs px-2 py-0.5 rounded font-medium shrink-0 ${
                    isFout ? "bg-red-100 text-red-700" : "bg-amber-100 text-amber-700"
                  }`}
                >
                  {aantal}
                </span>
                <span className="flex-1 text-sm text-slate-700">{AUDIT_CODE_LABELS[code] ?? code}</span>
                <span className="text-slate-400 text-sm">{open ? "▴" : "▾"}</span>
              </button>
              {open && (
                <ul className="border-t border-slate-100 px-4 py-3 space-y-1.5 max-h-72 overflow-y-auto">
                  {items.slice(0, 100).map((b: AuditBevinding, i: number) => (
                    <li key={i} className="text-xs text-slate-600">
                      <span className="font-mono text-slate-800">{b.onderwerp}</span> — {b.omschrijving}
                    </li>
                  ))}
                  {items.length > 100 && (
                    <li className="text-xs text-slate-400">… en {items.length - 100} meer.</li>
                  )}
                </ul>
              )}
            </div>
          );
        })}
        {codes.length === 0 && (
          <p className="text-sm text-slate-400 py-6 text-center">Geen bevindingen — de bibliotheek is volledig proper.</p>
        )}
      </div>
    </div>
  );
}

function StatStrip({ overzicht }: { overzicht: ReturnType<typeof bouwBibliotheekOverzicht> }) {
  const stats: { label: string; waarde: number; klasse: string }[] = [
    { label: "Modeldocumenten", waarde: overzicht.aantalModellen, klasse: "text-slate-800" },
    { label: "Modelonderdelen", waarde: overzicht.aantalOnderdelen, klasse: "text-slate-800" },
    { label: "Gedeeld (≥2 modellen)", waarde: overzicht.gedeeld.length, klasse: "text-brand-700" },
    { label: "Ongebruikt", waarde: overzicht.ongebruikt.length, klasse: "text-amber-700" },
    {
      label: "Ontbrekende verwijzingen",
      waarde: overzicht.ontbrekend.length,
      klasse: overzicht.ontbrekend.length > 0 ? "text-red-700" : "text-slate-400",
    },
  ];
  return (
    <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3">
      {stats.map((s) => (
        <div key={s.label} className="bg-white border border-slate-200 rounded-xl px-4 py-3">
          <p className={`text-2xl font-bold ${s.klasse}`}>{s.waarde}</p>
          <p className="text-xs text-slate-500 mt-0.5">{s.label}</p>
        </div>
      ))}
    </div>
  );
}

// ── Weergave 1: per modeldocument de structuur ───────────────────────────────

function ModellenRaster({
  modellen,
  onderdelen,
  aantalPerOnderdeel,
  gemarkeerd,
  onMarkeer,
}: {
  modellen: Modeldocument[];
  onderdelen: Modelonderdeel[];
  aantalPerOnderdeel: Map<string, number>;
  gemarkeerd: string | null;
  onMarkeer: (onderdeelId: string) => void;
}) {
  const onderdeelPerId = useMemo(() => new Map(onderdelen.map((o) => [o.id, o])), [onderdelen]);

  // Modellen gegroepeerd per thema, in vaste themavolgorde.
  const themaVolgorde = Object.keys(hoofdthemaLabels) as Hoofdthema[];
  const gesorteerd = useMemo(
    () =>
      [...modellen].sort((a, b) => {
        const ta = a.thema ? themaVolgorde.indexOf(a.thema) : 99;
        const tb = b.thema ? themaVolgorde.indexOf(b.thema) : 99;
        return ta - tb || a.titel.localeCompare(b.titel);
      }),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [modellen],
  );

  if (modellen.length === 0) {
    return <p className="text-sm text-slate-400">Nog geen modeldocumenten in de bibliotheek.</p>;
  }

  return (
    <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
      {gesorteerd.map((model) => (
        <div key={model.id} className="bg-white border border-slate-200 rounded-xl shadow-sm overflow-hidden flex flex-col">
          <div className="px-4 py-3 border-b border-slate-100">
            <div className="flex items-center gap-2 flex-wrap">
              <span className={`text-xs px-2 py-0.5 rounded-md border ${themaBadgeKlasse(model.thema)}`}>
                {model.thema ? hoofdthemaLabels[model.thema] : "—"}
              </span>
              {model.taal === "fr" && (
                <span className="text-xs px-2 py-0.5 rounded-md border border-slate-200 bg-slate-50 text-slate-500">
                  FR
                </span>
              )}
            </div>
            <p className="text-sm font-semibold text-slate-800 mt-1.5">{model.titel}</p>
            <p className="text-xs text-slate-400 mt-0.5">
              {model.akteType} · {model.structuur.length} onderdelen
            </p>
          </div>
          <ol className="px-4 py-3 space-y-1 flex-1">
            {model.structuur.map((item, i) => {
              const onderdeel = onderdeelPerId.get(item.onderdeelId);
              const aantal = aantalPerOnderdeel.get(item.onderdeelId) ?? 0;
              const isGemarkeerd = gemarkeerd === item.onderdeelId;
              const ontbreekt = !onderdeel;
              return (
                <li key={`${item.onderdeelId}-${i}`}>
                  <button
                    onClick={() => onMarkeer(item.onderdeelId)}
                    className={`w-full text-left flex items-baseline gap-2 rounded-md px-1.5 py-1 -mx-1.5 transition-colors ${
                      isGemarkeerd ? "bg-brand-50 ring-1 ring-brand-200" : "hover:bg-slate-50"
                    }`}
                    title={
                      ontbreekt
                        ? `Ontbrekend onderdeel: ${item.onderdeelId}`
                        : `Gebruikt in ${aantal} modeldocument${aantal > 1 ? "en" : ""} — klik om alle voorkomens te markeren`
                    }
                  >
                    <span className="text-slate-300 text-xs w-4 shrink-0 tabular-nums">{i + 1}</span>
                    <span className={`text-sm flex-1 ${ontbreekt ? "text-red-600" : "text-slate-700"}`}>
                      {onderdeel ? onderdeel.titel : `Ontbrekend: ${item.onderdeelId}`}
                      {!item.verplicht && (
                        <span className="ml-1.5 text-xs text-amber-600">(facultatief)</span>
                      )}
                    </span>
                    {aantal >= 2 && (
                      <span
                        className={`text-xs px-1.5 py-0.5 rounded-md shrink-0 ${
                          isGemarkeerd ? "bg-brand-600 text-white" : "bg-brand-50 text-brand-700"
                        }`}
                      >
                        ×{aantal}
                      </span>
                    )}
                  </button>
                </li>
              );
            })}
          </ol>
        </div>
      ))}
    </div>
  );
}

// ── Weergave 2: hergebruik van onderdelen over modellen heen ─────────────────

function HergebruikWeergave({
  overzicht,
  gemarkeerd,
  onMarkeer,
}: {
  overzicht: ReturnType<typeof bouwBibliotheekOverzicht>;
  gemarkeerd: string | null;
  onMarkeer: (onderdeelId: string) => void;
}) {
  const [toonOngebruikt, setToonOngebruikt] = useState(false);

  return (
    <div className="space-y-6">
      {overzicht.ontbrekend.length > 0 && (
        <section className="bg-red-50 border border-red-200 rounded-xl p-4 space-y-2">
          <p className="text-sm font-semibold text-red-800">
            ⚠️ Ontbrekende verwijzingen ({overzicht.ontbrekend.length})
          </p>
          <p className="text-xs text-red-700">
            Deze id&apos;s worden door een modeldocument aangeroepen maar bestaan niet (meer) als
            modelonderdeel — controleer de betrokken structuur.
          </p>
          <ul className="space-y-1.5">
            {overzicht.ontbrekend.map((g) => (
              <li key={g.onderdeelId} className="text-sm text-red-800">
                <code className="text-xs bg-red-100 px-1.5 py-0.5 rounded">{g.onderdeelId}</code>{" "}
                <span className="text-xs text-red-600">
                  in {g.modellen.map((m) => m.titel).join(", ")}
                </span>
              </li>
            ))}
          </ul>
        </section>
      )}

      <section className="space-y-2">
        <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          Gedeelde modelonderdelen — gebruikt in ≥2 modeldocumenten ({overzicht.gedeeld.length})
        </p>
        {overzicht.gedeeld.length === 0 ? (
          <p className="text-sm text-slate-400">
            Geen enkel onderdeel wordt momenteel door meer dan één modeldocument gebruikt.
          </p>
        ) : (
          <div className="space-y-2">
            {overzicht.gedeeld.map((g) => (
              <GedeeldeRegel
                key={g.onderdeelId}
                gebruik={g}
                gemarkeerd={gemarkeerd === g.onderdeelId}
                onMarkeer={() => onMarkeer(g.onderdeelId)}
              />
            ))}
          </div>
        )}
      </section>

      {overzicht.ongebruikt.length > 0 && (
        <section className="space-y-2">
          <button
            onClick={() => setToonOngebruikt((v) => !v)}
            className="text-xs font-semibold text-slate-500 uppercase tracking-wide flex items-center gap-1.5 hover:text-slate-700"
          >
            <span>{toonOngebruikt ? "▾" : "▸"}</span>
            Niet in een modeldocument opgenomen ({overzicht.ongebruikt.length})
          </button>
          {toonOngebruikt && (
            <>
              <p className="text-xs text-slate-400">
                Beschikbare clausules die (nog) in geen enkel modeldocument zijn opgenomen — bruikbaar
                als losse clausule of nog te koppelen aan een model.
              </p>
              <div className="flex flex-wrap gap-1.5">
                {overzicht.ongebruikt.map((o) => (
                  <span
                    key={o.id}
                    className="text-xs px-2 py-1 rounded-md border border-slate-200 bg-white text-slate-600"
                    title={onderdeelCategorieLabels[o.categorie]}
                  >
                    {o.titel}
                  </span>
                ))}
              </div>
            </>
          )}
        </section>
      )}
    </div>
  );
}

function GedeeldeRegel({
  gebruik,
  gemarkeerd,
  onMarkeer,
}: {
  gebruik: OnderdeelGebruik;
  gemarkeerd: boolean;
  onMarkeer: () => void;
}) {
  const onderdeel = gebruik.onderdeel;
  return (
    <div
      className={`bg-white border rounded-xl px-4 py-3 transition-colors ${
        gemarkeerd ? "border-brand-300 ring-1 ring-brand-200" : "border-slate-200"
      }`}
    >
      <button onClick={onMarkeer} className="w-full text-left flex items-start gap-3">
        <span className="shrink-0 mt-0.5 text-sm font-bold text-brand-700 bg-brand-50 rounded-md px-2 py-0.5 tabular-nums">
          ×{gebruik.modellen.length}
        </span>
        <div className="flex-1 min-w-0">
          <p className="text-sm font-medium text-slate-800">{onderdeel?.titel ?? gebruik.onderdeelId}</p>
          {onderdeel && (
            <p className="text-xs text-slate-400">{onderdeelCategorieLabels[onderdeel.categorie]}</p>
          )}
          <div className="flex flex-wrap gap-1.5 mt-2">
            {gebruik.modellen.map((m) => (
              <span
                key={m.id}
                className={`text-xs px-2 py-0.5 rounded-md border ${themaBadgeKlasse(m.thema)} ${
                  m.verplicht ? "" : "opacity-70 italic"
                }`}
                title={`${m.akteType} — positie ${m.positie}${m.verplicht ? "" : " · facultatief"}`}
              >
                {m.titel}
              </span>
            ))}
          </div>
        </div>
      </button>
    </div>
  );
}
