import argparse
import configparser
import os
import subprocess
import csv
import pandas as pd


def get_sivas_teilestamm(sivas_ids,  overwrite=True, out_dir= os.environ.get('PROJECT_DATA')):
    """
    Generiert für jede angegebene SIVAS-Teilenummer eine CSV-Datei, in der die Teilestamm-Informationen gespeichert sind
    """
    sivas_teilestamm_exe = os.environ.get('SIVAS_TEILESTAMM')

    if not os.path.isfile(sivas_teilestamm_exe):
        raise FileNotFoundError(
            f"Programmpfad '{sivas_teilestamm_exe}' nicht erreichbar. "
            f"Bitte Zugriff und Variable SIVAS_TEILESTAMM in setenv.bat prüfen."
        )

    if not os.path.isdir(out_dir):
        raise NotADirectoryError(
            f"Ausgabeverzeichnis '{out_dir}' existiert nicht. "
            f"Bitte VPN oder setenv.bat prüfen."
        )

    if isinstance(sivas_ids, str):
        sivas_ids = list(set(sivas_ids.strip().split(",")))

    ids_to_generate = []
    for id in sivas_ids:
        if not overwrite and os.path.isfile(os.path.join(out_dir, id + ".csv")):
            continue
        ids_to_generate.append(id)

    if len(ids_to_generate) == 0:
        print("Alle CSVs vorhanden oder keine neuen Nummern")
        return

    ids_to_generate_str = ",".join([f'"{id}"' for id in ids_to_generate])

    os.environ["SIVAS_EXCEL_EXPORT_DIR"] = out_dir
    print(f"Erstelle CSV(s) mit Teilestamminformationen...")
    subprocess.run(f'{sivas_teilestamm_exe} -teilenr={ids_to_generate_str} -open_target_dir=n')

    for id in ids_to_generate:
        csv_path = os.path.join(out_dir, id + ".csv")
        with open(csv_path, encoding="utf-8", newline="") as csv_file:
            csv_data = csv.reader(csv_file, delimiter=";")
            rows = list(csv_data)
            if len(rows) != 2:
                raise ValueError(f"SIVAS-Teilenummer '{id}' existiert nicht oder liefert keine gültige CSV.")

def read_bezeichner_from_csv(teilenr):
    """
    Liest den Bezeichner aus einer SIVAS-CSV für eine gegebene Teilenummer.

    :param teilenr: SIVAS Teilenummer als String
    :return: Bezeichner-String, falls erfolgreich. Wirft Exception bei Fehler.
    """
    csv_dir = os.environ.get("PROJECT_DATA", ".")
    csv_path = os.path.join(csv_dir, f"{teilenr}.csv")

    if not os.path.isfile(csv_path):
        raise FileNotFoundError(f"CSV für Teilenummer '{teilenr}' nicht gefunden unter {csv_path}")

    try:
        df = pd.read_csv(csv_path, sep=";", encoding="utf-8")
    except Exception as e:
        raise ValueError(f"Fehler beim Einlesen der CSV: {e}")

    if df.shape[0] != 1:
        raise ValueError(f"Ungültiger Zeileninhalt für '{teilenr}' – erwartet genau eine Datenzeile.")

    if "Bezeichnung1" not in df.columns:
        raise ValueError(f"Spalte 'Bezeichnung1' nicht gefunden in CSV für '{teilenr}'.")

    return str(df["Bezeichnung1"].iloc[0]).strip()
    
def update_bezeichner(names_config, config_path):

    if "Missing" not in names_config or not names_config["Missing"]:
        print("Keine fehlenden Einträge in [Missing]. Keine Abfrage angestoßen.")
        return

    missing_ids = list(names_config["Missing"].keys())
    resolved_ids = []

    print(f"Starte SIVAS-Abfrage für {len(missing_ids)} fehlende Teilenummer(n)...")

    try:
        get_sivas_teilestamm(missing_ids)
    except Exception as e:
        print(f"Fehler bei der SIVAS-Abfrage: {e}")

    updated = 0
    

    for id in missing_ids:
        try:
            bezeichner = read_bezeichner_from_csv(id)
            if "Sivasnummern" not in names_config:
                names_config["Sivasnummern"] = {}
            names_config["Sivasnummern"][id] = bezeichner
            resolved_ids.append(id)
            updated += 1
        except Exception as e:
            print(f"WARNUNG: Bezeichner für {id} konnte nicht gelesen werden: {e}")
    
    for id in resolved_ids:
        names_config["Missing"].pop(id, None)

    if "Missing" in names_config and not names_config["Missing"]:
        names_config.remove_section("Missing")

    with open(config_path, "w", encoding="utf-8") as f:
        names_config.write(f)

    print(f"{updated} Bezeichner erfolgreich ergänzt und Konfiguration aktualisiert.")


if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="Aktualisiert fehlende Bezeichner in bezeichner.cfg anhand von SIVAS-Teilestamm.")
    parser.add_argument("-c", "--config", type=str, default=os.path.join(os.environ.get("PROJECT_CFG", "."), "bezeichner.cfg"), help="Pfad zur bezeichner.cfg")

    args = parser.parse_args()
    config_path = args.config

    if not os.path.isfile(config_path):
        raise FileNotFoundError(f"Config-Datei nicht gefunden: {config_path}")

    config = configparser.ConfigParser()
    config.optionxform = str  # Groß-/Kleinschreibung erhalten
    config.read(config_path, encoding="utf-8")

    update_bezeichner(config)