// Central bilingual (DE/EN) plain-language label maps for internal machine
// codes the Multi-QAF engine persists (KAR-950 — Multi-QAF Detail-UI
// Aufräum-Pass, task item 6/7). Presentation-layer only: every map here
// translates an already-persisted `code`/`gate`/`reason`/`checkId` string
// into a short, jargon-free sentence for the visible UI — it never changes
// WHAT the engine computed, only HOW it reads. The engine's own raw
// message/messageDe/messageEn strings (which sometimes embed source file
// names like "variant-matcher.ts" or "differ.ts/computeNumericDelta" for
// internal traceability, e.g. aggregate-impact.ts's own `assumptions`/
// `excludedVariants` messages) are never rendered verbatim in the visible
// UI flow any more — callers pass them as a `title` attribute instead
// (still inspectable/greppable in the DOM, never part of the readable
// flow text — task requirement: "Quellcode-Dateinamen niemals im
// sichtbaren UI-Fließtext").
//
// Every map has a safe, non-crashing fallback for a code this file does not
// (yet) know — see `labelFor` below — so a future engine-side code addition
// degrades to "raw code, still visible" instead of a runtime error or a
// silently blank label.
// tdd-guard:skip — static label data + trivial lookup helpers, no business logic.

import type {
  AggregateImpactExclusionReason,
  AggregateImpactGateId,
  VariantReconciliationCheckId,
  VariantReconciliationNichtPruefbarReason,
} from '@/lib/qaf-differences'

export interface BilingualLabel {
  de: string
  en: string
}

/** Generic, safe lookup: known code -> curated label, unknown code -> the
 * raw code itself echoed as both DE/EN (never crashes, never blank —
 * mirrors `variantLabel`'s/`UnavailableNotice`'s "defensive, never hide"
 * convention elsewhere in this package). */
export function labelFor(map: Record<string, BilingualLabel>, code: string): BilingualLabel {
  return map[code] ?? { de: code, en: code }
}

/** Same safe-fallback discipline as `labelFor` above, specialized for
 * `GATE_LABEL` (which — unlike the other maps here — carries an extra
 * `description` field per entry). `AggregateImpactGateOutcome.gate` is typed
 * as the closed `AggregateImpactGateId` union, but a PERSISTED result can
 * still carry a gate id that union no longer has (an older/renamed engine
 * build) — TypeScript's static guarantee does not hold for data read back
 * out of storage. An unrecognized gate falls back to the raw code as its own
 * DE/EN label (still visible, never a crash) with `description: null` — the
 * caller renders the raw code in place of a description it does not have,
 * rather than fabricating one (KAR-950 review finding 1). */
export function gateLabelFor(gate: string): BilingualLabel & { description: BilingualLabel | null } {
  const entry = (GATE_LABEL as Record<string, BilingualLabel & { description: BilingualLabel }>)[gate]
  return entry ?? { de: gate, en: gate, description: null }
}

