// @vitest-environment jsdom
import { afterEach, describe, expect, it } from 'vitest'
import { cleanup, render, screen } from '@testing-library/react'
import ProjectKpiSection from '../kpi-section'

afterEach(() => {
  cleanup()
})

const EMPTY_PROPS = {
  projectId: 'proj-1',
  factoryAnalysis: null,
  qaf: null,
  valueStream: null,
  valueStreamHref: '/wertstrom',
  measures: null,
}

describe('ProjectKpiSection', () => {
  // No Demo-badge tests here: the badge lives solely in the sticky
  // ProjectHeader (see kpi-section.tsx's Props comment, PR #347 review fix).
  it('renders no Demo badge of its own (header owns it)', () => {
    render(<ProjectKpiSection {...EMPTY_PROPS} />)
    expect(screen.queryByText('Demo')).toBeNull()
  })

  it('renders a clean empty tile per module when no data exists at all', () => {
    render(<ProjectKpiSection {...EMPTY_PROPS} />)
    expect(screen.getByText('Keine Fabrikanalyse vorhanden')).toBeTruthy()
    expect(screen.getByText('Keine Maßnahmen vorhanden')).toBeTruthy()
    // QAF and Wertstrom both use the generic "Keine Daten" copy — expect two.
    expect(screen.getAllByText('Keine Daten')).toHaveLength(2)
  })

  it('links each empty tile to its module create/entry point', () => {
    render(<ProjectKpiSection {...EMPTY_PROPS} />)
    expect(
      screen.getByRole('link', { name: /Fabrikanalyse anlegen/ }).getAttribute('href'),
    ).toBe('/fabrikanalyse/proj-1')
    expect(screen.getByRole('link', { name: /Zum QAF-Vergleich/ }).getAttribute('href')).toBe(
      '/project/proj-1/qaf',
    )
    expect(screen.getByRole('link', { name: /Wertstrom anlegen/ }).getAttribute('href')).toBe(
      '/wertstrom',
    )
    expect(screen.getByRole('link', { name: /Zu den Maßnahmen/ }).getAttribute('href')).toBe(
      '/project/proj-1/workshop',
    )
  })

  it('renders real Fabrikanalyse numbers and the direct module link when data exists', () => {
    render(
      <ProjectKpiSection
        {...EMPTY_PROPS}
        factoryAnalysis={{
          answeredCount: 4,
          scoreAvg: 2.5,
          fulfilledCount: 2,
          partialCount: 1,
          notFulfilledCount: 1,
        }}
      />,
    )
    expect(screen.getByText('2.5')).toBeTruthy()
    expect(screen.getByText('4 Frage(n) beantwortet')).toBeTruthy()
    // Anteile (nicht Rohzahlen): 2/4, 1/4, 1/4 beantwortet.
    expect(screen.getByText(/50 %\s*erfüllt/)).toBeTruthy()
    expect(screen.getAllByText(/25 %/)).toHaveLength(2) // teilweise + nicht erfüllt
    expect(
      screen.getByRole('link', { name: /Zur Fabrikanalyse/ }).getAttribute('href'),
    ).toBe('/fabrikanalyse/proj-1')
  })

  it('shows "—" for the Fabrikanalyse share breakdown when nothing is answered yet (no divide-by-zero)', () => {
    render(
      <ProjectKpiSection
        {...EMPTY_PROPS}
        factoryAnalysis={{
          answeredCount: 0,
          scoreAvg: null,
          fulfilledCount: 0,
          partialCount: 0,
          notFulfilledCount: 0,
        }}
      />,
    )
    expect(screen.getAllByText(/—\s*(erfüllt|teilweise|nicht erfüllt)/)).toHaveLength(3)
  })

  it('renders a partial QAF tile (comparison found, no persisted summary KPIs — e.g. Multi-QAF)', () => {
    render(
      <ProjectKpiSection
        {...EMPTY_PROPS}
        qaf={{ comparisonTitle: 'Variante A', partNumber: '123', kpis: null }}
      />,
    )
    expect(screen.getByText(/Variante A — keine Kernkennzahlen verfügbar/)).toBeTruthy()
  })

  it('renders the Wertstrom map id in the link once a map exists', () => {
    render(
      <ProjectKpiSection
        {...EMPTY_PROPS}
        valueStream={{ title: 'Linie 1', leadTimeSec: 120, vaRatioPct: 25, bottleneckName: 'Station B' }}
        valueStreamHref="/wertstrom/vsm-42"
      />,
    )
    expect(screen.getByText('2 min')).toBeTruthy()
    expect(screen.getByText(/Station B/)).toBeTruthy()
    expect(
      screen.getByRole('link', { name: /Zum Wertstrom/ }).getAttribute('href'),
    ).toBe('/wertstrom/vsm-42')
  })

  it('renders Maßnahmen totals when data exists — all three buckets visible and summing to total', () => {
    render(<ProjectKpiSection {...EMPTY_PROPS} measures={{ total: 6, open: 2, inProgress: 2, done: 2 }} />)
    expect(screen.getByText('6')).toBeTruthy()
    expect(screen.getByText('2 offen')).toBeTruthy()
    expect(screen.getByText('2 in Arbeit')).toBeTruthy()
    expect(screen.getByText('2 erledigt')).toBeTruthy()
  })

  it('renders the QAF happy path — signed German percent formatting and cost-delta coloring (PR #347 review fix)', () => {
    const kpi = (deltaPercent: number | null) => ({
      alt: 100,
      neu: 100,
      deltaAbsolute: 0,
      deltaPercent,
    })
    render(
      <ProjectKpiSection
        {...EMPTY_PROPS}
        qaf={{
          comparisonTitle: 'Award vs. aktuell',
          partNumber: '61.35-000',
          kpis: {
            quotationPrice: kpi(1.5),
            materialCosts: kpi(0),
            totalProductionCosts: kpi(-3.25),
            currency: 'EUR',
          },
        }}
      />,
    )
    // Headline: cost REDUCTION → negative percent, one decimal, comma, green class.
    const headline = screen.getByText('-3,3 %')
    expect(headline.className).toContain('text-success-text')
    // Increase gets an explicit plus sign; zero stays unsigned.
    expect(screen.getByText(/Angebotspreis \+1,5 %/)).toBeTruthy()
    expect(screen.getByText(/Material 0,0 %/)).toBeTruthy()
  })
})
