// KAR-949 — Multi-QAF / Variante↔Standard XLSX export unit tests.
//
// Synthetic fixtures only (invented Q7x/T95-shaped variant/component ids —
// no real BMW project/vehicle codenames). // allow-customer-string
// Reuses synthetic-fixtures.ts's
// buildWideSlotFixture() for the container side (already-vetted synthetic
// container — see that module's own confidentiality discipline) and
// hand-builds minimal MultiQafComparisonResult / VariantVsStandardComparisonResult
// envelopes so the honesty-invariant cases (nicht_ermittelbar row,
// gate-failed aggregate, mixed-currency) are exercised deterministically —
// same "test-support literal, not the real engine output" category
// lib/qaf-differences/internal/__tests__/export.test.ts's own alt/neu
// fixtures already establish for the Standard export.
//
// tdd-guard:skip — test file.

import { describe, it, expect } from 'vitest'
import ExcelJS from 'exceljs'
import { buildWideSlotFixture } from './synthetic-fixtures'
import { buildMultiQafExportWorkbook, buildVariantVsStandardExportWorkbook, type MultiQafExportInput, type VariantVsStandardExportInput } from '../export'
import type { MultiQafComparisonResult } from '../compare-flow'
import type { MultiQafContainerDiff } from '../container-differ'
import type { MaterialDiffResult } from '../material-differ'
import type { ProfileDiffResult } from '../profile-differ'
import type { VariantReconciliationResult } from '../variant-reconciliation'
import type { SummaryTotalsDiffResult } from '../summary-totals-differ'
import type { AggregateImpactResult } from '../aggregate-impact'
import type { VariantVsStandardComparisonResult } from '../variant-vs-standard'
import { DEGRADED_MODULES } from '../variant-vs-standard'
import type { VariantMatchOverride, VariantMatchResult } from '../variant-matcher'

async function loadWorkbook(buf: ArrayBuffer): Promise<ExcelJS.Workbook> {
  const wb = new ExcelJS.Workbook()
  await wb.xlsx.load(buf as unknown as ArrayBuffer)
  return wb
}

function sheetContainsText(ws: ExcelJS.Worksheet, needle: string): boolean {
  let found = false
  ws.eachRow((row) => {
    const vals = (row.values as unknown[]).map((v) => String(v ?? ''))
    if (vals.some((v) => v.includes(needle))) found = true
  })
  return found
}

function emptyContainerDiff(overrides: Partial<MultiQafContainerDiff> = {}): MultiQafContainerDiff {
  return {
    variants: {
      added: [],
      removed: [],
      renamed: [],
      reordered: [],
      uncertainMatches: [],
      activeStateChanges: [],
      detailLinkageTransitions: [],
      detailWithoutSummary: { added: [], removed: [] },
      summaryWithoutDetail: [],
    },
    dimensions: { added: [], removed: [], renamedKeys: [] },
    sharedMaterial: {
      structure: { altRowCount: 0, neuRowCount: 0, altColumnVariantIds: [], neuColumnVariantIds: [], addedColumnVariantIds: [], removedColumnVariantIds: [] },
      addedRows: [],
      removedRows: [],
      changedRows: [],
    },
    profiles: { added: [], removed: [], volumeBandThresholdChanges: [], bindingChanges: [] },
    template: {
      family: {
        changed: false,
        altFamily: 'unknown',
        neuFamily: 'unknown',
        altClassification: null,
        neuClassification: null,
        altStructuralHash: null,
        neuStructuralHash: null,
        structuralHashChanged: false,
      },
      sheetSet: { added: [], removed: [], becameHidden: [], becameVisible: [] },
      externalLinks: { tracked: false, note: 'not tracked' },
    },
    reviewRequired: false,
    reviewRequiredReasons: [],
    ...overrides,
  }
}

function emptyMaterialDiff(overrides: Partial<MaterialDiffResult> = {}): MaterialDiffResult {
  return {
    sharedComponents: {
      unitCostValueChanges: [],
      unitCostCurrencyChanges: [],
      exchangeRateChanges: [],
      logisticsOrDutyChanges: [],
      materialOverheadChanges: [],
      formulaChanges: [],
      rowIdentityChanges: [],
    },
    variantAllocation: { findings: [], substitutionsSuspected: [] },
    uncertainMatches: [],
    warnings: [],
    ...overrides,
  }
}

