"""
oct_extract.py — MVP : lit UN fichier DICOM (OCT / imagerie ophtalmique),
extrait quelques tags et les range dans un CSV (une ligne), puis convertit
le CSV en fichier Excel.

Etapes :
  0. Validation du CIOD (SOP Class UID) contre une liste blanche.
  1. Lecture des tags via pydicom.dcmread.
  2. Ecriture dans un CSV (csv.DictWriter, sep ';').
  3. Conversion CSV -> Excel (pandas read_csv + to_excel).

MVP mono-fichier : l'iteration sur un dossier (os/glob) viendra plus tard.
"""

import os
import sys
import glob  # noqa: F401  (reserve pour l'iteration multi-fichiers a venir)
import csv

import pandas as pd
import pydicom


# --- Etape 0 : CIODs autorises (SOP Class UID -> libelle lisible) ------------
CIODS_AUTORISES = {
    "1.2.840.10008.5.1.4.1.1.77.1.5.4": "Ophthalmic Tomography Image Storage",
    "1.2.840.10008.5.1.4.1.1.77.1.5.1": "Ophthalmic Photography 8 Bit Image Storage",
    "1.2.840.10008.5.1.4.1.1.77.1.5.2": "Ophthalmic Photography 16 Bit Image Storage",
    "1.2.840.10008.5.1.4.1.1.77.1.5.7": "Ophthalmic OCT En Face Image Storage",
    "1.2.840.10008.5.1.4.1.1.77.1.5.8": "Ophthalmic OCT B-scan Volume Analysis Storage",
    "1.2.840.10008.5.1.4.1.1.77.1.5.5": "Ophthalmic Thickness Map Storage",
    "1.2.840.10008.5.1.4.1.1.7": "Secondary Capture Image Storage",
}

# Colonnes du CSV (== les tags a extraire, dans l'ordre)
COLONNES = [
    "PatientName",
    "PatientID",
    "PatientBirthDate",
    "PatientSex",
    "ManufacturerModelName",
    "DeviceSerialNumber",
    "ImageLaterality",
    "StudyDate",
]

# Noms des fichiers de sortie
CSV_SORTIE = "oct_metadata.csv"
XLSX_SORTIE = "oct_metadata.xlsx"


def format_patient_name(ds):
    """Reformate PatientName ('Nom^Prenom^...') en 'Prenom Nom' lisible.
    Retourne '' si le tag est absent."""
    pn = getattr(ds, "PatientName", "")
    if pn == "":
        return ""
    # pydicom expose given_name / family_name sur l'objet PersonName
    given = getattr(pn, "given_name", "") or ""
    family = getattr(pn, "family_name", "") or ""
    lisible = f"{given} {family}".strip()
    # Repli : si aucun composant nomme, on garde la representation brute nettoyee
    return lisible if lisible else str(pn).replace("^", " ").strip()


def extraire_tags(ds):
    """Etape 1 : construit le dict des tags. Tag absent -> chaine vide."""
    return {
        "PatientName": format_patient_name(ds),
        "PatientID": getattr(ds, "PatientID", ""),
        "PatientBirthDate": getattr(ds, "PatientBirthDate", ""),
        "PatientSex": getattr(ds, "PatientSex", ""),
        "ManufacturerModelName": getattr(ds, "ManufacturerModelName", ""),
        "DeviceSerialNumber": getattr(ds, "DeviceSerialNumber", ""),
        "ImageLaterality": getattr(ds, "ImageLaterality", ""),
        "StudyDate": getattr(ds, "StudyDate", ""),
    }


def ecrire_csv(lignes, chemin_csv):
    """Etape 2 : ecrit les lignes dans un CSV (separateur ';')."""
    with open(chemin_csv, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=COLONNES, delimiter=";")
        writer.writeheader()
        writer.writerows(lignes)


def csv_vers_excel(chemin_csv, chemin_xlsx):
    """Etape 3 : convertit le CSV en Excel via pandas."""
    df = pd.read_csv(chemin_csv, sep=";", dtype=str, keep_default_na=False)
    df.to_excel(chemin_xlsx, index=False)


def traiter_fichier(chemin_dicom):
    """Pipeline complet pour UN fichier DICOM."""
    # Etape 0 : validation CIOD -> si non supporte : message + arret.
    ds = pydicom.dcmread(chemin_dicom)
    sop = str(getattr(ds, "SOPClassUID", ""))
    if sop not in CIODS_AUTORISES:
        libelle = getattr(getattr(ds, "SOPClassUID", None), "name", "inconnu")
        print(f"[ARRET] CIOD non supporte : {sop} ({libelle})")
        print("        Aucun CSV/Excel n'a ete genere.")
        return False

    print(f"[OK] CIOD valide : {sop} ({CIODS_AUTORISES[sop]})")

    # Etape 1
    ligne = extraire_tags(ds)

    # Etape 2 (une seule ligne pour ce MVP, mais writerows attend une liste)
    ecrire_csv([ligne], CSV_SORTIE)
    print(f"[OK] CSV ecrit  : {CSV_SORTIE}")

    # Etape 3
    csv_vers_excel(CSV_SORTIE, XLSX_SORTIE)
    print(f"[OK] Excel ecrit: {XLSX_SORTIE}")

    print("\nTags extraits :")
    for k, v in ligne.items():
        print(f"  {k:<24}: {v!r}")
    return True


if __name__ == "__main__":
    # MVP : un seul fichier. Chemin passe en argument, sinon valeur par defaut.
    if len(sys.argv) > 1:
        cible = sys.argv[1]
    else:
        cible = os.path.join(os.path.dirname(__file__), "CT_small.dcm")

    if not os.path.isfile(cible):
        print(f"[ERREUR] Fichier introuvable : {cible}")
        sys.exit(1)

    print(f"Fichier : {cible}")
    traiter_fichier(cible)
