// Loop 10 View-Spec-Adoption, Modul 2 (Maßnahmen/SBM): Verhandlungs-Listen
// und Einmalzahlungen mit nachschlagbarer Herkunft.
//
// Muster wie overview-run.ts: ein pures Builder-Modul, das die bestehenden,
// geprüften Fachfunktionen (buildNegotiation, buildOneTimeRows,
// sumOneTimeDeltas — summary-view.ts) NICHT neu rechnet, sondern ihre Zeilen
// um `SourceRef`-Belege aus dem Differenzkatalog anreichert (U-02: keine
// Anzeigezahl ohne Verweis in den Kern) und die bisher in der Schale
// gebaute Facts-Zeile der Einmalzahlungen hierher zieht (die Anzeige zählt
// und formuliert nicht mehr selbst).
//
// Die ZAHLEN kommen weiterhin aus denselben qaf_summary_diff-Zeilen wie
// bisher (keine stille Quellen-Umstellung in diesem Schritt); nur die
// HERKUNFT kommt aus dem Katalog des Laufs (run.summaryRecords +
// summaryDifferenceIdsByMetricKey, beides von buildOverviewRun exponiert).
// Die Ein-Quellen-Konsolidierung — buildNegotiation & Co. komplett auf
// run.summaryDiffs statt der Roh-Zeilen umziehen — ist Teil des
// Zusammenfassungs-Moduls (view-spec-adoption-analyse.md, Modul 5), nicht
// dieses Schritts.
//
// Pure Funktionen, keine I/O.

import type { DifferenceRecord } from './all-differences'
import type { SummaryMetricKey } from './summary-metrics'
import type { SourceRef } from './view-specs'
import {
  buildNegotiation,
  buildOneTimeRows,
  sumOneTimeDeltas,
  type NegotiationRow,
  type OneTimeRow,
  type SummaryDiffRowData,
} from './summary-view'
import { deltaPhrase, unchangedPhrase } from './section-titles'

export interface NegotiationRowSpec extends NegotiationRow {
  sourceRef: SourceRef
}

export interface OneTimeRowSpec extends OneTimeRow {
  sourceRef: SourceRef
}

export interface NegotiationRun {
  /** Kostensenkungen (Top 3) — Argumente unserer Seite. */
  wins: NegotiationRowSpec[]
  /** Kostensteigerungen (Top 3) — die grössten Hebel des Lieferanten. */
  bringers: NegotiationRowSpec[]
  oneTime: OneTimeRowSpec[]
  /**
   * Facts-Zeile der Einmalzahlungen-Sektion, vorformuliert (wortgleich aus
   * der Schale übernommen): unterscheidet „alle unverändert", „Summe über
   * die bestimmbaren Positionen" und „Summe nicht bestimmbar" und benennt
   * übergangene Positionen, statt sie als 0 mitzuzählen.
   */
  oneTimeFactsDe: (string | null)[]
}

/**
 * Herkunft einer Metrik-Zeile aus dem Katalog des Laufs.
 *
 * Leer, wo der Katalog keine Kennung führt — eine unveränderte oder nicht
 * erhobene Kennzahl behauptet keine Differenz und trägt deshalb keinen
 * Beleg (dieselbe Doktrin wie kachelEingaben in overview-run.ts).
 */
function sourceRefFor(
  key: SummaryMetricKey,
  byId: ReadonlyMap<string, DifferenceRecord>,
  idsByMetricKey: ReadonlyMap<SummaryMetricKey, string[]>,
): SourceRef {
  const ids = idsByMetricKey.get(key) ?? []
  const belege = ids.map((id) => byId.get(id)).filter((r): r is DifferenceRecord => r !== undefined)
  return {
    path: `summary.${key}`,
    cells: belege.flatMap((r) => r.cells),
    differenceIds: [...ids].sort(),
  }
}

export function buildNegotiationRun(input: {
  summaryRows: readonly SummaryDiffRowData[]
  summaryRecords: readonly DifferenceRecord[]
  idsByMetricKey: ReadonlyMap<SummaryMetricKey, string[]>
}): NegotiationRun {
  const byId = new Map(input.summaryRecords.map((r) => [r.differenceId, r] as const))
  const withRef = <T extends { key: SummaryMetricKey }>(row: T) => ({
    ...row,
    sourceRef: sourceRefFor(row.key, byId, input.idsByMetricKey),
  })

  const negotiation = buildNegotiation([...input.summaryRows])
  const oneTimeRows = buildOneTimeRows([...input.summaryRows])
  const oneTimeSum = sumOneTimeDeltas(oneTimeRows)
  const oneTimeFactsDe: (string | null)[] = oneTimeRows.every((r) => r.same)
    ? [unchangedPhrase('Alle Positionen')]
    : [
        oneTimeSum.total === null ? 'Summe nicht bestimmbar' : deltaPhrase({ value: oneTimeSum.total, unit: 'EUR' }),
        oneTimeSum.unbestimmt > 0
          ? `${oneTimeSum.unbestimmt} Position${oneTimeSum.unbestimmt === 1 ? '' : 'en'} ohne bestimmbares Delta, nicht in der Summe`
          : null,
      ]

  return {
    wins: negotiation.wins.map(withRef),
    bringers: negotiation.bringers.map(withRef),
    oneTime: oneTimeRows.map(withRef),
    oneTimeFactsDe,
  }
}
