// Referenzfall der Anzeigeebene (Spezifikation Kap. 27, View-Phase V1; U-06).
//
// Wozu: Die V2-Anzeigeebene ist gebaut, aber noch an keine Datenquelle
// angeschlossen — es gibt in der App keinen Weg von zwei Dateien zu einem Lauf.
// Bis den Weg 1 der Integration liefert, ist dieser Fall die einzige
// Möglichkeit, die Ansichten überhaupt zu sehen und gegen U-01…U-08 abzunehmen.
//
// Zwei Entscheidungen prägen die Datei:
//
//   1. **Hier stehen Eingaben, keine Ergebnisse.** Die Kacheln, die Brücke und
//      die Zellnachweise entstehen aus `buildKpiTiles`, `buildWaterfall` und
//      `evidenceFor` — denselben Funktionen, die auch ein echter Lauf benutzt.
//      Hartkodierte Ergebnisse würden zeigen, was sich jemand ausgedacht hat,
//      statt was die Anzeigeebene tatsächlich tut.
//   2. **Zwei der drei Fälle zeigen absichtlich Unangenehmes.** Einer schliesst
//      nicht — die Eigenschaft, für die dieses Modul gebaut wurde: dass es sich
//      weigert zu zeichnen, wenn ein Betrag unerklärt bleibt (Befund F-01).
//      Der andere hat kleine Schritte auf hohem Niveau, die übliche Lage bei
//      einem echten QAF, in der die Brücke an ihre Darstellungsgrenze kommt.
//      Eine Referenzansicht, die nur den dankbaren Fall zeigt, ist Werbung.
//
// FIXTURE-DATEN-REGEL: jeder Name, jede Zahl, jeder Blatt- und Zellbezug unten
// ist freie Erfindung. Diese Datei wird mit ausgeliefert; ein anonymisierter
// Abzug eines echten Laufs hat hier nichts zu suchen.

import { buildKpiTiles, evidenceFor, validationBanner } from './view-specs'
import type { EvidenceRow, KpiTile, KpiTileInput, ValidationBanner } from './view-specs'
import { buildWaterfall } from './chart-specs'
import type { WaterfallInput, WaterfallSpec } from './chart-specs'
import type { DifferenceRecord } from './all-differences'
import type { DqFinding } from './data-quality'
// Seit Loop 4 leben beide Typen framework-frei im lib-Kern (die Header-
// Komponente aliasiert) — der frühere components-Import war die einzige
// lib→components-Kante und ist damit aufgelöst.
import type { ComparabilityStatus } from './comparability'
import type { DeclaredComparisonType as ComparisonType } from './declared-comparison-type'

export interface ReferenceCase {
  key: string
  labelDe: string
  /** Wozu dieser Fall da ist — steht in der Ansicht über der Sektion. */
  purposeDe: string
  partLabelDe: string
  supplierLabelDe: string | null
  comparisonType: ComparisonType
  comparability: ComparabilityStatus
  comparabilityReasonsDe: string[]
  files: Array<{ roleDe: string; nameDe: string; stampDe: string | null }>
  contentHash: string | null
  failedChecks: string[]
  kpiInputs: KpiTileInput[]
  waterfall: WaterfallInput
  records: DifferenceRecord[]
  findings: DqFinding[]
  /** Zeile, deren Zellnachweis in der Ansicht aufgeklappt gezeigt wird. */
  evidenceForId: string
}

const STÜCKPREIS_VERGABE = 2.46
const STÜCKPREIS_AKTUELL = 3.53
const GESAMTVOLUMEN = 840_000

// Die Schritte summieren sich exakt auf die Differenz der beiden Stände.
// Wäre das nicht so, zeichnete die Brücke nichts — genau das zeigt der dritte
// Fall weiter unten.
const SCHRITTE = [
  { key: 'material', labelDe: 'Material', delta: -0.58, differenceIds: ['MAT-0001'] },
  { key: 'fertigung', labelDe: 'Fertigung', delta: 1.24, differenceIds: ['MFG-0001'] },
  { key: 'werkzeug', labelDe: 'Werkzeugumlage', delta: 0.52, differenceIds: ['SBM-0001'] },
  { key: 'logistik', labelDe: 'Logistik', delta: -0.11, differenceIds: ['SUM-0002'] },
]

