// Wertstrom-Export (Demo-067 C, KAR-982) — DOCX. Net-new: the Wertstrom
// (VSM) module has no export today (app/wertstrom/[id]/page.tsx only
// renders the interactive editor). Reuses the SAME derived-metrics
// functions the editor's toolbar/badges use
// (components/wertstrom/vsm-metrics.ts — computeTimeline,
// findBottleneckId, computeVaClassBreakdown, computeSetupTimeSum,
// computeWaitTimeSum, computeTransportTimeSum, computeCostPerUnitRollup,
// computeScrapCostRollup) rather than re-deriving KPIs, so the export
// numbers always match what the editor shows on screen.
//
// Pure function of its inputs — the caller (server action) loads the
// value_stream_maps row (+ optionally the linked project's
// customer_takt_time_sec) and passes plain data in.
//
// Wertstrom P7 (A17, KAR-878/KAR-986, execution-prompt §19.3 "Microsoft
// Copilot Export"): additive — a "Copilot-Anweisung" section (the §19.3
// instruction block, German translation + verbatim English original, see
// `COPILOT_INSTRUCTION_BLOCK_*` below), a "Management-Analyse" section
// (Business-Interpretation = Baustein 1's `computeManagementAnalysis`
// sentences, §18/§19.3 "understandable business interpretation"), and an
// explicit "Provenance-Übersicht" section (measured/planned/imported/
// calculated/assumed counts, §19.3 "clearly distinguish measured, planned,
// imported, calculated and assumed values") — all new, appended sections;
// every field/section that existed before P7 is untouched (existing
// wertstrom-docx.test.ts assertions stay green).

import type { Paragraph, Table } from 'docx'
import type { ValueStreamMap, VsmNode } from '@/lib/vsm-types'
import {
  computeCostPerUnitRollup,
  computeScrapCostRollup,
  computeSetupTimeSum,
  computeTimeline,
  computeTransportTimeSum,
  computeVaClassBreakdown,
  computeWaitTimeSum,
  type CostRollup,
  type NodeTimeSum,
} from '@/components/wertstrom/vsm-metrics'
import { PROVENANCE_LABELS } from '@/components/wertstrom/vsm-config'
import { computeBottleneckV2, computeManagementAnalysis, type ShiftModelInput } from '@/lib/vsm-engine'
import type { ValueProvenance } from '@/lib/vsm-types'
import { buildAiInstructionBlock } from './ai-instruction-block'
import {
  bodyText,
  buildDocument,
  dataTable,
  docTitle,
  formatNumberDe,
  heading1,
  heading3,
  kvTable,
  packDocumentToBuffer,
  renderAiInstructionBlock,
  spacer,
} from './docx-shared'

/** §19.3, wörtlich aus dem execution-prompt (Z.2069–2077) — NICHT
 * umformuliert. Deutsche Übersetzung ist die primäre Anweisung im Dokument
 * (dieses Repo ist Deutsch-first, siehe CLAUDE.md); das Original-Englisch
 * wird zusätzlich beigelegt (Brief: "deutsch übersetzen + Original-Englisch
 * beilegen ist ok"), damit ein Copilot/Consultant beide Fassungen hat. */
export const COPILOT_INSTRUCTION_BLOCK_EN =
  'This file contains a SupplierPulse value stream analysis. Analyze the current state, future state, process data, inventories, material flows, information flows, bottlenecks, risks and measures as one connected operational system. Create a management summary, prioritized measure plan, decision document or presentation structure. Clearly distinguish measured, planned, imported, calculated and assumed values.'
export const COPILOT_INSTRUCTION_BLOCK_DE =
  'Diese Datei enthält eine SupplierPulse-Wertstromanalyse. Analysieren Sie Ist-Zustand, Soll-Zustand, Prozessdaten, Bestände, Materialflüsse, Informationsflüsse, Engpässe, Risiken und Maßnahmen als ein zusammenhängendes operatives System. Erstellen Sie eine Management-Zusammenfassung, einen priorisierten Maßnahmenplan, ein Entscheidungsdokument oder eine Präsentationsstruktur. Unterscheiden Sie klar zwischen gemessenen, geplanten, importierten, berechneten und angenommenen Werten.'

const PROVENANCE_ORDER: ValueProvenance[] = ['measured', 'planned', 'calculated', 'imported', 'assumed']