function emptyProfileDiff(overrides: Partial<ProfileDiffResult> = {}): ProfileDiffResult {
  return {
    componentValueChanges: [],
    totalChanges: [],
    bindingValueImpacts: [],
    added: [],
    removed: [],
    inconsistentBindings: { added: [], removed: [] },
    summaryReconciliation: { added: [], removed: [], changed: [] },
    uncertainMatches: [],
    warnings: [],
    ...overrides,
  }
}

const MODEL_VERSION_3 = 3 as const

function buildResult(overrides: Partial<MultiQafComparisonResult> = {}): MultiQafComparisonResult {
  const matchResult: VariantMatchResult[] = [
    {
      kind: 'matched',
      leftIndex: 0,
      leftId: 'wideslot-active-1',
      rightIndex: 0,
      rightId: 'wideslot-active-1',
      stage: 'raw_exact',
      confidence: 0.95,
      evidence: [{ signal: 'exact_dimension_match', detail: 'Q7x-Fixture: alle Kern-Dimensionen identisch.' }],
      explanation: 'Q7x-Fixture: exakter Match.',
      matchedDimensionCount: 4,
    },
    { kind: 'unmatched_left', leftIndex: 1, leftId: 'wideslot-active-2', reason: 'removed' },
    { kind: 'unmatched_right', rightIndex: 1, rightId: 't95-new-variant', reason: 'added' },
    {
      kind: 'ambiguous',
      leftIndices: [2, 3],
      leftIds: ['wideslot-active-3', 'wideslot-active-4'],
      rightIndices: [2],
      rightIds: ['t95-ambiguous-candidate'],
      candidates: [],
      reviewRelevant: true,
      explanation: 'Q7x-Fixture: mehrdeutiger Kandidat.',
    },
  ]
  const reconciliationCheck: VariantReconciliationResult = {
    variantId: 'wideslot-active-1',
    checks: [
      {
        checkId: 'currency',
        variantId: 'wideslot-active-1',
        status: 'nicht_pruefbar',
        nichtPruefbarReason: 'mixed_currency',
        expected: null,
        actual: null,
        deltaAbsolute: null,
        evidenceSource: null,
        toleranceBand: { relativeTolerance: 0.005, absoluteToleranceMinor: 1 },
        formulaSignatures: null,
        messageDe: 'Q7x-Fixture: Währung nicht prüfbar (gemischt).',
        messageEn: 'Q7x-fixture: currency not verifiable (mixed).',
      },
      {
        checkId: 'manufacturing_total',
        variantId: 'wideslot-active-1',
        status: 'bestanden',
        nichtPruefbarReason: null,
        expected: 100,
        actual: 100.2,
        deltaAbsolute: 0.2,
        evidenceSource: 'bound_vs_virtual',
        toleranceBand: { relativeTolerance: 0.005, absoluteToleranceMinor: 1 },
        formulaSignatures: [],
        messageDe: null,
        messageEn: null,
      },
    ],
  }
  const summaryTotalsDiff: SummaryTotalsDiffResult = {
    findings: [
      {
        metricKey: 'offerBasePrice',
        altVariantId: 'wideslot-active-1',
        neuVariantId: 'wideslot-active-1',
        state: 'changed',
        altAmount: { value: 100, currency: 'EUR' },
        neuAmount: { value: 110, currency: 'EUR' },
        currencyChanged: false,
        currencyGate: 'same_currency',
        deltaAbsolute: 10,
        deltaPercent: 0.1,
        status: 'anstieg',
        sourceRefs: [],
      },
      {
        metricKey: 'offerPrice',
        altVariantId: 'wideslot-active-1',
        neuVariantId: 'wideslot-active-1',
        state: 'nicht_ermittelbar',
        altAmount: null,
        neuAmount: null,
        currencyChanged: false,
        currencyGate: 'currency_unknown',
        deltaAbsolute: null,
        deltaPercent: null,
        status: null,
        sourceRefs: [],
      },
    ],
    materialCostsByCurrencyFindings: [],
    uncertainMatches: [],
    changedMetricSumsByCurrency: [{ currency: 'EUR', totalDeltaAbsolute: 10, metricFindingCount: 1 }],
  }
  const aggregateImpact: AggregateImpactResult = {
    modelVersion: 1 as const,
    gates: [
      { gate: 'valid_baseline', passed: false, messageDe: 'Q7x-Fixture: Baseline ungültig.', messageEn: 'Q7x-fixture: baseline invalid.', affectedVariantIds: [] },
      { gate: 'compatible_currencies', passed: true, messageDe: 'Q7x-Fixture: Währungen kompatibel.', messageEn: 'Q7x-fixture: currencies compatible.', affectedVariantIds: ['wideslot-active-1'] },
    ],
    gatesPassed: ['compatible_currencies'],
    gatesFailed: ['valid_baseline'],
    reviewRequired: true,
    excludedVariants: [{ variantId: 'wideslot-active-3', reason: 'ambiguous_or_uncertain_match', messageDe: 'Q7x-Fixture: unsicher.', messageEn: 'Q7x-fixture: uncertain.' }],
    unitPriceDeltas: [],
    annual: { population: [], perVariant: [], aggregate: [] },
    lifetime: { population: [], perVariant: [], aggregate: [] },
    structuralFallback: {
      variantsAdded: 1,
      variantsRemoved: 1,
      variantsRenamed: 0,
      variantsReordered: 0,
      variantsActiveStateChanged: 0,
      uncertainMatches: 1,
      materialRowsAdded: 0,
      materialRowsRemoved: 0,
      materialRowsChanged: 0,
      profilesAdded: 0,
      profilesRemoved: 0,
      volumeBandThresholdChanges: 0,
      profileBindingChanges: 0,
    },
    assumptions: [{ code: 'aggregate_suppressed_baseline_invalid', messageDe: 'Q7x-Fixture: Aggregat unterdrückt.', messageEn: 'Q7x-fixture: aggregate suppressed.' }],
  }

  return {
    modelVersion: MODEL_VERSION_3,
    matchResult,
    droppedOverrides: [],
    containerDiff: emptyContainerDiff({ reviewRequired: true, reviewRequiredReasons: ['uncertain_variant_matches_present'] }),
    materialDiff: emptyMaterialDiff({
      sharedComponents: {
        unitCostValueChanges: [],
        unitCostCurrencyChanges: [
          {
            canonicalComponentIdentity: 'Q7x::T95-Bauteil',
            alt: { canonicalComponentIdentity: 'Q7x::T95-Bauteil', sourceRow: 5, sourceCells: [], validationStatus: 'ok' },
            neu: { canonicalComponentIdentity: 'Q7x::T95-Bauteil', sourceRow: 5, sourceCells: [], validationStatus: 'ok' },
            altCurrency: 'EUR',
            neuCurrency: 'CNY',
            impact: { affectedVariantIds: ['wideslot-active-1'], impacts: [], aggregates: [] },
            reviewRelevant: true,
          },
        ],
        exchangeRateChanges: [],
        logisticsOrDutyChanges: [],
        materialOverheadChanges: [],
        formulaChanges: [],
        rowIdentityChanges: [],
      },
    }),
    profileDiff: emptyProfileDiff(),
    reconciliation: { alt: [reconciliationCheck], neu: [reconciliationCheck] },
    reviewRequired: true,
    reviewRequiredReasons: ['uncertain_variant_matches_present', 'summary_totals_changed_without_material_or_profile_evidence'],
    aggregateImpact,
    summaryTotalsDiff,
    ...overrides,
  }
}

