/**
 * „Daten importieren aus Home Assistant" — Zeitraum wählen, importieren
 * lassen, Ergebnis zeigen. Vorlage: `vImportPopup()` im Panel
 * (audi-dashboard-app.js), Backend: `pyscript/historienimport.py`.
 *
 * Warum ein Fenster und keine Kachel mit zwei Feldern: der Import ist keine
 * Einstellung, die man nebenbei ändert, sondern ein einmaliger Vorgang mit
 * Start, Laufzeit und Ergebnis. Er gehört deshalb in einen eigenen,
 * abgeschlossenen Schritt — deckungsgleich mit dem Panel.
 *
 * Der eigentliche Lauf passiert im Backend. Es meldet seinen Stand über die
 * Entität `sensor.audi_dashboard_import_status`; hier wird sie im
 * Sekundentakt gelesen, bis sie „fertig" oder „fehler" sagt. Ein Poll statt
 * eines Abwartens des Dienstaufrufs, weil pyscript-Dienste sofort
 * zurückkehren, während die Arbeit im Hintergrund weiterläuft.
 */

import { useEffect, useRef, useState } from "react"

import { ActionButton, Feld, Popup } from "@audi-dash/ui"

import type { DataMetricApi, ImportErgebnis } from "../api"
import { datumZeit, de } from "../format"

/** Vorbelegung: die letzten 30 Tage, im Format von <input
    type="datetime-local"> (Ortszeit, ohne Zeitzone, minutengenau) — genau
    das, was der Dienst als Ortszeit interpretiert. */
function zeitraumVorgabe() {
  const alsFeld = (d: Date) =>
    new Date(d.getTime() - d.getTimezoneOffset() * 60000).toISOString().slice(0, 16)
  const jetzt = new Date()
  return { von: alsFeld(new Date(jetzt.getTime() - 30 * 86400000)), bis: alsFeld(jetzt) }
}

export function ergebnisText(d: ImportErgebnis): string {
  const anzahl = (n: number, eins: string, viele: string) => `${de(n)} ${n === 1 ? eins : viele}`
  const teile = [anzahl(d.fahrten_angelegt ?? 0, "Fahrt", "Fahrten") + " angelegt"]
  if (d.fahrten_uebersprungen) teile.push(`${de(d.fahrten_uebersprungen)} bereits vorhanden`)
  if (d.fahrten_zu_kurz)
    teile.push(
      anzahl(
        d.fahrten_zu_kurz,
        "Zündung zu kurz für eine Fahrt",
        "Zündungen zu kurz für eine Fahrt",
      ),
    )
  if (d.tankvorgaenge_angelegt)
    teile.push(anzahl(d.tankvorgaenge_angelegt, "Tankvorgang", "Tankvorgänge"))
  if (d.batterie_tage)
    teile.push(anzahl(d.batterie_tage, "Tag Batteriespannung", "Tage Batteriespannung"))
  return teile.join(" · ")
}