// ── Section 1 — container warning codes (KAR-950 item 2) ───────────────────
//
// Every code that can actually reach `MultiQafContainer.warnings` (traced via
// container-assembly.ts's own `warnings.push(...)` call sites — material-
// matrix-parser.ts/profile-parser.ts/formula-lineage.ts/identity.ts all funnel
// into that one array; material-differ.ts/aggregate-impact.ts warnings do NOT
// — those are diff-/impact-level, not container-level, and never appear here).
export const WARNING_CODE_LABEL: Record<string, BilingualLabel> = {
  material_variant_unmatched_to_summary: {
    de: 'Detail-Spalten konnten keiner Varianten-Identität zugeordnet werden — ihre Materialdaten sind von der Aggregation ausgeschlossen.',
    en: 'Detail columns could not be matched to any variant identity — their material data is excluded from aggregation.',
  },
  material_variant_fuzzy_matched_to_summary: {
    de: 'Detail-Spalten wurden per Fuzzy-Matching einer Varianten-Identität zugeordnet — bitte prüfen.',
    en: 'Detail columns were matched to a variant identity via fuzzy matching — please verify.',
  },
  material_variant_fuzzy_match_below_aggregation_gate: {
    de: 'Detail-Spalten haben einen Fuzzy-Match-Kandidaten unterhalb der Mindestanforderung für automatische Kosten-Zuordnung — Materialdaten NICHT übernommen.',
    en: 'Detail columns have a fuzzy-match candidate below the minimum bar for automatic cost aggregation — material data NOT carried forward.',
  },
  material_matrix_row_identity_collision: {
    de: 'Material-Zeilen teilen sich Positionsnummer + Bezeichnung — Identität um eine Kollisions-Ordinalzahl erweitert, damit beide Zeilen unterscheidbar bleiben.',
    en: 'Material rows share position number + designation — identity suffixed with a collision ordinal so both rows stay distinguishable.',
  },
  material_matrix_reconciliation_mismatch: {
    de: 'Varianten mit abweichender SUMPRODUCT-Rekonziliation zwischen Material-Matrix und Summary.',
    en: 'Variants with a SUMPRODUCT reconciliation mismatch between the material matrix and the Summary.',
  },
  material_matrix_reconciliation_not_verifiable: {
    de: 'Varianten mit nicht prüfbarer SUMPRODUCT-Rekonziliation.',
    en: 'Variants with a non-verifiable SUMPRODUCT reconciliation.',
  },
  material_matrix_no_matched_variant_identity: {
    de: 'Material-/BOM-Sheet: keine seiner Varianten konnte einer Summary-Identität zugeordnet werden — Materialzeilen extrahiert, aber keiner Variante zugeordnet.',
    en: 'Material/BOM sheet: none of its variants could be matched to a Summary identity — material rows extracted but attributed to no variant.',
  },
  material_matrix_variant_never_referenced: {
    de: 'Varianten, die von keiner einzigen Materialzeile referenziert werden — Materialkosten gelten als „nicht ermittelbar", nicht als „nicht anwendbar".',
    en: 'Variants not referenced by a single material row — material costs count as "undeterminable", not "not applicable".',
  },
  material_matrix_no_variant_identity: {
    de: 'Material-/BOM-Sheet gefunden, aber kein eigener Varianten-Header-Block identifizierbar — Material-Matrix nicht extrahiert.',
    en: 'Material/BOM sheet found, but no variant header block of its own could be identified — material matrix not extracted.',
  },
  material_sheet_not_found: {
    de: 'Kein Material-/BOM-Sheet im Workbook gefunden — geteilte Material-Matrix bleibt leer.',
    en: 'No material/BOM sheet found in the workbook — shared material matrix stays empty.',
  },
  material_matrix_header_not_found: {
    de: 'Keine auswertbare Material-Matrix-Kopfzeile gefunden — Sheet nicht als Material-Matrix behandelt.',
    en: 'No usable material-matrix header row found — sheet not treated as a material matrix.',
  },
  material_matrix_padding_rows_skipped: {
    de: 'Leere Padding-Zeilen ohne Positionsnummer übersprungen (harmloser, dokumentierter Realfall).',
    en: 'Empty padding rows without a position number were skipped (a documented, harmless real-file pattern).',
  },
  material_matrix_total_row_excluded: {
    de: 'Summen-/Total-Zeilen erkannt und von der Materialzeilen-Extraktion ausgeschlossen.',
    en: 'Total/summary rows recognized and excluded from material-row extraction.',
  },
  material_matrix_scan_truncated: {
    de: 'Material-Matrix-Scan am Fenster-Ende abgebrochen — Ergebnis vorsorglich als unvollständig markiert.',
    en: 'Material-matrix scan stopped at the scan window edge — result conservatively marked as incomplete.',
  },
  formula_column_range_inconsistency: {
    de: 'Kontrollspalten für den Mengenfaktor sind inkonsistent (Template-Formel-Inkonsistenz) — nicht als Zielwert übernommen.',
    en: 'Control columns for the quantity factor are inconsistent (a template formula inconsistency) — not adopted as the target value.',
  },
  manufacturing_summary_row_not_found: {
    de: 'Keine Fertigungskosten-Zeile im Summary-Sheet gefunden — Varianten-Profil-Bindung übersprungen.',
    en: 'No manufacturing-cost row found in the Summary sheet — variant/profile binding resolution skipped.',
  },
  variant_profile_binding_summary_columns_unavailable: {
    de: 'Fertigungskosten-Profil-Bindung konnte nicht sicher auf Summary-Spalten abgebildet werden.',
    en: 'Manufacturing-cost profile binding could not be reliably mapped onto Summary columns.',
  },
  variant_profile_binding_unresolved: {
    de: 'Fertigungs-/Rüstkosten-Profilbindung für eine Variante nicht auflösbar.',
    en: 'Manufacturing/setup-cost profile binding could not be resolved for a variant.',
  },
  ambiguous_literal_profile_binding: {
    de: 'Ein Literalwert passt gleich gut zu mehreren Profil-Totalen — Bindung mehrdeutig.',
    en: 'A literal value fits equally well to several profile totals — binding ambiguous.',
  },
  hidden_sheet_reachability_unknown: {
    de: 'Verstecktes Sheet mit Profil-Struktur — ob es referenziert wird, ist nicht prüfbar (konservativ ausgeschlossen).',
    en: 'Hidden sheet with profile structure — whether it is referenced could not be checked (conservatively excluded).',
  },
  orphaned_hidden_sheet: {
    de: 'Verstecktes Sheet mit Profil-Struktur, aber von keiner Summary-Formel referenziert — als Orphan ausgeschlossen.',
    en: 'Hidden sheet with profile structure, never referenced by a Summary formula — excluded as an orphan.',
  },
  lineage_reachability_unknown_conservative_include: {
    de: 'Sheet-Erreichbarkeit nicht beweisbar — konservativ als Profil-Kandidat einbezogen statt verworfen.',
    en: 'Sheet reachability could not be proven — conservatively included as a profile candidate instead of dropped.',
  },
  canonical_key_collision: {
    de: 'Mehrere Varianten teilen sich dieselbe Identität (Kollision) — nicht automatisch aufgelöst.',
    en: 'Several variants share the same identity (collision) — not auto-resolved.',
  },
  mixed_currency_material_costs: {
    de: 'Materialkosten mischen Währungen — kein Gesamt-Materialkosten-Total gebildet.',
    en: 'Material costs mix currencies — no aggregate material-cost total was formed.',
  },
  mixed_currency_total_production_costs: {
    de: 'Material- und Fertigungskosten verwenden unterschiedliche Währungen — kein Gesamt-Produktionskosten-Total gebildet.',
    en: 'Material and manufacturing costs use different currencies — no total production cost was formed.',
  },
  formula_cell_scan_guard_triggered: {
    de: 'Formel-Zellen-Scan-Grenze erreicht — Scan vorzeitig gestoppt, Lineage für den Rest unvollständig.',
    en: 'Formula-cell scan guard reached — scan stopped early, lineage for the remainder is incomplete.',
  },
  range_truncated: {
    de: 'Scan-Fenster erreicht — reale Inhalte könnten darüber hinausgehen, Lineage jenseits davon unbekannt.',
    en: 'Scan window reached — real content may extend further, lineage beyond it unknown.',
  },
  external_reference_not_followed: {
    de: 'Externe Verknüpfung gefunden, aber nicht aufgelöst (aus Sicherheitsgründen nie gefolgt).',
    en: 'External reference found, but not resolved (never followed, for safety reasons).',
  },
  lineage_cycle_detected: {
    de: 'Zirkelbezug in der Formel-Lineage entdeckt.',
    en: 'A cycle was detected while tracing formula lineage.',
  },
  lineage_depth_limit_reached: {
    de: 'Formel-Lineage-Tiefenlimit erreicht — die Kette dahinter wurde nicht weiterverfolgt.',
    en: 'Formula-lineage depth limit reached — the chain beyond it was not followed further.',
  },
  no_summary_sheet_found: {
    de: 'Kein SUMMARY-/Zusammenfassung-Sheet gefunden — Formel-Lineage-Graph bleibt leer.',
    en: 'No SUMMARY sheet found — the formula-lineage graph stays empty.',
  },
}