const altContainer = buildWideSlotFixture()
const neuContainer = buildWideSlotFixture()

const persistedOverrides: VariantMatchOverride[] = [
  {
    left: { compositeCanonicalKey: 'wideslot-active-1-key', dimensions: altContainer.activeVariants[0]!.dimensions },
    right: { compositeCanonicalKey: 'wideslot-active-1-key', dimensions: neuContainer.activeVariants[0]!.dimensions },
    decision: 'matched',
    note: 'Q7x-Fixture manuell bestätigt.',
    setBy: 'test-user',
    setAt: '2026-01-01T00:00:00.000Z',
    status: 'active',
  },
  {
    left: { compositeCanonicalKey: 'wideslot-active-5-key', dimensions: altContainer.activeVariants[4]!.dimensions },
    right: null,
    decision: 'unmatched',
    note: null,
    setBy: 'test-user',
    setAt: '2026-01-01T00:00:00.000Z',
    status: 'dropped_on_drift',
  },
]

const fullInput: MultiQafExportInput = {
  generatedAtLabel: '2026-07-14 00:00',
  altFileName: 'Q7x_ALT.xlsx',
  neuFileName: 'Q7x_NEU.xlsx',
  altContainer,
  neuContainer,
  result: buildResult(),
  persistedOverrides,
}