/** §19.3 "clearly distinguish measured/planned/imported/calculated/assumed
 * values" — counts every node by its `provenance` field, PLUS an explicit
 * "ohne Herkunftsangabe" bucket (unlike the in-canvas badge, which shows
 * nothing for an absent value — a data-quality report must surface the gap,
 * not hide it). */
function provenanceCounts(nodes: VsmNode[]): ReadonlyArray<readonly [string, string]> {
  const counts = new Map<ValueProvenance, number>()
  let unknown = 0
  for (const n of nodes) {
    if (n.provenance) counts.set(n.provenance, (counts.get(n.provenance) ?? 0) + 1)
    else unknown++
  }
  const rows: Array<readonly [string, string]> = PROVENANCE_ORDER.map((p) => [PROVENANCE_LABELS[p], String(counts.get(p) ?? 0)] as const)
  rows.push(['Ohne Herkunftsangabe', String(unknown)])
  return rows
}

const NODE_TYPE_LABEL: Record<VsmNode['type'], string> = {
  process: 'Prozess',
  machine: 'Maschine',
  inventory: 'Bestand',
  transport: 'Transport',
  customer: 'Kunde',
  supplier: 'Lieferant',
  timevalue: 'Zeitwertlinie',
}

function nodeValueAddedLabel(n: VsmNode): string {
  if (n.vaClass) {
    return { va: 'wertschöpfend (VA)', nnva: 'notwendig, nicht wertschöpfend (NNVA)', nva: 'nicht wertschöpfend (NVA)', unknown: 'ungeklärt' }[n.vaClass]
  }
  return n.isValueAdded ? 'wertschöpfend (VA)' : '—'
}

function secLabel(sum: NodeTimeSum): string {
  return sum.totalSec === null ? 'keine Datenbasis' : `${formatNumberDe(sum.totalSec, 0)} s (${sum.nodeCount} Node(s))`
}

function rollupRows(rollup: CostRollup): ReadonlyArray<readonly [string, string]> {
  if (rollup.buckets.length === 0) return [['—', 'keine Datenbasis']]
  return rollup.buckets.map((b) => [b.currency, `${formatNumberDe(b.total)} (${b.nodeCount} Node(s))`] as const)
}

export interface WertstromDocxInput {
  vsm: ValueStreamMap
  /** Linked project's customer_takt_time_sec, if the Wertstrom is linked to
   * a project — same source page.tsx already resolves for the editor. */
  taktTimeSec: number | null
  /** `value_stream_maps.is_demo` — kept as its own top-level field (not read
   * off `vsm.is_demo` inside this module) even though `ValueStreamMap` in
   * lib/vsm-types.ts carries `is_demo` since Wertstrom P0 (KAR-878): this
   * builder stays a pure function of plain data, same reasoning QAF's
   * `QafComparisonDocxInput.isDemo` already follows for its own (still
   * `is_demo`-less) `QafComparisonResult`. The caller (copilot-export-actions.ts)
   * now reads `vsm.is_demo` directly instead of re-casting the raw row. */
  isDemo: boolean
  generatedAtLabel: string
  /** Wertstrom P7 (§19.3 Business-Interpretation/Provenance) — optional,
   * additive context for `computeManagementAnalysis` (Baustein 1). Absent =
   * the Management-Analyse section still renders, with every takt-/bedarf-
   * abhängige Aussage as an honest "nicht bewertbar" statement (same
   * doctrine the engine itself uses) — never a fabricated number. */
  demandUnitsPerDay?: number
  shiftModel?: ShiftModelInput
}

