// ── Modellen per rechtshandeling, als NL/FR-paar ─────────────────────────────
// Het kantoor werkt tweetalig en denkt per rechtshandeling (akteType): de
// bibliotheek wordt daarom niet als vlakke lijst getoond maar gegroepeerd per
// rechtshandeling, met het Nederlandstalige model en zijn Franstalige spiegel
// als één paar. Clausules die nog niet vertaald zijn (het FR-model verwijst
// naar het NL-onderdeel, of de FR-tekst draagt de "[TE VERTALEN]"-markering)
// worden in de UI in het GROEN gemarkeerd — instructie notaris 2026-07-05.
// Pure functies; de weergave zit in components/modeldocumenten/ModellenTab.

import type { Modeldocument, Modelonderdeel } from "./types";
import { TE_VERTALEN } from "./pariteit";

/** Eén rechtshandeling-model als taalpaar; één van beide kan (nog) ontbreken. */
export interface ModelPaar {
  nl?: Modeldocument;
  fr?: Modeldocument;
}

/** Alle modelparen van één rechtshandeling (akteType). */
export interface RechtshandelingGroep {
  rechtshandeling: string;
  paren: ModelPaar[];
}

/**
 * Koppelt de modellen tot NL/FR-paren via `vertalingVanId`. Een NL-model
 * zonder spiegel wordt een paar zonder `fr`; een FR-model zonder (bestaande)
 * NL-bron een paar zonder `nl` — beide blijven dus zichtbaar.
 */
export function koppelModelParen(modellen: readonly Modeldocument[]): ModelPaar[] {
  const byId = new Map(modellen.map((m) => [m.id, m]));
  const frPerBron = new Map<string, Modeldocument>();
  const frZonderBron: Modeldocument[] = [];
  for (const m of modellen) {
    if (m.taal !== "fr") continue;
    if (m.vertalingVanId && byId.has(m.vertalingVanId)) frPerBron.set(m.vertalingVanId, m);
    else frZonderBron.push(m);
  }
  const paren: ModelPaar[] = modellen
    .filter((m) => m.taal !== "fr")
    .map((nl) => ({ nl, fr: frPerBron.get(nl.id) }));
  return [...paren, ...frZonderBron.map((fr) => ({ fr }))];
}

/**
 * Groepeert de modelparen per rechtshandeling (het akteType van het NL-model,
 * of van het FR-model als er geen NL is), alfabetisch gesorteerd; binnen een
 * groep op titel.
 */
export function groepeerPerRechtshandeling(modellen: readonly Modeldocument[]): RechtshandelingGroep[] {
  const groepen = new Map<string, ModelPaar[]>();
  for (const paar of koppelModelParen(modellen)) {
    const sleutel = (paar.nl ?? paar.fr)!.akteType;
    const lijst = groepen.get(sleutel) ?? [];
    lijst.push(paar);
    groepen.set(sleutel, lijst);
  }
  return [...groepen.entries()]
    .map(([rechtshandeling, paren]) => ({
      rechtshandeling,
      paren: [...paren].sort((a, b) =>
        ((a.nl ?? a.fr)!.titel).localeCompare((b.nl ?? b.fr)!.titel, "nl")
      ),
    }))
    .sort((a, b) => a.rechtshandeling.localeCompare(b.rechtshandeling, "nl"));
}

/**
 * De onderdeel-ids in de structuur van een model die nog niet (volledig) in
 * de taal van het model beschikbaar zijn: het onderdeel is in de andere taal
 * (bv. een FR-model dat het NL-onderdeel hergebruikt zolang de vertaling
 * ontbreekt) of draagt nog de "[TE VERTALEN]"-markering. Dit zijn de
 * clausules die de UI in het groen toont.
 */
export function onvertaaldeClausules(
  model: Modeldocument,
  onderdelen: readonly Modelonderdeel[]
): string[] {
  const byId = new Map(onderdelen.map((o) => [o.id, o]));
  const doeltaal = model.taal === "fr" ? "fr" : "nl";
  const ids: string[] = [];
  for (const item of model.structuur) {
    const onderdeel = byId.get(item.onderdeelId);
    if (!onderdeel) continue; // ontbrekend onderdeel is een aparte fout (rood, niet groen)
    const andereTaal = (onderdeel.taal ?? "nl") !== doeltaal;
    const teVertalen = [onderdeel.tekst, ...onderdeel.varianten.map((v) => v.tekst)].some((t) =>
      t.includes(TE_VERTALEN)
    );
    if (andereTaal || teVertalen) ids.push(onderdeel.id);
  }
  return [...new Set(ids)];
}
