'use client'

// Projection & potential in € (KAR-840, V11 section 5 — interactive).
// Editable year/volume table (+Jahr), Δ-per-unit override with reset, defend
// quota slider — every input recomputes immediately (V11 rebuild()).
//
// KAR-985: when a `comparisonId` is passed (qaf-comparison-detail.tsx's
// Section 12 usage — its help text now says so), edits are debounced-
// autosaved into qaf_comparison.user_inputs.projection via the shared
// qaf-autosave hook, no explicit Save button. `comparisonId` is OPTIONAL and
// omitted by qaf-g60-detail.tsx's own usage of this same component, which
// keeps its pre-KAR-985 session-only behavior unchanged (that view's own
// help text still says so, correctly — see that file).
import { useCallback, useEffect, useMemo, useState } from 'react'
import {
  Bar,
  CartesianGrid,
  Cell,
  ComposedChart,
  Legend,
  Line,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts'
import {
  computeProjection,
  defaultProjectionYears,
  type ProjectionYearInput,
  type QafProjectionUserInputs,
} from '@/lib/qaf-differences'
import { saveQafComparisonUserInputs } from '@/app/qaf-differences/qaf-comparison-user-inputs-actions'
import { useDebouncedAutosave, QafAutosaveIndicator } from './qaf-autosave'
import { moneyFormatter, parseNumericInput } from './format'

const M_EUR_FMT = new Intl.NumberFormat('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })

/** Totals in millions, V11 style ("0,00 M€"); unknown codes fall back verbose. */
export function formatMEur(value: number, currency: string | null): string {
  const millions = M_EUR_FMT.format(value / 1_000_000)
  return currency === null || currency === 'EUR' ? `${millions} M€` : `${millions} Mio. ${currency}`
}

/** Immutable single-row update for the editable year table. */
export function updateYearRow(
  rows: ProjectionYearInput[],
  index: number,
  patch: Partial<ProjectionYearInput>,
): ProjectionYearInput[] {
  return rows.map((r, i) => (i === index ? { ...r, ...patch } : r))
}

/** Append the next consecutive year (V11 '+Jahr'). */
export function addYearRow(rows: ProjectionYearInput[], fallbackStartYear = 2026): ProjectionYearInput[] {
  const nextYear = rows.length > 0 ? rows[rows.length - 1].year + 1 : fallbackStartYear
  return [...rows, { year: nextYear, volume: 0, included: true }]
}

/** Prepend the previous year (Kais: past years must be addable too). */
export function prependYearRow(rows: ProjectionYearInput[], fallbackStartYear = 2026): ProjectionYearInput[] {
  const prevYear = rows.length > 0 ? rows[0].year - 1 : fallbackStartYear
  return [{ year: prevYear, volume: 0, included: true }, ...rows]
}

/** Remove one year row entirely (vs. just unchecking it). */
export function removeYearRow(rows: ProjectionYearInput[], index: number): ProjectionYearInput[] {
  return rows.filter((_, i) => i !== index)
}

interface Props {
  /** Computed Δ per unit (NEU − ALT quotation price). */
  deltaComputed: number
  currency: string | null
  /** Pre-filled years/volumes (G60: real Stückzahlen from the QAF). */
  initialYears?: ProjectionYearInput[]
  /** KAR-985: enables debounced autosave into this comparison's
   * qaf_comparison.user_inputs.projection when set — see file header. */
  comparisonId?: string
  /** KAR-985: previously-saved state, if any — takes priority over
   * `initialYears` (a user's own edits are never silently replaced by the
   * QAF's raw volumes again on reload). `null`/absent = nothing saved yet. */
  initialUserInputs?: QafProjectionUserInputs | null
}

function inputText(value: number): string {
  return String(Number(value.toFixed(4)))
}

/**
 * Controlled number input that keeps the RAW text while focused (an
 * in-progress "0." or cleared field is never reformatted under the cursor)
 * and only commits finite values — NaN can never reach the projection.
 * Exported: the G60 scenario editor reuses the exact same commit semantics.
 */
export function NumericInput({
  value,
  onCommit,
  min,
  step,
  className,
  ariaLabel,
}: {
  value: number
  onCommit: (n: number) => void
  min?: number
  step?: string
  className?: string
  ariaLabel?: string
}) {
  const [text, setText] = useState(() => inputText(value))
  const [focused, setFocused] = useState(false)

  useEffect(() => {
    if (!focused) setText(inputText(value))
  }, [value, focused])

  return (
    <input
      type="number"
      min={min}
      step={step}
      value={text}
      aria-label={ariaLabel}
      className={className}
      onFocus={() => setFocused(true)}
      onBlur={() => {
        setFocused(false)
        setText(inputText(value))
      }}
      onChange={(e) => {
        setText(e.target.value)
        const n = parseNumericInput(e.target.value)
        if (n !== null) onCommit(min !== undefined ? Math.max(min, n) : n)
      }}
    />
  )
}

export default function QafProjection({ deltaComputed, currency, initialYears, comparisonId, initialUserInputs }: Props) {
  const [years, setYears] = useState<ProjectionYearInput[]>(() =>
    initialUserInputs?.years ??
    (initialYears && initialYears.length > 0 ? initialYears : defaultProjectionYears(new Date().getFullYear(), 5)),
  )
  const [overrideDelta, setOverrideDelta] = useState<number | null>(initialUserInputs?.overrideDelta ?? null)
  const [defendPct, setDefendPct] = useState(initialUserInputs?.defendPct ?? 0)

  const deltaPerUnit = overrideDelta ?? deltaComputed
  const projection = useMemo(() => computeProjection(years, deltaPerUnit, defendPct), [years, deltaPerUnit, defendPct])
  const fmt = moneyFormatter(currency)
  const hasVolume = projection.totals.vol > 0

  // KAR-985: debounced autosave — a no-op (`enabled: false`) when no
  // comparisonId was passed (qaf-g60-detail.tsx's usage), see file header.
  const projectionState = useMemo<QafProjectionUserInputs>(
    () => ({ years, overrideDelta, defendPct }),
    [years, overrideDelta, defendPct],
  )
  const saveProjection = useCallback(
    async (value: QafProjectionUserInputs) => {
      if (!comparisonId) return { ok: true as const }
      return saveQafComparisonUserInputs(comparisonId, { projection: value })
    },
    [comparisonId],
  )
  const { status: autosaveStatus, error: autosaveError } = useDebouncedAutosave(projectionState, saveProjection, {
    enabled: Boolean(comparisonId),
  })

  return (
    <div className="space-y-4" data-testid="qaf-projection">
      <div className="flex flex-wrap items-end gap-x-6 gap-y-3 text-sm">
        <label className="space-y-1">
          <span className="block text-xs text-muted-foreground">Mehrkosten je Einheit (Δ)</span>
          <span className="flex items-center gap-1">
            <NumericInput
              value={deltaPerUnit}
              step="0.01"
              onCommit={(n) => setOverrideDelta(n)}
              ariaLabel="Mehrkosten je Einheit"
              className="w-28 rounded border border-border bg-card px-2 py-1 text-right tabular-nums"
            />
            {overrideDelta !== null && (
              <button
                type="button"
                onClick={() => setOverrideDelta(null)}
                className="rounded border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground"
                title={`Zurück auf berechnetes Δ (${fmt(deltaComputed)})`}
              >
                Reset
              </button>
            )}
          </span>
        </label>
        <label className="grow max-w-xs space-y-1">
          <span className="block text-xs text-muted-foreground">
            Abgewehrte Erhöhung: <span className="font-medium text-foreground">{Math.round(defendPct * 100)} %</span>
          </span>
          <input
            type="range"
            min={0}
            max={100}
            value={Math.round(defendPct * 100)}
            onChange={(e) => setDefendPct(Number(e.target.value) / 100)}
            className="w-full accent-[color:var(--primary)]"
          />
        </label>
        {comparisonId && <QafAutosaveIndicator status={autosaveStatus} error={autosaveError} className="ml-auto self-center" />}
      </div>

      <div className="overflow-x-auto">
        <table className="w-auto text-sm">
          <thead>
            <tr className="border-b border-border text-left text-muted-foreground">
              <th className="py-2 pr-4 font-medium">zählt</th>
              <th className="py-2 pr-4 font-medium">Jahr</th>
              <th className="py-2 pr-4 text-right font-medium">Volumen (editierbar)</th>
              <th className="py-2 text-right font-medium">Δ restant/Jahr</th>
              <th className="py-2 pl-2 print:hidden" aria-label="Aktionen" data-export-exclude />
            </tr>
          </thead>
          <tbody>
            {projection.perYear.map((row, i) => (
              <tr key={row.year} className="border-b border-border/60">
                <td className="py-1.5 pr-4">
                  <input
                    type="checkbox"
                    checked={row.included}
                    onChange={(e) => setYears((r) => updateYearRow(r, i, { included: e.target.checked }))}
                    aria-label={`Jahr ${row.year} einbeziehen`}
                  />
                </td>
                <td className="py-1.5 pr-4 tabular-nums">{row.year}</td>
                <td className="py-1.5 pr-4 text-right">
                  <NumericInput
                    value={row.volume}
                    min={0}
                    onCommit={(n) => setYears((r) => updateYearRow(r, i, { volume: n }))}
                    ariaLabel={`Volumen ${row.year}`}
                    className="w-28 rounded border border-border bg-card px-2 py-1 text-right tabular-nums"
                  />
                </td>
                <td className={`py-1.5 text-right tabular-nums ${row.remaining > 0 ? 'text-destructive' : row.remaining < 0 ? 'text-success-text' : 'text-muted-foreground'}`}>
                  {fmt(row.remaining)}
                </td>
                <td className="py-1.5 pl-2 text-right print:hidden" data-export-exclude>
                  <button
                    type="button"
                    onClick={() => setYears((r) => removeYearRow(r, i))}
                    aria-label={`Jahr ${row.year} löschen`}
                    className="text-muted-foreground hover:text-destructive"
                  >
                    ×
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        <div className="mt-2 flex gap-2 print:hidden" data-export-exclude>
          <button
            type="button"
            onClick={() => setYears((r) => prependYearRow(r, new Date().getFullYear()))}
            className="rounded border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground"
          >
            + Jahr davor
          </button>
          <button
            type="button"
            onClick={() => setYears((r) => addYearRow(r, new Date().getFullYear()))}
            className="rounded border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground"
          >
            + Jahr danach
          </button>
        </div>
      </div>

      <p className="text-sm">
        <span className="text-muted-foreground">
          Mehr-/Minderkosten über gewählte Laufzeit ({projection.totals.nYears} Jahre, Σ{' '}
          {new Intl.NumberFormat('de-DE').format(projection.totals.vol)} Stück):
        </span>{' '}
        <span
          className={`font-bold tabular-nums ${projection.totals.remaining > 0 ? 'text-destructive' : projection.totals.remaining < 0 ? 'text-success-text' : 'text-foreground'}`}
        >
          {formatMEur(projection.totals.remaining, currency)}
        </span>
        {defendPct > 0 && projection.totals.defended > 0 && (
          <span className="text-xs text-muted-foreground"> (abgewehrt: {formatMEur(projection.totals.defended, currency)})</span>
        )}
      </p>

      {hasVolume && (
        <div className="h-64 w-full">
          <ResponsiveContainer width="100%" height="100%">
            <ComposedChart data={projection.perYear} margin={{ top: 8, right: 8, left: 8, bottom: 4 }}>
              <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
              <XAxis dataKey="year" tick={{ fontSize: 11 }} tickLine={false} axisLine={{ stroke: 'var(--border)' }} />
              <YAxis yAxisId="year" tick={{ fontSize: 11 }} tickLine={false} axisLine={false} tickFormatter={(v: number) => fmt(v)} width={90} />
              <YAxis yAxisId="cum" orientation="right" tick={{ fontSize: 11 }} tickLine={false} axisLine={false} tickFormatter={(v: number) => fmt(v)} width={90} />
              <Tooltip
                formatter={(value, name) => [fmt(Number(value ?? 0)), name === 'remaining' ? 'Δ/Jahr' : 'kumuliert']}
                cursor={{ fill: 'var(--muted)' }}
                contentStyle={{ fontSize: 12, borderRadius: 2, border: '1px solid var(--border)' }}
              />
              <Legend
                wrapperStyle={{ fontSize: 12 }}
                formatter={(value: string) => (value === 'remaining' ? 'Δ je Jahr (nach Abwehr)' : 'kumuliert')}
              />
              <Bar yAxisId="year" dataKey="remaining" isAnimationActive={false} radius={[2, 2, 0, 0]}>
                {projection.perYear.map((r, i) => (
                  <Cell key={i} fill={r.remaining > 0 ? 'var(--destructive)' : 'var(--success-text)'} />
                ))}
              </Bar>
              <Line yAxisId="cum" dataKey="cumRemaining" name="cumRemaining" stroke="var(--qaf-stand-neu)" strokeWidth={2} dot={{ r: 3 }} isAnimationActive={false} />
            </ComposedChart>
          </ResponsiveContainer>
        </div>
      )}
    </div>
  )
}