// Derselbe Aufbau, aber kleine Schritte auf hohem Niveau — der Fall, in dem die
// Brücke an ihre Grenze kommt. Er steht bewusst daneben: Eine Referenzansicht,
// die nur die günstige Grössenordnung zeigt, verschweigt, wie die Darstellung
// bei realen Stückpreisen mit wenigen Prozent Veränderung aussieht.
const SCHRITTE_FLACH = [
  { key: 'material', labelDe: 'Material', delta: 2.84, differenceIds: ['MAT-0001'] },
  { key: 'fertigung', labelDe: 'Fertigung', delta: 1.37, differenceIds: ['MFG-0001'] },
  { key: 'werkzeug', labelDe: 'Werkzeugumlage', delta: 0.68, differenceIds: ['SBM-0001'] },
  { key: 'logistik', labelDe: 'Logistik', delta: -0.16, differenceIds: ['SUM-0002'] },
]

const zelle = (
  fileRole: 'award' | 'current',
  sheet: string,
  cell: string,
  formula: string | null,
  valueState: DifferenceRecord['cells'][number]['valueState'] = 'formula_and_cached',
) => ({ fileRole, sheet, cell, formula, valueState })

const RECORDS: DifferenceRecord[] = [
  {
    differenceId: 'MAT-0001',
    area: 'MAT',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Dichtring: Einstandspreis gesunken',
    valueAward: 1.02,
    valueCurrent: 0.44,
    delta: -0.58,
    deltaNullReason: null,
    unit: 'EUR_per_piece',
    cells: [
      zelle('award', 'MATERIAL', 'K10', '=H10*J10'),
      zelle('current', 'MATERIAL', 'K10', '=H10*J10'),
    ],
    relatedDq: [],
    anchorRow: 10,
  },
  {
    differenceId: 'MFG-0001',
    area: 'MFG',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Station 40: Zykluszeit und Stundensatz angepasst',
    valueAward: 0.61,
    valueCurrent: 1.85,
    delta: 1.24,
    deltaNullReason: null,
    unit: 'EUR_per_piece',
    cells: [
      zelle('award', 'FERTIGUNG', 'M22', '=L22*N22/3600'),
      zelle('current', 'FERTIGUNG', 'M22', '=L22*N22/3600'),
    ],
    relatedDq: ['DQ-0007'],
    anchorRow: 22,
  },
  {
    differenceId: 'SBM-0001',
    area: 'SBM',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Werkzeugumlage: Zweitwerkzeug hinzugekommen',
    valueAward: 0.29,
    valueCurrent: 0.81,
    delta: 0.52,
    deltaNullReason: null,
    unit: 'EUR_per_piece',
    cells: [
      zelle('award', 'SBM-Werkzeuge', 'AP31', null, 'constant'),
      zelle('current', 'SBM-Werkzeuge', 'AP31', '=AN31/AO31'),
    ],
    relatedDq: [],
    anchorRow: 31,
  },
  {
    differenceId: 'SUM-0002',
    area: 'SUM',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Logistikpauschale gesenkt',
    valueAward: 0.54,
    valueCurrent: 0.43,
    delta: -0.11,
    deltaNullReason: null,
    unit: 'EUR_per_piece',
    cells: [zelle('award', 'SUMMARY', 'D18', null, 'constant'), zelle('current', 'SUMMARY', 'D18', null, 'constant')],
    relatedDq: [],
    anchorRow: 18,
  },
  {
    differenceId: 'SUM-0001',
    area: 'SUM',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Stückpreis gesamt',
    valueAward: STÜCKPREIS_VERGABE,
    valueCurrent: STÜCKPREIS_AKTUELL,
    delta: STÜCKPREIS_AKTUELL - STÜCKPREIS_VERGABE,
    deltaNullReason: null,
    unit: 'EUR_per_piece',
    cells: [
      zelle('award', 'SUMMARY', 'D42', '=SUMME(D10:D40)'),
      zelle('current', 'SUMMARY', 'D42', '=SUMME(D10:D40)'),
    ],
    relatedDq: [],
    anchorRow: 42,
  },
  {
    differenceId: 'SBM-0002',
    area: 'SBM',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Einmalzahlungen Werkzeuge gesamt',
    valueAward: 240_000,
    valueCurrent: 252_000,
    delta: 12_000,
    deltaNullReason: null,
    unit: 'EUR',
    cells: [
      zelle('award', 'SBM-Werkzeuge', 'AP88', '=SUMME(AP10:AP80)'),
      zelle('current', 'SBM-Werkzeuge', 'AP88', '=SUMME(AP10:AP80)'),
    ],
    relatedDq: [],
    anchorRow: 88,
  },
  {
    differenceId: 'MFG-0002',
    area: 'MFG',
    kind: 'changed',
    formulaFindingKind: null,
    descriptionDe: 'Taktzeit der Hauptlinie',
    valueAward: 33.04,
    valueCurrent: 31.8,
    delta: -1.24,
    deltaNullReason: null,
    unit: 'seconds',
    cells: [
      zelle('award', 'FERTIGUNG', 'F94', '=MAX(F10:F90)'),
      zelle('current', 'FERTIGUNG', 'F94', '=MAX(F10:F90)'),
    ],
    relatedDq: [],
    anchorRow: 94,
  },
]