// ── Section 6 — Rekonziliation je Variante (KAR-950 item 4) ────────────────

export const RECONCILIATION_CHECK_LABEL: Record<VariantReconciliationCheckId, BilingualLabel> = {
  currency: { de: 'Währung', en: 'Currency' },
  volumes: { de: 'Volumina', en: 'Volumes' },
  material_total_detail_to_summary: { de: 'Material-Summe (Detail → Summary)', en: 'Material total (detail → Summary)' },
  material_total_matrix_independent: { de: 'Material-Summe (unabhängig, Matrix)', en: 'Material total (independent, matrix)' },
  manufacturing_total: { de: 'Fertigungskosten-Summe', en: 'Manufacturing cost total' },
  setup_cost_allocation: { de: 'Rüstkosten-Allokation', en: 'Setup cost allocation' },
  tooling_fixture_cost: { de: 'Werkzeug-/Vorrichtungskosten', en: 'Tooling/fixture cost' },
  scrap: { de: 'Ausschuss', en: 'Scrap' },
  surcharges: { de: 'Zuschläge/Overhead', en: 'Surcharges/overhead' },
  offer_base_price: { de: 'Angebotsbasispreis', en: 'Offer base price' },
  offer_price: { de: 'Angebotspreis', en: 'Offer price' },
  total_production_costs_cascade: { de: 'Summe Herstellkosten (Kaskade)', en: 'Total production costs (cascade)' },
  formula_identity_material_rows: { de: 'Formel-Identität Materialzeilen', en: 'Formula identity, material rows' },
  formula_identity_profiles: { de: 'Formel-Identität Profile', en: 'Formula identity, profiles' },
}

