'use client'

// Biggest price movers — tornado (KAR-840, V11 section 4).
// Horizontal bars sorted by |Δ|, red = teurer / grün = günstiger, grey ALT
// value left of the axis label, interactive top-N filter (re-filter only,
// no recompute — V11 behaviour). Height grows with the row count.

import { useState } from 'react'
import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  ReferenceLine,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts'
import { selectMovers, type Movers, type TopN } from '@/lib/qaf-differences'
import { moneyFormatter } from './format'

export const TOP_N_OPTIONS: TopN[] = [5, 12, 20, 'all']

/** Dynamic chart height: 30px per row + axis space, readable minimum. */
export function tornadoHeight(rowCount: number): number {
  return Math.max(120, rowCount * 30 + 70)
}

/** Axis column width from the longest label (~6.5px/char), clamped 120–280.
 *  Longer labels still fit — the tooltip always shows the full name. */
export function yAxisWidth(labels: string[]): number {
  const maxLen = labels.reduce((m, l) => Math.max(m, l.length), 0)
  return Math.min(280, Math.max(120, Math.round(maxLen * 6.5) + 16))
}

interface Props {
  movers: Movers
  currency: string | null
}

export default function QafMoversChart({ movers, currency }: Props) {
  const [topN, setTopN] = useState<TopN>(12)
  const fmt = moneyFormatter(currency, { signed: true })
  // '*' mirrors the uncertain-match caveat of the Fertigungskosten table.
  const selection = selectMovers(movers.rows, topN)
  const rows = selection.shown.map((r) => ({
    ...r,
    displayLabel: r.uncertain ? `${r.label} *` : r.label,
  }))
  const anyUncertain = rows.some((r) => r.uncertain)

  // R-20 (Befund F-16): Wenn die Zeilensumme nicht zur Blattzeile passt, aus der
  // sie stammt, muss das sichtbar sein. Im Anlassfall zeigten drei Schritte
  // zusammen +1,95 bei einem Blattdelta von +1,06 — der Widerspruch war
  // nirgends ausgewiesen, und wer nachrechnete, verlor das Vertrauen in alles
  // Übrige. `passed === null` heisst „nicht geprüft" und darf keine Warnung
  // erzeugen.
  const rec = movers.reconciliation

  return (
    <div className="space-y-2" data-testid="qaf-movers-chart">
      {rec.passed === false && rec.residual !== null && (
        <p className="text-muted-foreground text-xs" data-testid="qaf-movers-reconciliation">
          Die Positionen erklären {fmt(movers.totalDelta)} von {fmt(rec.reference!)}
          {rec.label ? ` (${rec.label})` : ''} — Differenz {fmt(rec.residual)}. Die Liste ist damit nicht
          vollständig.
        </p>
      )}
      {movers.rows.length > 1 && (
        <div className="flex items-center gap-1 text-xs">
          <span className="text-muted-foreground mr-1">Top</span>
          {TOP_N_OPTIONS.map((n) => (
            <button
              key={String(n)}
              type="button"
              onClick={() => setTopN(n)}
              className={`rounded border px-2 py-0.5 ${
                topN === n
                  ? 'border-primary bg-primary-soft text-primary font-medium'
                  : 'border-border text-muted-foreground hover:text-foreground'
              }`}
            >
              {n === 'all' ? 'Alle' : n}
            </button>
          ))}
          <span className="ml-2 text-muted-foreground">
            {selection.shown.length} von {selection.ofTotal} Positionen
            {selection.truncated && <> · Rest {fmt(selection.residualSum)}</>}
          </span>
        </div>
      )}
      <div style={{ height: tornadoHeight(rows.length) }} className="w-full">
        <ResponsiveContainer width="100%" height="100%">
          <BarChart data={rows} layout="vertical" margin={{ top: 8, right: 60, left: 8, bottom: 4 }}>
            <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" horizontal={false} />
            <XAxis
              type="number"
              tick={{ fontSize: 11 }}
              tickLine={false}
              axisLine={{ stroke: 'var(--border)' }}
              tickFormatter={(v: number) => fmt(v)}
            />
            <YAxis
              type="category"
              dataKey="displayLabel"
              width={yAxisWidth(rows.map((r) => r.displayLabel))}
              tick={{ fontSize: 11 }}
              tickLine={false}
              axisLine={false}
            />
            <Tooltip
              formatter={(value) => [fmt(Number(value ?? 0)), 'Δ Angebotswert']}
              cursor={{ fill: 'var(--muted)' }}
              contentStyle={{ fontSize: 12, borderRadius: 2, border: '1px solid var(--border)' }}
            />
            <ReferenceLine x={0} stroke="var(--border)" />
            <Bar dataKey="delta" isAnimationActive={false} radius={[0, 2, 2, 0]}>
              {rows.map((r, i) => (
                <Cell key={i} fill={r.delta > 0 ? 'var(--destructive)' : 'var(--success-text)'} />
              ))}
            </Bar>
          </BarChart>
        </ResponsiveContainer>
      </div>
      {anyUncertain && (
        <p className="text-xs text-muted-foreground">
          * Delta aus einem unsicheren Prozessschritt-Match — vor Eskalation prüfen.
        </p>
      )}
    </div>
  )
}