const REQUIRED_MULTI_QAF_SHEETS = ['Uebersicht', 'Varianten_Matching', 'Summary_Kennzahlen', 'Material_Diff', 'Fertigungsprofile', 'Rekonziliation', 'Aggregat_Impact']

describe('buildMultiQafExportWorkbook', () => {
  it('produces all 7 sheets', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const names = wb.worksheets.map((w) => w.name)
    for (const s of REQUIRED_MULTI_QAF_SHEETS) expect(names).toContain(s)
    expect(names).toHaveLength(REQUIRED_MULTI_QAF_SHEETS.length)
  })

  it('Summary_Kennzahlen contains both a changed and a nicht_ermittelbar row, changed sorted first', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Summary_Kennzahlen')!
    const rows: string[][] = []
    ws.eachRow((row) => rows.push((row.values as unknown[]).map((v) => String(v ?? ''))))
    const changedRowIndex = rows.findIndex((r) => r.includes('changed'))
    const nichtErmittelbarRowIndex = rows.findIndex((r) => r.includes('nicht_ermittelbar'))
    expect(changedRowIndex).toBeGreaterThan(0)
    expect(nichtErmittelbarRowIndex).toBeGreaterThan(0)
    expect(changedRowIndex).toBeLessThan(nichtErmittelbarRowIndex)
    // Never a blank/zero-looking cell for the undeterminable row — the status
    // Klartext column must say so explicitly (Ehrlichkeits-Invariante).
    expect(sheetContainsText(ws, 'nicht ermittelbar')).toBe(true)
  })

  it('Aggregat_Impact shows the failed gate AND an explicit "blocked by gate" row, never a naked sum', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Aggregat_Impact')!
    expect(sheetContainsText(ws, 'valid_baseline')).toBe(true)
    expect(sheetContainsText(ws, 'blockiert')).toBe(true)
    expect(sheetContainsText(ws, 'kein Aggregat berechnet')).toBe(true)
  })

  it('Material_Diff marks the mixed-currency unit-cost finding as review-relevant, never silently netted', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Material_Diff')!
    expect(sheetContainsText(ws, 'T95-Bauteil')).toBe(true)
    expect(sheetContainsText(ws, 'ja / yes')).toBe(true)
  })

  it('Rekonziliation shows the nicht_pruefbar check with its reason, not a blank/passed cell', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Rekonziliation')!
    expect(sheetContainsText(ws, 'nicht_pruefbar')).toBe(true)
    expect(sheetContainsText(ws, 'gemischte Währungen')).toBe(true)
  })

  it('Varianten_Matching lists matched/added/removed/uncertain and the dropped override', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Varianten_Matching')!
    expect(sheetContainsText(ws, 'gematcht')).toBe(true)
    expect(sheetContainsText(ws, 'entfallen (nur ALT)')).toBe(true)
    expect(sheetContainsText(ws, 'neu (nur NEU)')).toBe(true)
    expect(sheetContainsText(ws, 'mehrdeutig')).toBe(true)
    expect(sheetContainsText(ws, 'dropped_on_drift') || sheetContainsText(ws, 'verworfen')).toBe(true)
  })

  // KAR-949 review Finding 1 (CONFIRMED): a `'leftIds' in r` / `'rightIds' in
  // r` check silently read as [] for split_suspected's/merge_suspected's
  // SINGULAR leftId/rightId field (see variant-matcher.ts's
  // VariantSplitSuspectedResult/VariantMergeSuspectedResult), which dropped
  // exactly the "which variant is affected" information the export exists
  // to show. Read-back assertions: the exported row must carry the real
  // variant id/label, never the '—' fallback that a truly-missing id would
  // produce.
  it('Varianten_Matching split_suspected row exports the ALT variant id AND label (not "—")', async () => {
    const splitCase: VariantMatchResult = {
      kind: 'split_suspected',
      leftIndex: 5,
      leftId: 'wideslot-active-6',
      rightIndices: [10, 11],
      rightIds: ['t95-split-a', 't95-split-b'],
      candidates: [],
      reviewRelevant: true,
      explanation: 'Q7x-Fixture: Split vermutet.',
    }
    const base = buildResult()
    const input: MultiQafExportInput = {
      ...fullInput,
      result: { ...base, matchResult: [...base.matchResult, splitCase] },
    }
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(input))
    const ws = wb.getWorksheet('Varianten_Matching')!
    const rows: string[][] = []
    ws.eachRow((row) => rows.push((row.values as unknown[]).map((v) => String(v ?? ''))))
    const splitRow = rows.find((r) => r.includes('wideslot-active-6'))
    expect(splitRow, 'split_suspected row must carry the ALT variant id, not fall back to "—"').toBeDefined()
    expect(splitRow).toContain('slot-6')
    expect(splitRow).toContain('t95-split-a, t95-split-b')
  })

  it('Varianten_Matching merge_suspected row exports the NEU variant id AND label (not "—")', async () => {
    const mergeCase: VariantMatchResult = {
      kind: 'merge_suspected',
      rightIndex: 6,
      rightId: 'wideslot-active-7',
      leftIndices: [12, 13],
      leftIds: ['t95-merge-a', 't95-merge-b'],
      candidates: [],
      reviewRelevant: true,
      explanation: 'Q7x-Fixture: Merge vermutet.',
    }
    const base = buildResult()
    const input: MultiQafExportInput = {
      ...fullInput,
      result: { ...base, matchResult: [...base.matchResult, mergeCase] },
    }
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(input))
    const ws = wb.getWorksheet('Varianten_Matching')!
    const rows: string[][] = []
    ws.eachRow((row) => rows.push((row.values as unknown[]).map((v) => String(v ?? ''))))
    const mergeRow = rows.find((r) => r.includes('wideslot-active-7'))
    expect(mergeRow, 'merge_suspected row must carry the NEU variant id, not fall back to "—"').toBeDefined()
    expect(mergeRow).toContain('slot-7')
    expect(mergeRow).toContain('t95-merge-a, t95-merge-b')
  })

  it('every sheet has a frozen top view', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    for (const name of REQUIRED_MULTI_QAF_SHEETS) {
      const ws = wb.getWorksheet(name)!
      expect(ws.views).toBeTruthy()
    }
  })

  it('tolerates a null result (no saved comparison) without throwing — every sheet gets an honest hint row', async () => {
    const input: MultiQafExportInput = { ...fullInput, result: null }
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(input))
    const names = wb.worksheets.map((w) => w.name)
    for (const s of REQUIRED_MULTI_QAF_SHEETS) expect(names).toContain(s)
    const matching = wb.getWorksheet('Varianten_Matching')!
    expect(sheetContainsText(matching, 'kein gespeichertes Vergleichsergebnis')).toBe(true)
  })

  it('tolerates null containers and a null result together (old/corrupt persisted record)', async () => {
    const input: MultiQafExportInput = {
      generatedAtLabel: '2026-07-14 00:00',
      altFileName: null,
      neuFileName: null,
      altContainer: null,
      neuContainer: null,
      result: null,
      persistedOverrides: [],
    }
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(input))
    expect(wb.worksheets.length).toBe(REQUIRED_MULTI_QAF_SHEETS.length)
  })

  it('an aggregateImpact of null (pre-KAR-944 envelope) renders an explicit hint, not a crash or a fabricated total', async () => {
    const input: MultiQafExportInput = { ...fullInput, result: buildResult({ aggregateImpact: null }) }
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(input))
    const ws = wb.getWorksheet('Aggregat_Impact')!
    expect(sheetContainsText(ws, 'altes Ergebnis-Format')).toBe(true)
  })

  it('numeric cells carry real numbers (typeof number), not stringified numbers', async () => {
    const wb = await loadWorkbook(await buildMultiQafExportWorkbook(fullInput))
    const ws = wb.getWorksheet('Summary_Kennzahlen')!
    let sawNumber = false
    ws.eachRow((row, rowNumber) => {
      if (rowNumber === 1) return
      const cell = row.getCell(9) // ALT-Betrag
      if (typeof cell.value === 'number') sawNumber = true
    })
    expect(sawNumber).toBe(true)
  })
})

