// Loop 8 (Roadmap §12): primäre Navigation an QAF-Terminologie ausgerichtet.
//
// Die Roadmap gibt die Hauptreiter wörtlich vor — Überblick, Zusammenfassung,
// Material, Fertigungskosten, SBM/Vorrichtungen/Folgewerkzeuge, Logistik und
// Zoll, Rohstoffrisiken, Zusatzmodule, Qualität und Maßnahmen, Technischer
// Nachweis — mit vier Auflagen, die dieses Modul umsetzt:
//
//   1. „nur verfügbare Hauptreiter anzeigen"      → `visibleAreas`
//   2. „gleiche semantische IDs im Hintergrund"   → `sections` je Bereich sind
//      die unveränderten QafSectionKeys der 14-Sektionen-Seite
//   3. „aktuelle 14-Sektionen-Langseite als Kompatibilitätsansicht erhalten"
//      → `ALL_SECTIONS_AREA`, immer sichtbar, zeigt alles
//   4. „Deep Links auf semantische Bereiche"      → `?bereich=<id>`
//
// Was dieses Modul BEWUSST nicht tut: einen Bereich verstecken, nur weil ihm
// keine der 14 Sektionen zugeordnet ist. Material ist genau dieser Fall — die
// Langseite hat keine eigene Material-Sektion, Material steckt in Buckets und
// Kennzahlen. Ein solcher Bereich wird trotzdem angeboten, wenn die
// Capability-Matrix sein Modul als vorhanden meldet, und sagt dann selbst,
// dass die Detailsicht dazu noch fehlt. Das ist der Unterschied zwischen
// „nicht da" und „nicht gebaut", und Letzteres darf nicht als Ersteres
// aussehen (Roadmap-Exit „nicht berechnete Bereiche sind in Coverage
// sichtbar").
//
// Pur: keine DB, kein Framework, keine React-Abhängigkeit.

import type { QafSectionKey } from "@/components/qaf-differences/qaf-section-registry"
import type { CoverageEntry } from "@/lib/qaf-differences"

/** Query-Parameter des aktiven Hauptreiters. Deutsch, weil in der URL sichtbar. */
export const PRIMARY_AREA_PARAM = "bereich"

/** Kompatibilitätsansicht: die vollständige 14-Sektionen-Langseite. Bleibt
 *  laut Roadmap erhalten und ist der Rückfallwert — wer keinen Reiter wählt,
 *  sieht weiterhin alles, genau wie vor Loop 8. */
export const ALL_SECTIONS_AREA = "alle"

export interface PrimaryArea {
  /** Stabiler Bezeichner, erscheint in der URL. */
  id: string
  /** Anzeigename in QAF-/Excel-Terminologie (Roadmap-Exit: „QAF-Nutzer
   *  erkennen ihre Excel-Terminologie wieder"). */
  label: string
  /** Capability-Module, die diesen Bereich tragen. Leer = nicht an die
   *  Matrix gebunden (Überblick, Kompatibilitätsansicht) und damit immer
   *  sichtbar. */
  modules: readonly string[]
  /** Sektionen der Langseite, die dieser Bereich zeigt — unveränderte
   *  semantische IDs, keine Umbenennung. Leer heißt: noch keine eigene
   *  Detailsicht (siehe Modulkopf). */
  sections: readonly QafSectionKey[]
}

/* Zuordnung der 14 Sektionen zu den Bereichen. Jede Zuordnung folgt der
 * Beschreibung in qaf-section-registry.ts, nicht dem Bauchgefühl:
 *  - form/buckets/bridge/metrics/movers/scenario/projection/anomalies lesen
 *    allesamt aus dem Zusammenfassungs-Blatt (die Registry sagt das je
 *    Eintrag) → Zusammenfassung.
 *  - prod: „Prozess-Parameter je Fertigungsschritt aus dem
 *    Fertigungskosten-Blatt" → Fertigungskosten.
 *  - onetime: Einmalzahlungen sind die Werkzeug-/Vorrichtungsseite → SBM.
 *  - negotiation/levers: Verhandlung und Gegenmaßnahmen → Qualität und
 *    Maßnahmen.
 *  - fazit: Management-Fazit ist Einstiegsmaterial → Überblick. */
export const PRIMARY_AREAS: readonly PrimaryArea[] = [
  {
    id: "ueberblick",
    label: "Überblick",
    modules: [],
    sections: ["overview", "fazit"],
  },
  {
    id: "zusammenfassung",
    label: "Zusammenfassung",
    modules: ["SUMMARY"],
    sections: [
      "form",
      "buckets",
      "bridge",
      "metrics",
      "anomalies",
      "movers",
      "scenario",
      "projection",
    ],
  },
  { id: "material", label: "Material", modules: ["MATERIAL"], sections: [] },
  {
    id: "fertigungskosten",
    label: "Fertigungskosten",
    modules: ["MANUFACTURING"],
    sections: ["prod"],
  },
  {
    id: "sbm",
    label: "SBM / Vorrichtungen (FWZ)",
    modules: ["SBM"],
    sections: ["onetime"],
  },
  {
    id: "logistik",
    label: "Logistik und Zoll",
    modules: ["LOGISTICS", "LC_CN"],
    sections: [],
  },
  {
    id: "rohstoffrisiken",
    label: "Rohstoffrisiken",
    modules: ["RMR"],
    sections: [],
  },
  {
    id: "zusatzmodule",
    label: "Zusatzmodule",
    modules: ["CO2E"],
    sections: [],
  },
  {
    id: "massnahmen",
    label: "Qualität und Maßnahmen",
    modules: [],
    sections: ["negotiation", "levers"],
  },
] as const

