/**
 * Batteriespannung im Verlauf. Vorlage: `vBatterieverlauf()`.
 *
 * Das Diagramm ist von Hand als SVG gezeichnet — wie im alten Panel und aus
 * demselben Grund: eine Diagrammbibliothek wäre um ein Vielfaches größer als
 * die ganze Seite.
 *
 * Wichtig für die Einordnung: Der Ladezustand wird aus der **Tagesminimum**-
 * Spannung geschätzt (Ruhespannung kurz nach dem Start, bevor die Lichtmaschine
 * anhebt); Werte über 12,8 V gelten als „während der Fahrt gemessen" und
 * taugen nicht als Ruhewert.
 */

import { useEffect, useState } from "react"

import { Tile } from "@audi-dash/ui"

import { ENTITAETEN } from "../api"
import { useDaten } from "../daten/DatenKontext"
import { datum, de } from "../format"
import { Leerzustand, Wertzeile, Werteliste } from "./bausteine"

interface Tageswert {
  datum: string
  min: number | null
  max: number | null
  min_ts?: string
  max_ts?: string
}

/** Ab hier gilt eine Messung als nicht mehr in Ruhe aufgenommen - alles
    darüber ist schon Lichtmaschinenspannung, nicht mehr Ruhespannung. */
const AGM_RUHE_MAX_V = 12.8

/** Spannung → Ladezustand für eine AGM-Batterie in Ruhe. */
const LADEKURVE: [number, number][] = [
  [12.8, 100],
  [12.6, 90],
  [12.4, 75],
  [12.2, 50],
  [12.0, 25],
  [11.8, 10],
]

function ladezustand(spannung: number): number | null {
  if (spannung > AGM_RUHE_MAX_V) return null
  const ersterTreffer = LADEKURVE.find(([v]) => spannung >= v)
  if (ersterTreffer) return ersterTreffer[1]
  return 0
}

export function Batterie() {
  const { api, fahrzeug } = useDaten()
  const [verlauf, setzeVerlauf] = useState<Tageswert[] | null>(null)
  const [fehler, setzeFehler] = useState(false)

  useEffect(() => {
    void api.rest
      .datenLesen<Tageswert[]>(ENTITAETEN.batterieverlauf)
      .then((daten) => setzeVerlauf(Array.isArray(daten) ? daten : []))
      .catch(() => setzeFehler(true))
  }, [api])

  if (fehler) {
    return (
      <Leerzustand
        titel="Verlauf nicht abrufbar"
        text="Der Server hat den Batterieverlauf nicht geliefert. Beim nächsten Aufruf klappt es vielleicht wieder."
      />
    )
  }

  if (!verlauf) return <div className="dm-laden">Verlauf wird geladen …</div>

  const messwerte = verlauf.filter((t) => t.min != null)

  if (messwerte.length === 0) {
    return (
      <Leerzustand
        titel="Keine Messwerte"
        text="Für dieses Fahrzeug liefert die Anbindung derzeit keinen Spannungssensor. Sobald einer verfügbar ist, zeichnet die App den Verlauf hier auf."
      />
    )
  }

  const letzter = messwerte[messwerte.length - 1]!
  const soc = letzter.min != null ? ladezustand(letzter.min) : null

  // Trend als Vergleich früher gegen später — keine echte Kapazitätsmessung.
  const haelfte = Math.floor(messwerte.length / 2)
  const mittel = (liste: Tageswert[]) =>
    liste.length > 0 ? liste.reduce((s, t) => s + (t.min ?? 0), 0) / liste.length : null
  const frueher = mittel(messwerte.slice(0, haelfte))
  const spaeter = mittel(messwerte.slice(haelfte))
  const trend = frueher != null && spaeter != null ? spaeter - frueher : null

  return (
    <>
      <Tile>
        <span className="ads-eyebrow">Ruhespannung</span>
        <div className="dm-detail__kopf">
          <div className="dm-detail__zahl">
            {letzter.min != null ? de(letzter.min, 2) : "—"}
            <span className="dm-detail__einheit">V</span>
          </div>
        </div>
        <Verlaufsdiagramm werte={messwerte} />
        <Werteliste
          kinder={
            <>
              <Wertzeile label="Letzte Messung" wert={datum(letzter.datum)} />
              <Wertzeile
                label="Geschätzter Ladezustand"
                wert={soc != null ? `${de(soc)} %` : "—"}
                zusatz={soc == null ? "Messung nicht in Ruhe aufgenommen" : undefined}
              />
              <Wertzeile
                label="Trend über den Zeitraum"
                wert={trend != null ? `${trend >= 0 ? "+" : ""}${de(trend, 2)} V` : "—"}
              />
              <Wertzeile
                label="Aktuell gemeldet"
                wert={
                  fahrzeug?.batteriespannung != null
                    ? `${de(fahrzeug.batteriespannung, 2)} V`
                    : "—"
                }
              />
            </>
          }
        />
        <p className="dm-fussnote">
          Der Ladezustand wird aus dem Tagesminimum geschätzt — das ist die Spannung kurz nach dem
          Start, bevor die Lichtmaschine sie anhebt. Der Trend vergleicht die frühere mit der
          späteren Hälfte des Zeitraums; er ist ein Hinweis, keine Kapazitätsmessung.
        </p>
      </Tile>
    </>
  )
}

/** Von Hand gezeichnete Verlaufskurve aus Tagesminimum und -maximum. */
function Verlaufsdiagramm({ werte }: { werte: Tageswert[] }) {
  const breite = 320
  const hoehe = 120
  const rand = 4

  const alleWerte = werte.flatMap((t) => [t.min, t.max].filter((v): v is number => v != null))
  const kleinster = Math.min(...alleWerte) - 0.1
  const groesster = Math.max(...alleWerte) + 0.1
  const spanne = Math.max(0.2, groesster - kleinster)

  const x = (i: number) =>
    rand + (i / Math.max(1, werte.length - 1)) * (breite - 2 * rand)
  const y = (v: number) => hoehe - rand - ((v - kleinster) / spanne) * (hoehe - 2 * rand)

  const linie = (auswahl: (t: Tageswert) => number | null) =>
    werte
      .map((t, i) => {
        const v = auswahl(t)
        return v == null ? null : `${i === 0 ? "M" : "L"}${x(i).toFixed(1)},${y(v).toFixed(1)}`
      })
      .filter(Boolean)
      .join(" ")

  return (
    <svg
      className="dm-diagramm"
      viewBox={`0 0 ${breite} ${hoehe}`}
      preserveAspectRatio="none"
      role="img"
      aria-label={`Spannungsverlauf über ${werte.length} Tage`}
    >
      <path d={linie((t) => t.max)} fill="none" stroke="var(--fg3)" strokeWidth="1" />
      <path d={linie((t) => t.min)} fill="none" stroke="var(--red)" strokeWidth="1.5" />
    </svg>
  )
}