export function HistorienImport({
  offen,
  beiSchliessen,
  api,
  beiFertig,
}: {
  offen: boolean
  beiSchliessen: () => void
  api: DataMetricApi
  /** Nach einem erfolgreichen Lauf: Fahrten-/Tankvorgangslisten neu laden. */
  beiFertig: () => void
}) {
  const [von, setzeVon] = useState(() => zeitraumVorgabe().von)
  const [bis, setzeBis] = useState(() => zeitraumVorgabe().bis)
  const [laeuft, setzeLaeuft] = useState(false)
  const [fehler, setzeFehler] = useState<string | null>(null)
  const [ergebnis, setzeErgebnis] = useState<ImportErgebnis | null>(null)
  // Nach dem Schließen darf keine noch laufende Warteschleife mehr in den
  // State schreiben - React warnt sonst zu Recht über ein Update auf einer
  // ausgehängten Komponente, und ein späterer Lauf würde ein längst
  // weggeklicktes Ergebnis wieder einblenden.
  const aktiv = useRef(true)
  useEffect(() => {
    aktiv.current = true
    return () => {
      aktiv.current = false
    }
  }, [])

  // Beim erneuten Öffnen wieder mit den Feldern anfangen, nicht mit dem
  // Ergebnis des letzten Laufs.
  useEffect(() => {
    if (offen) {
      setzeErgebnis(null)
      setzeFehler(null)
      setzeLaeuft(false)
    }
  }, [offen])

  const schliessen = () => {
    if (laeuft) return
    beiSchliessen()
  }

  const starten = async () => {
    if (laeuft) return
    if (!von || !bis) {
      setzeFehler("Bitte Start und Ende wählen.")
      return
    }
    if (von >= bis) {
      setzeFehler("Das Ende muss nach dem Start liegen.")
      return
    }
    setzeFehler(null)
    setzeLaeuft(true)

    try {
      await api.historieImportieren(von, bis)
    } catch (err) {
      if (!aktiv.current) return
      setzeLaeuft(false)
      setzeFehler(err instanceof Error ? err.message : "Der Import konnte nicht gestartet werden.")
      return
    }

    // Bis zu zwei Minuten - ein Jahr Verlauf über sechs Sensoren braucht
    // seine Zeit, und ein zu früher Abbruch sähe wie ein Fehlschlag aus,
    // obwohl der Import im Hintergrund sauber zu Ende läuft.
    for (let versuch = 0; versuch < 120; versuch++) {
      await new Promise((r) => setTimeout(r, 1000))
      if (!aktiv.current) return
      let stand: { zustand: string; daten: ImportErgebnis }
      try {
        stand = await api.importStatusLesen()
      } catch {
        continue
      }
      if (!aktiv.current) return
      if (stand.zustand === "fertig") {
        setzeLaeuft(false)
        setzeErgebnis(stand.daten)
        beiFertig()
        return
      }
      if (stand.zustand === "fehler") {
        setzeLaeuft(false)
        setzeFehler(stand.daten.meldung ?? "Der Import ist fehlgeschlagen.")
        return
      }
    }
    if (!aktiv.current) return
    setzeLaeuft(false)
    setzeFehler("Der Import dauert ungewöhnlich lange — er läuft im Hintergrund weiter.")
  }

  const fertig = ergebnis !== null && !laeuft

  return (
    <Popup open={offen} onClose={schliessen} variant="form" anchor="center">
      <span className="ads-eyebrow">Daten importieren aus Home Assistant</span>

      {fertig ? (
        <>
          <p className="dm-importergebnis">{ergebnisText(ergebnis)}</p>
          {!ergebnis.fahrten_angelegt && (
            <p className="dm-fussnote">
              {ergebnis.ab_wann_daten
                ? `Aufgezeichnet ist in diesem Zeitraum ab ${datumZeit(ergebnis.ab_wann_daten)}. Weiter zurück bewahrt Home Assistant nichts mehr auf.`
                : "Für diesen Zeitraum liegt in Home Assistant kein Verlauf mehr vor."}
            </p>
          )}
          <div style={{ marginTop: 14 }}>
            <ActionButton onClick={beiSchliessen}>Fertig</ActionButton>
          </div>
        </>
      ) : (
        <>
          <Feld label="Von">
            <input
              className="dm-eingabe"
              type="datetime-local"
              value={von}
              onChange={(e) => setzeVon(e.target.value)}
            />
          </Feld>
          <Feld label="Bis" last>
            <input
              className="dm-eingabe"
              type="datetime-local"
              value={bis}
              onChange={(e) => setzeBis(e.target.value)}
            />
          </Feld>
          {fehler && <p className="dm-fussnote dm-fussnote--warnung">{fehler}</p>}
          <p className="dm-fussnote">
            Bereits erfasste Fahrten bleiben unangetastet — überschneidet sich ein Zeitraum, wird
            er übersprungen statt doppelt angelegt.
          </p>
          <div style={{ marginTop: 14 }}>
            <ActionButton onClick={() => void starten()} disabled={laeuft}>
              {laeuft ? "Importiere …" : "Importieren"}
            </ActionButton>
          </div>
          <div style={{ marginTop: 10 }}>
            <ActionButton onClick={schliessen} disabled={laeuft}>
              Abbrechen
            </ActionButton>
          </div>
        </>
      )}
    </Popup>
  )
}