describe('buildVariantVsStandardExportWorkbook', () => {
  const variantId = altContainer.activeVariants[0]!.stableInternalId
  const vvsResult: VariantVsStandardComparisonResult = {
    modelVersion: 1 as const,
    variantId,
    standardRef: { id: 'standard-file-id', fileName: 'T95_Standard.xlsx', quotationDate: '2026-01-01' },
    summaryIdentityIssues: [
      { type: 'part_number_comparison_not_applicable', severity: 'hinweis', field: 'partNumber', explanation: 'Q7x-Fixture: nicht anwendbar.', explanationEn: 'Q7x-fixture: not applicable.' },
    ],
    summaryMetricsDiff: [
      {
        metricKey: 'materialCosts',
        altValue: 100,
        neuValue: 120,
        deltaAbsolute: 20,
        deltaPercent: 0.2,
        status: 'anstieg',
        currency: 'EUR',
        sourceAlt: null,
        sourceNeu: null,
        // Virtuelle Variante gegen Standard: es gibt keine Blattzeile mit
        // Label, die man gegen die Registry prüfen könnte.
        labelFileAlt: null,
        labelFileNeu: null,
        labelVerifiedAlt: null,
        labelVerifiedNeu: null,
      },
    ],
    degradedModules: DEGRADED_MODULES,
    reviewRequired: false,
    reviewRequiredReasons: [],
    variantWarnings: [],
    containerReviewWarnings: [],
  }
  const vvsInput: VariantVsStandardExportInput = {
    generatedAtLabel: '2026-07-14 00:00',
    multiQafFileName: 'Q7x_Container.xlsx',
    standardFileName: 'T95_Standard.xlsx',
    container: altContainer,
    variantId,
    result: vvsResult,
  }

  const REQUIRED_VVS_SHEETS = ['Uebersicht', 'Summary_Identitaet', 'Summary_Kennzahlen_Diff', 'Nicht_Verfuegbar']

  it('produces all 4 sheets', async () => {
    const wb = await loadWorkbook(await buildVariantVsStandardExportWorkbook(vvsInput))
    const names = wb.worksheets.map((w) => w.name)
    for (const s of REQUIRED_VVS_SHEETS) expect(names).toContain(s)
    expect(names).toHaveLength(REQUIRED_VVS_SHEETS.length)
  })

  it('Nicht_Verfuegbar lists all 12 degraded modules with a reason, never looking like "no differences"', async () => {
    const wb = await loadWorkbook(await buildVariantVsStandardExportWorkbook(vvsInput))
    const ws = wb.getWorksheet('Nicht_Verfuegbar')!
    const moduleKeys = new Set(DEGRADED_MODULES.map((m) => m.moduleKey))
    let dataRowCount = 0
    ws.eachRow((row) => {
      if (moduleKeys.has(String(row.getCell(1).value ?? '') as (typeof DEGRADED_MODULES)[number]['moduleKey'])) dataRowCount += 1
    })
    expect(dataRowCount).toBe(12)
    expect(sheetContainsText(ws, 'manufacturing_steps')).toBe(true)
    expect(sheetContainsText(ws, 'workbook_safety')).toBe(true)
  })

  it('Summary_Kennzahlen_Diff renders the real diff with a real numeric delta', async () => {
    const wb = await loadWorkbook(await buildVariantVsStandardExportWorkbook(vvsInput))
    const ws = wb.getWorksheet('Summary_Kennzahlen_Diff')!
    expect(sheetContainsText(ws, 'materialCosts')).toBe(true)
    let sawDelta = false
    ws.eachRow((row, rowNumber) => {
      if (rowNumber === 1) return
      if (row.getCell(5).value === 20) sawDelta = true
    })
    expect(sawDelta).toBe(true)
  })

  it('tolerates a null result and a null container without throwing', async () => {
    const input: VariantVsStandardExportInput = {
      generatedAtLabel: '2026-07-14 00:00',
      multiQafFileName: null,
      standardFileName: null,
      container: null,
      variantId: null,
      result: null,
    }
    const wb = await loadWorkbook(await buildVariantVsStandardExportWorkbook(input))
    expect(wb.worksheets.length).toBe(REQUIRED_VVS_SHEETS.length)
    const overview = wb.getWorksheet('Uebersicht')!
    expect(sheetContainsText(overview, 'kein gespeichertes Vergleichsergebnis')).toBe(true)
  })
})
