/* ================================================================
   Datenschicht DataMetric360 - Sammelexport
   ================================================================
   Ein Zugang für die gesamte Oberfläche: REST für Lesen und Schreiben,
   WebSocket für Push, Warteschlange fürs Funkloch. Welche Bildschirme es
   gibt, ist hier bewusst unbekannt - diese Schicht überlebt jeden
   Entwurfsdurchlauf unverändert. */

export * from "./types.ts";
export * from "./umgebung.ts";
export * from "./rest.ts";
export * from "./live.ts";
export * from "./warteschlange.ts";
export * from "./ablageNativ.ts";

import { ENTITAETEN } from "./types.ts";
import type { Fahrt, Fahrzeugstatus, Profil, Tankvorgang } from "./types.ts";
import { HassRest } from "./rest.ts";
import { HassLive } from "./live.ts";
import { Warteschlange } from "./warteschlange.ts";

/** Eingabefelder für Tankvorgänge. Die Namen sind die des Backends
    (belegverarbeitung.py), nicht die des Datensatzes - deshalb "liter" statt
    "liters" und "kosten" statt "fuel_total_eur". */
export interface TankvorgangFelder {
  ts?: string;
  liter?: number | null;
  kosten?: number | null;
  km?: number | null;
  ersparnis?: number | null;
  station?: string | null;
  distanz?: number | null;
  kraftstoff?: string | null;
}

/** Bündelt die drei Bausteine und bildet die Fachvorgänge ab, die das alte
    Dashboard über hass.callService erledigt hat. */
export class DataMetricApi {
  readonly rest: HassRest;
  readonly live: HassLive;
  readonly warteschlange: Warteschlange;

  constructor() {
    this.rest = new HassRest();
    this.live = new HassLive();
    this.warteschlange = new Warteschlange(this.rest);

    /* Sobald die Verbindung wieder steht, wartende Änderungen nachliefern -
       ohne dass die Oberfläche etwas anstoßen muss. */
    this.live.aufVerbindung((zustand) => {
      if (zustand === "verbunden") void this.warteschlange.abarbeiten();
    });
  }

  /* ------------------------------------------------------------ Lesen */

  profilLesen(): Promise<Profil> {
    return this.rest.datenLesen<Profil>(ENTITAETEN.profil);
  }

  fahrtenLesen(): Promise<Fahrt[]> {
    return this.rest.datenLesen<Fahrt[]>(ENTITAETEN.fahrten);
  }

  tankvorgaengeLesen(): Promise<Tankvorgang[]> {
    return this.rest.datenLesen<Tankvorgang[]>(ENTITAETEN.tankvorgaenge);
  }

  fahrzeugstatusLesen(): Promise<Fahrzeugstatus> {
    return this.rest.datenLesen<Fahrzeugstatus>(ENTITAETEN.fahrzeugstatus);
  }

  /* --------------------------------------------------------- Schreiben
     Alle schreibenden Vorgänge laufen über die Warteschlange, nicht direkt
     über rest.dienstAufrufen(). Damit verhält sich die App im Funkloch
     genauso wie mit Netz - nur eben zeitversetzt. */

  profilSchreiben(profil: Profil): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_profil_schreiben",
      { profil_json: JSON.stringify(profil) },
      "Fahrzeugdaten speichern",
    );
  }

  belegHochladen(pdfBase64: string, dateiname: string, tankId?: string): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_beleg_hochladen",
      { pdf_base64: pdfBase64, dateiname, ...(tankId ? { tank_id: tankId } : {}) },
      `Beleg „${dateiname}" hochladen`,
    );
  }

  /** Legt eine Fahrt von Hand an — für Fahrten ohne automatische Erkennung. */
  fahrtAnlegen(tsStart: string, tsEnde: string, art: "privat" | "arbeitsweg"): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_fahrt_manuell_anlegen",
      { ts_start: tsStart, ts_end: tsEnde, art },
      "Fahrt eintragen",
    );
  }

  fahrtLoeschen(tripId: string): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_fahrt_loeschen",
      { trip_id: tripId },
      "Fahrt löschen",
    );
  }

  /** Felder eines Tankvorgangs, wie sie das Backend erwartet (deutsche
      Parameternamen — belegverarbeitung.py). */
  tankvorgangAnlegen(felder: TankvorgangFelder): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_tankvorgang_manuell",
      { ...felder },
      "Tankvorgang eintragen",
    );
  }

  tankvorgangAktualisieren(tankId: string, felder: TankvorgangFelder): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_tankvorgang_aktualisieren",
      { tank_id: tankId, ...felder },
      "Tankvorgang ändern",
    );
  }

  tankvorgangLoeschen(tankId: string): Promise<unknown> {
    return this.warteschlange.einreihen(
      "pyscript",
      "audi_dashboard_tankvorgang_loeschen",
      { tank_id: tankId },
      "Tankvorgang löschen",
    );
  }

  /** Stößt eine sofortige Aktualisierung im Backend an (Pull-to-refresh). */
  jetztAktualisieren(): Promise<unknown> {
    return this.rest.dienstAufrufen("pyscript", "audi_dashboard_jetzt_aktualisieren");
  }
}