const FINDINGS: DqFinding[] = [
  {
    findingId: 'DQ-0007',
    detector: 'D07',
    scope: 'current',
    context: 'cost_path',
    severity: 'medium',
    descriptionDe: 'Gruppensumme weicht um mehr als einen Cent von den Einzelzeilen ab.',
    recommendationDe: 'Die Zwischensumme der Stationsgruppe gegen die Einzelzeilen prüfen.',
    affectedCells: [{ fileRole: 'current', sheet: 'FERTIGUNG', cell: 'M22' }],
    relatedDifferenceIds: ['MFG-0001'],
  },
]

const KPI_INPUTS: KpiTileInput[] = [
  {
    key: 'stueckpreis',
    labelDe: 'Stückpreis',
    valueAward: STÜCKPREIS_VERGABE,
    valueCurrent: STÜCKPREIS_AKTUELL,
    unit: 'EUR_per_piece',
    path: 'summary.piece_price',
    differenceIds: ['SUM-0001'],
  },
  {
    key: 'lifetime',
    labelDe: 'Lifetime-Wirkung',
    valueAward: STÜCKPREIS_VERGABE * GESAMTVOLUMEN,
    valueCurrent: STÜCKPREIS_AKTUELL * GESAMTVOLUMEN,
    unit: 'EUR',
    path: 'summary.lifetime',
    differenceIds: ['SUM-0001'],
    formulaNoteDe: 'Δ × Gesamtvolumen — Bewertungsgröße, keine bestätigte Einsparung',
  },
  {
    key: 'einmalzahlung',
    labelDe: 'Einmalzahlungen',
    valueAward: 240_000,
    valueCurrent: 252_000,
    unit: 'EUR',
    path: 'tooling.one_time',
    differenceIds: ['SBM-0002'],
  },
  {
    key: 'takt',
    labelDe: 'Taktzeit',
    valueAward: 33.04,
    valueCurrent: 31.8,
    unit: 'seconds',
    path: 'manufacturing.takt',
    differenceIds: ['MFG-0002'],
  },
  {
    key: 'volumen',
    labelDe: 'Jahresvolumen',
    valueAward: 120_000,
    valueCurrent: 120_000,
    unit: 'pieces',
    path: 'summary.annual_volume',
    differenceIds: [],
  },
]

/** Der Fall, an dem die Ansicht ihren Normalzustand zeigt. */
export const REFERENCE_CASE_OK: ReferenceCase = {
  key: 'schliesst',
  labelDe: 'Referenzfall — Brücke schliesst',
  purposeDe:
    'Der Normalfall: die Schritte erklären die Differenz vollständig, die Brücke wird gezeichnet.',
  partLabelDe: 'Baugruppe Muster A · 000 000 000',
  supplierLabelDe: 'Beispiellieferant Nord',
  comparisonType: 'temporal_change',
  comparability: 'comparable',
  comparabilityReasonsDe: [],
  files: [
    { roleDe: 'Vergabestand', nameDe: 'muster-a-vergabe.xlsx', stampDe: '05.07.2022' },
    { roleDe: 'Aktueller Stand', nameDe: 'muster-a-aktuell.xlsx', stampDe: '01.04.2026' },
  ],
  contentHash: 'sha256:4f1c8b02e7a9d3550c61',
  failedChecks: [],
  kpiInputs: KPI_INPUTS,
  waterfall: {
    startLabelDe: 'Vergabestand',
    endLabelDe: 'Aktueller Stand',
    start: STÜCKPREIS_VERGABE,
    end: STÜCKPREIS_AKTUELL,
    steps: SCHRITTE,
    residual: 0,
  },
  records: RECORDS,
  findings: FINDINGS,
  evidenceForId: 'MFG-0001',
}

