"""Sicherung von Fahrzeugprofil, Fahrten, Tankvorgängen und Sensor-Zuordnung.

Manuell über "Backup jetzt erstellen" in den Einstellungen oder automatisch je
nach einstellungen.backup_intervall im Fahrzeugprofil (aus/täglich/
wöchentlich/monatlich) - immer um 04:00 Uhr, wenn eingestellt. Ein einzelner
täglicher Termin genügt für alle drei Intervalle: wöchentlich läuft nur
montags, monatlich nur am Monatsersten, täglich jeden Tag.

Jede Sicherung ist ein eigener Zeitstempel-Unterordner mit Kopien der vier
Bestände, keine ZIP-Datei - eine Sicherung, in die man ohne Werkzeug
hineinschauen und aus der man eine einzelne Datei zurückkopieren kann, ist im
Ernstfall mehr wert als ein paar gesparte Kilobyte.

entitaeten.json gehört ausdrücklich dazu: ohne sie wäre nach einer
Wiederherstellung die komplette Sensor-Zuordnung aus dem Setup-Menü verloren,
und weil sie sonst nirgends abgelegt ist, gäbe es nichts zurückzuholen.

"Backup exportieren"/"importieren" in der Oberfläche laufen dagegen rein über
den Browser (aktuell geladenes Profil + Fahrten + Tankvorgänge als eine
JSON-Datei); wiederherstellen() hier ist das Gegenstück zum Import, das die
Bestände wieder komplett überschreibt.
"""

from __future__ import annotations

import datetime
import json
import logging
import os
import shutil
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .koordinator import Koordinator

_LOGGER = logging.getLogger(__name__)

DATEIEN = (
    "fahrzeugprofil.json",
    "fahrten.jsonl",
    "tankvorgaenge.jsonl",
    "entitaeten.json",
)


def _kopieren(basis: str, ziel: str) -> str:
    os.makedirs(ziel, exist_ok=True)
    for name in DATEIEN:
        quelle = os.path.join(basis, name)
        if os.path.exists(quelle):
            shutil.copy(quelle, os.path.join(ziel, name))
    return ziel


async def jetzt(k: Koordinator) -> str:
    zeitstempel = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    ziel = os.path.join(k.ablage.backup_ordner, zeitstempel)
    await k.hass.async_add_executor_job(_kopieren, k.ablage.basis, ziel)
    await _vermerken(k)
    _LOGGER.info("Sicherung erstellt unter %s", ziel)
    return ziel


async def _vermerken(k: Koordinator) -> None:
    profil = await k.ablage.profil_lesen()
    if profil is None:
        return
    profil.setdefault("einstellungen", {})["letztes_backup"] = (
        datetime.datetime.now().isoformat()
    )
    await k.ablage.profil_schreiben(profil)
    await k.profil_veroeffentlichen(profil)


async def automatisch(k: Koordinator) -> None:
    """Der tägliche 04:00-Termin - prüft selbst, ob heute überhaupt eine
    Sicherung fällig ist."""
    profil = await k.ablage.profil_lesen()
    if profil is None:
        return
    intervall = profil.get("einstellungen", {}).get("backup_intervall", "aus")
    heute = datetime.date.today()
    faellig = (
        intervall == "taeglich"
        or (intervall == "woechentlich" and heute.weekday() == 0)
        or (intervall == "monatlich" and heute.day == 1)
    )
    if not faellig:
        return
    ziel = await jetzt(k)
    _LOGGER.info("Automatische Sicherung (%s) erstellt unter %s", intervall, ziel)


def _als_objekt(wert: object) -> object:
    return json.loads(wert) if isinstance(wert, str) else wert


async def wiederherstellen(k: Koordinator, daten: dict) -> None:
    """Überschreibt Profil, Fahrten, Tankvorgänge und die Sensor-Zuordnung
    komplett.

    entitaeten_json ist optional: ältere Sicherungen, die vor dem Setup-Menü
    entstanden sind, enthalten den Abschnitt nicht - dann bleibt die aktuelle
    Zuordnung unangetastet, statt sie zu leeren."""
    if daten.get("profil_json"):
        await k.ablage.profil_schreiben(_als_objekt(daten["profil_json"]))  # type: ignore[arg-type]
    if daten.get("fahrten_json") is not None:
        await k.ablage.fahrten_schreiben(_als_objekt(daten["fahrten_json"]))  # type: ignore[arg-type]
    if daten.get("tankvorgaenge_json") is not None:
        await k.ablage.tankvorgaenge_schreiben(_als_objekt(daten["tankvorgaenge_json"]))  # type: ignore[arg-type]
    if daten.get("entitaeten_json"):
        await k.zuordnung.speichern(_als_objekt(daten["entitaeten_json"]))  # type: ignore[arg-type]
        await k.trigger_neu_binden()
    await k.alles_veroeffentlichen()
    _LOGGER.info("Sicherung wiederhergestellt")