export const NICHT_PRUEFBAR_REASON_LABEL: Record<VariantReconciliationNichtPruefbarReason, BilingualLabel> = {
  fehlende_daten: { de: 'fehlende Daten', en: 'missing data' },
  same_source_no_independent_check: { de: 'gleiche Quelle, kein unabhängiger Gegencheck', en: 'same source, no independent check' },
  mixed_currency: { de: 'gemischte Währungen', en: 'mixed currencies' },
  unmatched_variant: { de: 'Variante nicht gematcht', en: 'variant not matched' },
  fingerprint_unavailable: { de: 'Struktur-Fingerabdruck nicht verfügbar', en: 'structural fingerprint unavailable' },
}

// ── Section 3 — Container-Struktur review reasons (KAR-950 item 6) ─────────

export const REVIEW_REASON_LABEL: Record<string, BilingualLabel> = {
  alt_container_review_required: { de: 'ALT-Datei braucht eigene Review', en: 'ALT file needs its own review' },
  neu_container_review_required: { de: 'NEU-Datei braucht eigene Review', en: 'NEU file needs its own review' },
  uncertain_variant_matches_present: { de: 'unsichere Varianten-Zuordnungen vorhanden', en: 'uncertain variant matches present' },
  caller_override: { de: 'manuell erzwungen', en: 'manually forced' },
}

// ── Section 7 — Aggregat-Impact gates + exclusions (KAR-950 item 6) ────────

export const GATE_LABEL: Record<AggregateImpactGateId, BilingualLabel & { description: BilingualLabel }> = {
  compatible_currencies: {
    de: 'Kompatible Währungen',
    en: 'Compatible currencies',
    description: { de: 'Alle einbezogenen Varianten haben eine bekannte, kompatible Währung.', en: 'Every included variant has a known, compatible currency.' },
  },
  volumes_available: {
    de: 'Volumen vorhanden',
    en: 'Volumes available',
    description: { de: 'Für die Hochrechnung wird ein Jahres-/Lifetime-Volumen benötigt.', en: 'The projection needs an annual/lifetime volume to be present.' },
  },
  no_duplicates_or_ambiguous: {
    de: 'Keine Duplikate/Unsicherheiten',
    en: 'No duplicates/ambiguities',
    description: { de: 'Keine unsicheren (ambiguous/split/merge) Varianten-Zuordnungen im Ergebnis.', en: 'No uncertain (ambiguous/split/merge) variant matches in the result.' },
  },
  consistent_units: {
    de: 'Konsistente Einheiten',
    en: 'Consistent units',
    description: { de: 'Die Währungs-Prüfung je Variante ist tatsächlich verifiziert, nicht nur unbestätigt.', en: 'The per-variant currency check is actually verified, not merely unconfirmed.' },
  },
  valid_baseline: {
    de: 'Valide Baseline',
    en: 'Valid baseline',
    description: { de: 'Beide Container sind frei von eigenen Review-Findern, die eine Baseline in Frage stellen.', en: 'Both containers are free of their own review findings that would call a baseline into question.' },
  },
  no_blocked_critical_mappings: {
    de: 'Keine blockierten Zuordnungen',
    en: 'No blocked mappings',
    description: { de: 'Keine gematchte Variante referenziert eine geblockte kritische Zuordnung.', en: 'No matched variant references a blocked critical mapping.' },
  },
}

