"""Automatische Migration alter materials.csv (Version 1.4, 24 Spalten).

Die v1.4-CSV nutzt die alten Principled-Namen (Specular, Clearcoat,
Transmission Roughness ...). Wird so eine Datei erkannt, wird sie einmalig
ins aktuelle Format (``material.HEADERS``) umgerechnet; das Original bleibt
als ``materials.csv.bak-v14`` daneben liegen. Anlass: Ein Nutzer stand nach
dem Blender-5.2-Update vor einer leeren Bibliothek (05.08.2026).
"""

import csv
import os
import shutil

from .material import HEADERS

ALT_V14_SPALTEN = 24


def _farbe(text, fallback):
    try:
        teile = [float(x) for x in str(text).split(",")]
    except ValueError:
        return fallback
    if len(teile) == 3:
        teile.append(1.0)
    return tuple(teile) if len(teile) == 4 else fallback


def _fstr(rgba):
    return ",".join(f"{x:.3f}" for x in rgba)


def _mix_weiss(basis, anteil):
    # Blender-4-Versioning: Tint-ZAHL wird zur FARBE (weiss Richtung Grundfarbe)
    return tuple((1.0 - anteil) + anteil * c for c in basis[:3]) + (1.0,)


def _f(wert, standard=0.0):
    try:
        return float(str(wert).replace(",", "."))
    except ValueError:
        return standard


def _konvertiere_zeile(alt):
    """Eine 24-Spalten-Zeile (v1.4) in die 27-Spalten-Form umrechnen.

    v1.4-Reihenfolge: Category, Name, Base Color, Metallic, Specular,
    Roughness, Subsurface, Subsurface Radius, IOR, Transmission,
    Subsurface Color, Subsurface IOR, Subsurface Anisotropy, Specular Tint,
    Anisotropic, Anisotropic Rotation, Sheen, Sheen Tint, Clearcoat,
    Clearcoat Roughness, Transmission Roughness, Emission, Emission
    Strength, Alpha. Entfaellt in Blender 4/5: Subsurface Color,
    Subsurface IOR, Transmission Roughness.
    """
    basis = _farbe(alt[2], (1.0, 1.0, 1.0, 1.0))
    return [
        alt[0], alt[1], _fstr(basis),
        f"{_f(alt[3]):.3f}",                             # Metallic
        f"{_f(alt[5]):.3f}",                             # Roughness
        f"{_f(alt[8], 1.45):.3f}",                       # IOR
        f"{_f(alt[23], 1.0):.3f}",                       # Alpha
        f"{_f(alt[6]):.3f}",                             # Subsurface -> Weight
        ",".join(f"{x:.3f}" for x in _farbe(alt[7], (1.0, 1.0, 1.0, 1.0))[:3]),
        "0.050",                                         # Subsurface Scale (neu)
        f"{_f(alt[12]):.3f}",                            # Subsurface Anisotropy
        f"{_f(alt[4], 0.5):.3f}",                        # Specular -> Specular IOR Level
        _fstr(_mix_weiss(basis, _f(alt[13]))),           # Specular Tint: Zahl -> Farbe
        f"{_f(alt[14]):.3f}",                            # Anisotropic
        f"{_f(alt[15]):.3f}",                            # Anisotropic Rotation
        f"{_f(alt[9]):.3f}",                             # Transmission -> Weight
        f"{_f(alt[18]):.3f}",                            # Clearcoat -> Coat Weight
        f"{_f(alt[19]):.3f}",                            # Clearcoat Rough. -> Coat Rough.
        "1.500",                                         # Coat IOR (neu)
        "1.000,1.000,1.000,1.000",                       # Coat Tint (neu)
        f"{_f(alt[16]):.3f}",                            # Sheen -> Sheen Weight
        "0.500",                                         # Sheen Roughness (neu)
        _fstr(_mix_weiss(basis, _f(alt[17]))),           # Sheen Tint: Zahl -> Farbe
        _fstr(_farbe(alt[21], (0.0, 0.0, 0.0, 1.0))),    # Emission -> Emission Color
        f"{_f(alt[22]):.3f}",                            # Emission Strength
        "0.000",                                         # Thin Film Thickness (neu)
        "1.333",                                         # Thin Film IOR (neu)
    ]


def migriere_falls_alt(file_path):
    """Erkennt eine v1.4-CSV und schreibt sie ins aktuelle Format um.

    Rueckgabe: Anzahl konvertierter Zeilen, sonst None (nichts zu tun).
    Wirft nie - im Zweifel bleibt die Datei unangetastet.
    """
    try:
        roh = None
        for kodierung in ("utf-8-sig", "cp1252"):
            try:
                with open(file_path, "r", encoding=kodierung, newline="") as f:
                    roh = f.read()
                break
            except UnicodeDecodeError:
                continue
        if not roh:
            return None
        kopfzeile = roh.splitlines()[0]
        # Excel (deutsch) speichert mit Semikolon - auch das abfangen
        trenner = ";" if kopfzeile.count(";") > kopfzeile.count(",") else ","
        zeilen = [z for z in csv.reader(roh.splitlines(), delimiter=trenner)
                  if z and any(feld.strip() for feld in z)]
        if not zeilen or len(zeilen[0]) != ALT_V14_SPALTEN:
            return None  # aktuelles Format oder unbekannt -> nicht anfassen
        konvertiert = [_konvertiere_zeile(z) for z in zeilen[1:]
                       if len(z) == ALT_V14_SPALTEN]
        sicherung = file_path + ".bak-v14"
        if not os.path.exists(sicherung):
            shutil.copy2(file_path, sicherung)
        with open(file_path, "w", encoding="utf-8", newline="") as f:
            w = csv.writer(f)
            w.writerow(HEADERS)
            w.writerows(konvertiert)
        print(f"BaseMaterials: alte materials.csv (v1.4) erkannt -> "
              f"{len(konvertiert)} Materialien konvertiert. Sicherung: {sicherung}")
        return len(konvertiert)
    except Exception as fehler:
        print(f"BaseMaterials: CSV-Migration fehlgeschlagen: {fehler}")
        return None