/** Der Reiter der Kompatibilitätsansicht. Kein Teil von PRIMARY_AREAS, damit
 *  „alle Bereiche" und „der Alles-Reiter" nicht durcheinandergehen. */
export const ALL_SECTIONS_TAB: PrimaryArea = {
  id: ALL_SECTIONS_AREA,
  label: "Alle Sektionen",
  modules: [],
  sections: [],
}

/** Status eines Moduls laut Capability-Matrix, auf die Frage reduziert, die
 *  die Navigation stellt: „gibt es hier etwas zu sehen?" */
function moduleIsPresent(
  coverage: readonly CoverageEntry[],
  module: string
): boolean {
  const entry = coverage.find((c) => c.module === module)
  if (!entry) return false
  /* PARSE_FAILED zählt als vorhanden: das Blatt IST da, es ließ sich nur nicht
   * lesen. Diesen Bereich zu verstecken würde einen echten Datenbestand
   * unsichtbar machen und den Fehler gleich mit — der Nutzer soll ihn sehen. */
  return (
    entry.status === "AVAILABLE" ||
    entry.status === "PARTIAL" ||
    entry.status === "DERIVABLE" ||
    entry.status === "PARSE_FAILED"
  )
}

/**
 * Vereinigt die Abdeckung beider Vergleichsseiten.
 *
 * Ein Bereich wird angeboten, sobald ihn EINE Seite trägt. Der Schnitt wäre
 * falsch: ein Modul, das nur im neuen Stand existiert, ist genau das, was ein
 * Vergleich zeigen soll — es zu verstecken, weil die andere Seite es nicht
 * hat, würde eine echte Änderung unsichtbar machen.
 *
 * Sind beide Seiten ohne erhobenen Stand, bleibt das Ergebnis `null`
 * („nie gemessen"), nicht die leere Liste („geprüft, nichts da").
 */
export function mergeCoverage(
  alt: readonly CoverageEntry[] | null,
  neu: readonly CoverageEntry[] | null
): CoverageEntry[] | null {
  if (alt === null && neu === null) return null
  const byModule = new Map<string, CoverageEntry>()
  for (const entry of [...(alt ?? []), ...(neu ?? [])]) {
    const bisher = byModule.get(entry.module)
    /* Der „stärkere" Stand gewinnt: vorhanden schlägt fehlend. Sonst würde
     * eine Seite mit MISSING einen echten Bestand der anderen überschreiben,
     * je nachdem welche zuerst kommt. */
    if (
      !bisher ||
      (!moduleIsPresent([bisher], entry.module) &&
        moduleIsPresent([entry], entry.module))
    ) {
      byModule.set(entry.module, entry)
    }
  }
  return [...byModule.values()]
}

/**
 * Welche Hauptreiter werden angeboten?
 *
 * `coverage === null` heißt „kein Capability-Stand erhoben" (Datei vor
 * KAR-959 oder fehlender Schlüssel) — NICHT „nichts vorhanden". In dem Fall
 * werden alle Bereiche angeboten, denn das Gegenteil würde eine nie
 * durchgeführte Messung als negatives Ergebnis ausgeben.
 */
export function visibleAreas(
  coverage: readonly CoverageEntry[] | null
): readonly PrimaryArea[] {
  if (coverage === null) return PRIMARY_AREAS
  return PRIMARY_AREAS.filter(
    (area) =>
      area.modules.length === 0 ||
      area.modules.some((m) => moduleIsPresent(coverage, m))
  )
}

/**
 * Löst `?bereich=` gegen die tatsächlich sichtbaren Reiter auf.
 *
 * Ein Bereich, den die Matrix ausgeblendet hat, ist per Deep-Link nicht
 * erzwingbar — sonst zeigte ein alter Link einen Reiter, den diese Datei gar
 * nicht trägt. Unbekannt, leer oder ausgeblendet fällt auf die
 * Kompatibilitätsansicht zurück, die alles zeigt.
 */
export function resolveActiveArea(
  raw: string | string[] | undefined,
  visible: readonly PrimaryArea[]
): string {
  if (raw === undefined) return ALL_SECTIONS_AREA
  const candidates = Array.isArray(raw) ? raw : [raw]
  for (const candidate of candidates) {
    if (candidate === ALL_SECTIONS_AREA) return ALL_SECTIONS_AREA
    if (visible.some((a) => a.id === candidate)) return candidate
  }
  return ALL_SECTIONS_AREA
}

/**
 * Ist diese Sektion im aktiven Bereich sichtbar?
 *
 * In der Kompatibilitätsansicht ist alles sichtbar — dort ändert Loop 8
 * nichts am Bestand.
 */
export function sectionVisible(
  activeArea: string,
  section: QafSectionKey
): boolean {
  if (activeArea === ALL_SECTIONS_AREA) return true
  const area = PRIMARY_AREAS.find((a) => a.id === activeArea)
  if (!area) return true
  return area.sections.includes(section)
}

/** Ziel eines Reiters — relativer Query-Link, behält die Vergleichs-URL. */
export function areaTabHref(id: string): string {
  return `?${PRIMARY_AREA_PARAM}=${id}`
}