export const EXCLUSION_REASON_LABEL: Record<AggregateImpactExclusionReason, BilingualLabel> = {
  ambiguous_or_uncertain_match: { de: 'unsichere Varianten-Zuordnung', en: 'uncertain variant match' },
  blocked_critical_mapping: { de: 'geblockte kritische Zuordnung', en: 'blocked critical mapping' },
  inconsistent_units: { de: 'inkonsistente Einheiten', en: 'inconsistent units' },
  consistent_units_not_verifiable: { de: 'Einheiten-Konsistenz nicht prüfbar', en: 'unit consistency not verifiable' },
  volume_missing_annual: { de: 'Jahres-Volumen fehlt', en: 'annual volume missing' },
  volume_missing_lifetime: { de: 'Lifetime-Volumen fehlt', en: 'lifetime volume missing' },
}

/** `AggregateImpactAssumption.code` is a plain `string` (not a closed union)
 * on the engine side (aggregate-impact.ts) — this map covers every code that
 * module's own pure functions currently produce; an unknown future code
 * safely falls back to the raw engine `messageDe`/`messageEn` via the
 * caller's own fallback branch (see AggregateSection in qaf-multi-qaf-
 * detail.tsx), never to a blank/crashing render. */
export const ASSUMPTION_LABEL: Record<string, BilingualLabel> = {
  sign_convention: {
    de: 'Ein positiver Betrag bedeutet Verteuerung ALT→NEU, ein negativer Betrag eine Ersparnis.',
    en: 'A positive amount means a cost increase from ALT to NEU, a negative amount a saving.',
  },
  volume_and_currency_basis: {
    de: 'Volumen/Währung werden von der NEU-Seite gelesen — eine echte Volumen-/Währungsänderung ist ein eigener, separater Befund.',
    en: 'Volume/currency are read from the NEU side — a genuine volume/currency change is its own separate finding.',
  },
  material_included: {
    de: 'Material-Impacts sind eingeschlossen, sofern Faktor und Währung unverändert und die Zeile nicht review-relevant ist.',
    en: 'Material impacts are included where the factor and currency are unchanged and the row is not review-relevant.',
  },
  manufacturing_included_where_currency_valid: {
    de: 'Fertigungs-Deltas sind eingeschlossen, wo die Varianten-Währung ALT=NEU bekannt ist.',
    en: 'Manufacturing deltas are included where the variant currency ALT=NEU is known.',
  },
  no_matched_variants: {
    de: 'Keine gematchten Varianten — das Aggregat ist leer, der unweighted Struktur-Vergleich bleibt verfügbar.',
    en: 'No matched variants — the aggregate is empty, the unweighted structural comparison stays available.',
  },
  review_relevant_rows_excluded: {
    de: 'Mindestens eine review-relevante Material-Zeile wurde aus der Summe ausgeschlossen.',
    en: 'At least one review-relevant material row was excluded from the sum.',
  },
  aggregate_suppressed_baseline_invalid: {
    de: 'Die Aggregat-Zahl wurde unterdrückt, weil die Baseline-Prüfung nicht bestanden und nicht bestätigt wurde.',
    en: 'The aggregate figure was suppressed because the baseline check failed and was not acknowledged.',
  },
  aggregate_computed_despite_review: {
    de: 'Das Aggregat wurde trotz blockierendem Review-Zustand berechnet (bestätigt).',
    en: 'The aggregate was computed despite a blocking review state (acknowledged).',
  },
}
