"""Fahrzeugbilder direkt aus der Oberfläche hochladen und löschen
(Einstellungen -> Fahrzeugbilder).

Nur die festen, im Frontend fest verdrahteten Dateinamen sind erlaubt - eine
Positivliste, damit ein manipulierter Dateiname aus dem Frontend niemals
außerhalb von www/bilder/ schreiben kann (kein Pfad-Traversal über "../" oder
absolute Pfade).

Die Bytes werden unverändert unter dem erwarteten Namen abgelegt, unabhängig
vom tatsächlichen Bildformat des Originalfotos (z. B. JPEG von einem iPhone
unter einem ".webp"-Namen) - Browser stellen <img> nach den tatsächlichen
Bilddaten dar, nicht nach der Dateiendung. Eine Größenbeschränkung gibt es
bewusst nicht: jede Fotogröße muss hochladbar sein.

WARUM DIESE DATEIEN NICHT IM INTEGRATIONSORDNER LIEGEN: sie sind Nutzerdaten,
kein Auslieferbestandteil. Lägen sie unter custom_components/audi_dashboard/,
würde der nächste install.ps1-Lauf sie mitlöschen (er leert den Zielordner
vor dem Kopieren, siehe install.ps1). /config/www/bilder/ gehört dagegen dem
Nutzer und wird von keinem Update angefasst; ausgeliefert wird es weiterhin
unter /local/bilder/.
"""

from __future__ import annotations

import base64
import binascii
import logging
import os

from homeassistant.core import HomeAssistant

_LOGGER = logging.getLogger(__name__)

ERLAUBTE_DATEINAMEN = frozenset({
    "seitenansicht.webp",
    "seitenansicht-winter.webp",
    "front-schraeg.webp",
    "frontansicht.webp",
    "heckansicht.webp",
    "cockpit.webp",
    "scheinwerfer.webp",
    "sitze.webp",
    "rad-sommer.webp",
    "rad-winter.webp",
    "draufsicht.webp",
})


def _pfad(ordner: str, dateiname: str | None) -> str | None:
    if not dateiname or dateiname not in ERLAUBTE_DATEINAMEN:
        return None
    return os.path.join(ordner, dateiname)


def _schreiben(pfad: str, rohdaten: bytes) -> None:
    os.makedirs(os.path.dirname(pfad), exist_ok=True)
    tmp = pfad + ".tmp"
    with open(tmp, "wb") as datei:
        datei.write(rohdaten)
    os.replace(tmp, pfad)


def _loeschen(pfad: str) -> bool:
    if not os.path.exists(pfad):
        return False
    os.remove(pfad)
    return True


async def hochladen(
    hass: HomeAssistant, ordner: str, dateiname: str | None, daten_base64: str | None
) -> None:
    pfad = _pfad(ordner, dateiname)
    if not pfad or not daten_base64:
        _LOGGER.warning("Bild-Upload abgelehnt (dateiname=%s)", dateiname)
        return
    try:
        rohdaten = base64.b64decode(daten_base64)
    except (binascii.Error, ValueError) as fehler:
        _LOGGER.error("Bild-Upload: Daten nicht lesbar (%s)", fehler)
        return
    await hass.async_add_executor_job(_schreiben, pfad, rohdaten)
    _LOGGER.info("Fahrzeugbild gespeichert (%s, %s Bytes)", dateiname, len(rohdaten))


async def loeschen(hass: HomeAssistant, ordner: str, dateiname: str | None) -> None:
    pfad = _pfad(ordner, dateiname)
    if not pfad:
        _LOGGER.warning("Bild-Löschen abgelehnt (dateiname=%s)", dateiname)
        return
    if await hass.async_add_executor_job(_loeschen, pfad):
        _LOGGER.info("Fahrzeugbild gelöscht (%s)", dateiname)
