import { describe, it, expect } from 'vitest'
import { buildWaterfallData } from '../qaf-bridge-chart'
import type { BridgeData } from '@/lib/qaf-differences'

const bridge: BridgeData = {
  start: 2.46,
  end: 3.7,
  delta: 1.24,
  steps: [
    { bucket: 'Material', label: 'Materialkosten', delta: -0.81 },
    { bucket: 'Manufacturing', label: 'Fertigungskosten', delta: 1.72 },
    { bucket: 'Other', label: 'Übrige', delta: 0.33 },
  ],
  endComposition: [
    { key: 'Material', label: 'Material', value: 0.69 },
    { key: 'Manufacturing', label: 'Manufacturing', value: 2.1 },
    { key: 'ScrapB', label: 'Scrap', value: 0.12 },
    { key: 'SGA', label: 'SG&A', value: 0.6 },
    { key: 'Other', label: 'Übrige', value: 0.19 },
  ],
  // Diese Fixture stammt aus der G60-Brücke, die ihren Sammelposten vorerst
  // behält (siehe g60/view.ts) — der Rest ist dort ausgewiesen und außerhalb
  // der Toleranz, genau das bildet sie ab.
  residual: 0.33,
  residualWithinTolerance: false,
}

describe('buildWaterfallData', () => {
  const rows = buildWaterfallData(bridge)

  it('anchors with an ALT total bar and ends with the NEU composition', () => {
    expect(rows[0]).toMatchObject({ name: 'ALT', total: 2.46 })
    const end = rows[rows.length - 1]
    expect(end.name).toBe('NEU')
    expect(end.Material).toBeCloseTo(0.69)
    expect(end.Other).toBeCloseTo(0.19)
  })

  it('floats a decrease step down from the running level (green)', () => {
    const mat = rows.find((r) => r.name === 'Materialkosten')!
    expect(mat.decrease).toBeCloseTo(0.81)
    expect(mat.increase).toBe(0)
    expect(mat.base).toBeCloseTo(2.46 - 0.81)
    expect(mat.delta).toBeCloseTo(-0.81)
  })

  it('floats an increase step up from the running level (red)', () => {
    const mfg = rows.find((r) => r.name === 'Fertigungskosten')!
    expect(mfg.increase).toBeCloseTo(1.72)
    expect(mfg.decrease).toBe(0)
    expect(mfg.base).toBeCloseTo(2.46 - 0.81)
  })

  it('accumulates so the last step ends at the NEU level', () => {
    const uebrige = rows.find((r) => r.name === 'Übrige')!
    expect(uebrige.base + uebrige.increase).toBeCloseTo(3.7, 2)
  })

  it('carries the bucket label for the step tooltip', () => {
    expect(rows.find((r) => r.name === 'Materialkosten')!.bucketLabel).toBe('Material')
    expect(rows[0].bucketLabel).toBeNull()
  })

  it('falls back to a solid NEU bar when the composition is not stackable', () => {
    const solid = buildWaterfallData({ ...bridge, endComposition: [] })
    const end = solid[solid.length - 1]
    expect(end.neuTotal).toBeCloseTo(3.7)
    expect(end.Material).toBe(0)
    // with a composition present, neuTotal stays 0
    expect(rows[rows.length - 1].neuTotal).toBe(0)
  })
})
