"""
Kanonische Speichereinheiten pro CSV-Zielfeld (module_registry: field.unit) und
abwählbare Quelleinheiten → Faktor für type_conversions.source_unit.
"""

from __future__ import annotations

from typing import Any

from csv_parser.module_registry import get_module_definition

# 1 kcal = 4.184 kJ (IEC/ISO 80000)
_KJ_TO_KCAL = 1.0 / 4.184

# — Energie (Ziel kcal) —
_ENERGY: list[dict[str, Any]] = [
    {"id": "kcal", "label": "Kilokalorien (kcal), wie in DB", "factor": 1.0},
    {"id": "kj", "label": "Kilojoule (kJ) → kcal", "factor": _KJ_TO_KCAL},
    {"id": "j", "label": "Joule (J) → kcal", "factor": _KJ_TO_KCAL / 1000.0},
]

# — Masse klein (Ziel g): Makronährstoffe —
_GRAM: list[dict[str, Any]] = [
    {"id": "g", "label": "Gramm (g), wie in DB", "factor": 1.0},
    {"id": "kg", "label": "Kilogramm (kg) → g", "factor": 1000.0},
    {"id": "mg", "label": "Milligramm (mg) → g", "factor": 0.001},
]

# — Körpergewicht (Ziel kg) —
_KG: list[dict[str, Any]] = [
    {"id": "kg", "label": "Kilogramm (kg), wie in DB", "factor": 1.0},
    {"id": "g", "label": "Gramm (g) → kg", "factor": 0.001},
    {"id": "lb", "label": "Pfund / lb → kg", "factor": 0.45359237},
    {"id": "oz", "label": "Unze / oz → kg", "factor": 0.028349523125},
]

# — Strecke (Ziel km) —
_KM: list[dict[str, Any]] = [
    {"id": "km", "label": "Kilometer (km), wie in DB", "factor": 1.0},
    {"id": "m", "label": "Meter (m) → km", "factor": 0.001},
    {"id": "mi", "label": "Meilen (mi) → km", "factor": 1.609344},
]

_UNIT_FAMILY: dict[str, list[dict[str, Any]]] = {
    "kcal": _ENERGY,
    "g": _GRAM,
    "kg": _KG,
    "km": _KM,
}


def get_canonical_unit(module: str, db_field: str) -> str | None:
    mod = get_module_definition(module)
    if not mod:
        return None
    finfo: dict[str, Any] | None = mod.get("fields", {}).get(db_field)
    if not finfo:
        return None
    u = finfo.get("unit")
    return str(u) if u else None


def source_unit_choices_for_field(module: str, db_field: str) -> list[dict[str, Any]]:
    """Optionen für GUI: id, label, canonical_unit, is_canonical (Umrechnung serverseitig)."""
    cu = get_canonical_unit(module, db_field)
    if not cu:
        return []
    choices = _UNIT_FAMILY.get(cu)
    if not choices:
        return []
    out: list[dict[str, Any]] = [
        {
            "id": c["id"],
            "label": c["label"],
            "canonical_unit": cu,
            "is_canonical": c["id"] == cu,
        }
        for c in choices
    ]
    out.append(
        {
            "id": "custom",
            "label": "Benutzerdefiniert (Konvertierungsfaktor, z. B. ml→g je nach Dichte)",
            "canonical_unit": cu,
            "is_canonical": False,
        }
    )
    return out


def factor_source_to_canonical(module: str, db_field: str, source_unit: str | None) -> float:
    """
    Multiplikator: CSV-Zahl * Faktor → Wert in kanonischer DB-Einheit.
    Unbekannte/None/leer/Passthrough → 1.0

    ``source_unit`` ``custom`` / ``none``: kein Registry-Faktor (1.0); freie Skalierung nur über
    ``conversion_factor`` in type_conversions (JSON).
    """
    if source_unit is None:
        return 1.0
    su = str(source_unit).strip().lower()
    if not su:
        return 1.0
    if su in ("custom", "none"):
        return 1.0
    cu = get_canonical_unit(module, db_field)
    if not cu:
        return 1.0
    choices = _UNIT_FAMILY.get(cu)
    if not choices:
        return 1.0
    for c in choices:
        if str(c["id"]).lower() == su:
            return float(c["factor"])
    return 1.0