/**
 * Der Fall, an dem die Ansicht ihre wichtigste Eigenschaft zeigt.
 *
 * Ein Schritt fehlt, also bleibt ein Betrag unerklärt. Die Brücke wird nicht
 * gezeichnet, und zusätzlich sind zwei Prüfungen des Kerns fehlgeschlagen —
 * das Banner steht, und mit ihm ist die KI-Zusammenfassung gesperrt.
 */
export const REFERENCE_CASE_BROKEN: ReferenceCase = {
  ...REFERENCE_CASE_OK,
  key: 'schliesst-nicht',
  labelDe: 'Referenzfall — Brücke schliesst nicht',
  purposeDe:
    'Ein Schritt fehlt, 1,3700 EUR bleiben unerklärt. Statt eines Balkens „Übrige" zeigt die Ansicht die Diagnose — und das Banner sperrt die Zusammenfassung.',
  comparability: 'undetermined',
  comparabilityReasonsDe: ['Stückzahlbezug beider Stände nicht bestätigt'],
  failedChecks: ['P-03 Brückenrest über Toleranz', 'P-07 Einheit der Sektion fehlt'],
  waterfall: {
    ...REFERENCE_CASE_OK.waterfall,
    steps: SCHRITTE.filter((s) => s.key !== 'fertigung'),
    residual: null,
  },
}

/**
 * Der Fall, in dem die Darstellung an ihre Grenze kommt.
 *
 * Ein Stückpreis von 87 EUR, der sich um 5 % ändert — die übliche Lage bei
 * einem echten QAF. Auf einer Skala, die bei null beginnt, sind solche Schritte
 * nur noch Linien. Dieser Fall steht bewusst neben dem günstigen: Eine
 * Referenzansicht, die nur die dankbare Grössenordnung zeigt, verschweigt, wie
 * die Brücke in der Praxis meistens aussieht.
 */
export const REFERENCE_CASE_FLAT: ReferenceCase = {
  ...REFERENCE_CASE_OK,
  key: 'flach',
  labelDe: 'Referenzfall — kleine Schritte auf hohem Niveau',
  purposeDe:
    'Ein Stückpreis von 87,42 EUR, der um 5 % steigt. Die Stände stehen im richtigen Verhältnis, die Schritte werden dafür zu Linien mit Wertangabe — die Grenze jeder Brücke, die bei null beginnt.',
  waterfall: {
    startLabelDe: 'Vergabestand',
    endLabelDe: 'Aktueller Stand',
    start: 87.42,
    end: 92.15,
    steps: SCHRITTE_FLACH,
    residual: 0,
  },
  kpiInputs: KPI_INPUTS.map((k) =>
    k.key === 'stueckpreis'
      ? { ...k, valueAward: 87.42, valueCurrent: 92.15 }
      : k.key === 'lifetime'
        ? { ...k, valueAward: 87.42 * GESAMTVOLUMEN, valueCurrent: 92.15 * GESAMTVOLUMEN }
        : k,
  ),
}

export const REFERENCE_CASES: readonly ReferenceCase[] = [
  REFERENCE_CASE_OK,
  REFERENCE_CASE_FLAT,
  REFERENCE_CASE_BROKEN,
]

export interface ReferenceView {
  case: ReferenceCase
  tiles: KpiTile[]
  waterfall: WaterfallSpec
  validation: ValidationBanner
  evidence: EvidenceRow[]
}

/**
 * Den Fall durch die echten Bauer schicken.
 *
 * Bewusst kein eigener Rechenweg: Was die Ansicht zeigt, soll das sein, was
 * `buildKpiTiles`, `buildWaterfall` und `evidenceFor` aus diesen Eingaben
 * machen — sonst prüft die Referenzansicht sich selbst statt der Anzeigeebene.
 */
export function buildReferenceView(fall: ReferenceCase): ReferenceView {
  const record = fall.records.find((r) => r.differenceId === fall.evidenceForId)

  return {
    case: fall,
    tiles: buildKpiTiles(fall.kpiInputs, fall.records),
    waterfall: buildWaterfall(fall.waterfall),
    validation: validationBanner(fall.failedChecks),
    evidence: record === undefined ? [] : evidenceFor(record, fall.findings),
  }
}