export async function buildWertstromCopilotDocx(input: WertstromDocxInput): Promise<Buffer> {
  const { vsm, taktTimeSec, isDemo, generatedAtLabel, demandUnitsPerDay, shiftModel } = input
  const nodes = vsm.nodes
  const nodeNameById = new Map(nodes.map((n) => [n.id, n.name || '(unbenannt)']))

  const timeline = computeTimeline(nodes)
  const vaBreakdown = computeVaClassBreakdown(nodes)
  const setupSum = computeSetupTimeSum(nodes)
  const waitSum = computeWaitTimeSum(nodes)
  const transportSum = computeTransportTimeSum(nodes)
  const costRollup = computeCostPerUnitRollup(nodes)
  const scrapRollup = computeScrapCostRollup(nodes)

  // Wertstrom P7 — Business-Interpretation (§18/§19.3), computed the SAME
  // way the editor's own Management-Analyse panel does (capacityOverridesByNodeId
  // derived from node.availabilityPct, the only per-node override this app
  // collects today — see components/wertstrom/vsm-scenario-compare.ts's
  // identical derivation for the P5 Kern-KPIs).
  const capacityOverridesByNodeId: Record<string, { availabilityPct?: number }> = {}
  for (const n of nodes) {
    if ((n.type === 'process' || n.type === 'machine') && n.availabilityPct != null) capacityOverridesByNodeId[n.id] = { availabilityPct: n.availabilityPct }
  }
  // P7 fix-round Grundsatz-Entscheidung "v2 überall, wo 'Engpass'
  // draufsteht": was `findBottleneckId` (Legacy, type==='process' only, raw
  // cycleTimeSec) — the "Kennzahlen"-Zeile below and the "Management-
  // Analyse"-Abschnitt further down (computeManagementAnalysis, which
  // itself uses computeBottleneckV2) used to compute two DIFFERENT engpass
  // answers for the SAME map in the SAME document — an unbelegter
  // Widerspruch, unlike the presentation-mode/XLSX v1-vs-v2 divergences,
  // which were at least documented judgment calls. Both sections now read
  // from the same v2 model.
  const bottleneck = computeBottleneckV2(nodes, taktTimeSec, capacityOverridesByNodeId)
  const bottleneckName = bottleneck.primary?.nodeName ?? null
  const managementAnalysis = computeManagementAnalysis(nodes, vsm.connections, { taktTimeSec, demandUnitsPerDay, shiftModel, capacityOverridesByNodeId })

  const aiBlock = buildAiInstructionBlock({
    exportTitle: 'Wertstrom-Export',
    aboutText:
      'Dieses Dokument ist der Export eines Wertstroms (VSM) — der visuellen Darstellung des Material- ' +
      'und Informationsflusses durch ein Produktionssystem. Es enthält die Prozessschritte, ihre ' +
      'Verbindungen sowie abgeleitete Kennzahlen (VA-Quote, Rüst-/Warte-/Transportzeit-Summen, ' +
      'Kosten-Rollup je Währung) exakt so, wie sie auch im Wertstrom-Editor berechnet werden.',
    usageHints: [
      'Nutze die VA-Quote und den Engpass (Bottleneck) als Einstieg für eine Verschwendungs-Analyse.',
      'Bei mehreren Währungs-Buckets im Kosten-Rollup: niemals über Buckets hinweg addieren, sondern getrennt bewerten.',
      'Prozessschritte ohne Zykluszeit oder ohne VA-Klassifizierung explizit als Datenlücke benennen, nicht schätzen.',
    ],
    isDemo,
  })

  const children: (Paragraph | Table)[] = [
    docTitle('Wertstrom-Export'),
    bodyText(vsm.title, { bold: true }),
    spacer(),
    ...renderAiInstructionBlock(aiBlock),

    // Wertstrom P7 (§19.3, wörtlich) — eigener Abschnitt, getrennt vom
    // generischen AI-Block oben (der ist modul-übergreifend für alle 4
    // Copilot-Exporte, dieser ist die spezifische §19.3-Anweisung nur für
    // den Wertstrom-Export).
    heading1('Copilot-Anweisung (§19.3)'),
    bodyText(COPILOT_INSTRUCTION_BLOCK_DE),
    heading3('Original (Englisch)'),
    bodyText(COPILOT_INSTRUCTION_BLOCK_EN, { italics: true }),
    spacer(),

    heading1('Steckbrief'),
    kvTable([
      ['Titel', vsm.title],
      ['Beschreibung', vsm.description ?? '—'],
      ['Prozessschritte', String(nodes.length)],
      ['Verbindungen', String(vsm.connections.length)],
      ['Kundentakt', taktTimeSec !== null ? `${formatNumberDe(taktTimeSec, 0)} s` : '— (kein verknüpftes Projekt mit Kundentakt)'],
      ['Erzeugt am', generatedAtLabel],
    ]),

    heading1('Kennzahlen'),
    kvTable([
      ['VA-Quote', `${vaBreakdown.vaRatioPct} % (${formatNumberDe(timeline.va, 0)} s wertschöpfend von ${formatNumberDe(timeline.total, 0)} s gesamt)`],
      ['Rüstzeit-Summe', secLabel(setupSum)],
      ['Wartezeit-Summe', secLabel(waitSum)],
      ['Transportzeit-Summe (Node-Ebene)', secLabel(transportSum)],
      ['Engpass (Bottleneck)', bottleneckName ?? '— (kein Kundentakt oder zu wenig Kapazitätsdaten für eine Engpass-Berechnung)'],
    ]),
    spacer(),

    heading1('VA-Klassen-Verteilung'),
    dataTable(
      ['Klasse', 'Sekunden', 'Anzahl Nodes'],
      [
        ['VA (gemeldet)', formatNumberDe(vaBreakdown.va.seconds, 0), String(vaBreakdown.va.nodeCount)],
        ['NNVA', formatNumberDe(vaBreakdown.nnva.seconds, 0), String(vaBreakdown.nnva.nodeCount)],
        ['NVA', formatNumberDe(vaBreakdown.nva.seconds, 0), String(vaBreakdown.nva.nodeCount)],
        ['Ungeklärt', formatNumberDe(vaBreakdown.unknown.seconds, 0), String(vaBreakdown.unknown.nodeCount)],
        ['VA (abgeleitet aus isValueAdded)', formatNumberDe(vaBreakdown.derivedVa.seconds, 0), String(vaBreakdown.derivedVa.nodeCount)],
        ['Nicht-VA (abgeleitet)', formatNumberDe(vaBreakdown.derivedNonVa.seconds, 0), String(vaBreakdown.derivedNonVa.nodeCount)],
      ],
    ),
    spacer(),

    heading1('Kosten-Rollup je Währung (BW)'),
    kvTable(rollupRows(costRollup)),
    spacer(),
    heading1('Ausschuss-Kosten-Rollup je Angebotswährung (AW)'),
    kvTable(rollupRows(scrapRollup)),
    spacer(),

    // Wertstrom P7 (A15/§18, Business-Interpretation) — dieselben
    // regelbasierten Sätze, die auch das Editor-Panel zeigt (lib/vsm-engine
    // computeManagementAnalysis), hier als Fließtext-Aufzählung.
    heading1('Management-Analyse'),
    ...managementAnalysis.statements.map((s) => bodyText(`${s.text} (Konfidenz: ${s.confidence})`)),
    spacer(),
  ]

  children.push(heading1('Prozessschritte'))
  if (nodes.length === 0) {
    children.push(bodyText('Keine Prozessschritte erfasst.'))
  } else {
    children.push(
      dataTable(
        ['Name', 'Typ', 'Zykluszeit (s)', 'VA-Klasse', 'Maschinentyp', 'Mitarbeiter', 'Standort'],
        nodes.map((n) => [
          n.name || '(unbenannt)',
          NODE_TYPE_LABEL[n.type] ?? n.type,
          n.cycleTimeSec !== undefined ? formatNumberDe(n.cycleTimeSec, 1) : '—',
          nodeValueAddedLabel(n),
          n.machineType ?? '—',
          n.numWorkers !== undefined ? String(n.numWorkers) : '—',
          n.location ?? '—',
        ]),
      ),
    )
  }
  children.push(spacer())

  children.push(heading1('Verbindungen'))
  if (vsm.connections.length === 0) {
    children.push(bodyText('Keine Verbindungen erfasst.'))
  } else {
    children.push(
      dataTable(
        ['Von', 'Nach', 'Label', 'Transportzeit (s)', 'Losgröße'],
        vsm.connections.map((conn) => [
          nodeNameById.get(conn.fromNodeId) ?? conn.fromNodeId,
          nodeNameById.get(conn.toNodeId) ?? conn.toNodeId,
          conn.label ?? '—',
          conn.transportTimeSec !== undefined ? formatNumberDe(conn.transportTimeSec, 1) : '—',
          conn.batchSize !== undefined ? String(conn.batchSize) : '—',
        ]),
      ),
    )
  }
  children.push(spacer())

  // Wertstrom P7 (§19.3 "clearly distinguish measured, planned, imported,
  // calculated and assumed values") — explicit provenance breakdown, not
  // just the per-node badge the editor shows.
  children.push(heading1('Provenance-Übersicht'))
  children.push(kvTable(provenanceCounts(nodes)))

  const doc = buildDocument(`Wertstrom-Export — ${vsm.title}`, children)
  return packDocumentToBuffer(doc)
}
