import os
import shutil
import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.styles import Font, PatternFill
import smtplib
from email.message import EmailMessage
import getpass  # Nouveau: pour saisir le mot de passe sécurisé

# --- 0. CONFIGURATION GLOBALE ---
INPUT_DIR = 'MESURES_TP'
ARCHIVE_DIR = 'ARCHIVES_TP'
RAPPORT_FILE = 'Rapport_Carac_Redresseur.xlsx'
# La fréquence d'échantillonnage est cruciale pour le calcul RMS
FE = 50000  # Fréquence d'échantillonnage (exemple: 50 kHz)
TOLERANCE_VMOY_SORTIE = 0.95  # Tolérance pour la valeur moyenne théorique (95%)

# --- CONFIGURATION EMAIL (Corrigée) ---
EMAIL_SENDER = 'etudiant1@univ.com'
EMAIL_RECEIVER = 'etudiant2@univ.com'
EMAIL_SUBJECT = 'Rapport : Caractérisation Redresseur Monophasé'

# --- 1. GESTION DES DOSSIERS (os & shutil) ---
print("--- Démarrage de l'automatisation du TP ---")
if not os.path.exists(INPUT_DIR):
    print(f"❌ Le dossier '{INPUT_DIR}' n'existe pas. Création...")
    os.mkdir(INPUT_DIR)

if not os.path.exists(ARCHIVE_DIR):
    os.mkdir(ARCHIVE_DIR)

data_files = [f for f in os.listdir(INPUT_DIR) if f.endswith('.csv')]

if not data_files:
    print(f"⛔ Aucun fichier de mesure CSV trouvé dans '{INPUT_DIR}'. Arrêt du script.")
    exit()

print(f"✅ {len(data_files)} fichiers de mesure trouvés.")

# --- 2. CONSOLIDATION ET ANALYSE (Pandas & NumPy) ---

results_list = []  # Liste pour stocker les résultats de caractérisation

for file_name in data_files:
    file_path = os.path.join(INPUT_DIR, file_name)
    
    # Extraction sécurisée du label de charge
    try:
        # Plus robuste: extraire avant l'extension
        base_name = os.path.splitext(file_name)[0]
        if '_' in base_name:
            charge_label = base_name.split('_')[1]
        else:
            charge_label = base_name
    except:
        charge_label = file_name  # Fallback

    try:
        df = pd.read_csv(file_path)
        
        # Vérifier que les colonnes nécessaires existent
        required_columns = ['Tension_sortie (V)', 'Tension_entree (V)']
        if not all(col in df.columns for col in required_columns):
            print(f"⚠️ Fichier {file_name} ne contient pas les colonnes attendues")
            continue
            
        V_out = df['Tension_sortie (V)']
        V_in = df['Tension_entree (V)']
        
        # --- CALCULS CLÉS EN ÉLECTRONIQUE DE PUISSANCE ---
        
        # 1. Calcul de la valeur efficace (RMS) - Utilisation de NumPy pour la formule
        # V_RMS = sqrt( (1/N) * sum(V^2) )
        V_out_rms = np.sqrt(np.mean(V_out**2))
        V_in_rms = np.sqrt(np.mean(V_in**2))
        
        # 2. Calcul de la valeur moyenne (V_DC)
        V_out_avg = np.mean(V_out)
        
        # 3. Validation de la mesure (Exemple didactique)
        # Pour un redresseur simple, Vmoy_théorique ≈ (2*Vmax) / pi
        # Vmax est approximée par V_in_rms * sqrt(2)
        V_max = V_in_rms * np.sqrt(2) 
        V_moy_theorique = (2 * V_max) / np.pi
        
        is_ok = V_out_avg >= (V_moy_theorique * TOLERANCE_VMOY_SORTIE)
        statut = "VALIDÉ" if is_ok else "ÉCHEC (Sous-tension)"

        # Ajout du résultat
        results_list.append({
            'Configuration': charge_label,
            'V_in_RMS (mesuré)': round(V_in_rms, 2),
            'V_out_RMS': round(V_out_rms, 2),
            'V_out_Moyenne (DC)': round(V_out_avg, 2),
            'V_Moyenne_Théorique': round(V_moy_theorique, 2),
            'Statut': statut
        })
        
        print(f"  ✓ {file_name} analysé")
        
    except Exception as e:
        print(f"⚠️ Erreur lors du traitement de {file_name}: {e}")

# Vérifier si on a des résultats
if not results_list:
    print("❌ Aucun fichier n'a pu être analysé. Arrêt du script.")
    exit()

# Création du DataFrame de synthèse
df_report = pd.DataFrame(results_list)
print("✅ Caractérisation des différentes charges terminée.")

# --- 3. GÉNÉRATION ET FORMATAGE DU RAPPORT (openpyxl) ---

wb = Workbook()
ws = wb.active
# CORRECTION: Titre de 31 caractères maximum
ws.title = "Synthèse Redresseur"  # 20 caractères

# Ajouter les données du DataFrame
for r_idx, row in enumerate(dataframe_to_rows(df_report, header=True, index=False)):
    ws.append(row)

# Formatage de l'en-tête
header_font = Font(bold=True, color="FFFFFF")
header_fill = PatternFill(start_color="0052CC", end_color="0052CC", fill_type="solid")
for cell in ws[1]:
    cell.font = header_font
    cell.fill = header_fill

# Mise en forme conditionnelle pour les échecs
red_fill = PatternFill(start_color="FFCCCC", end_color="FFCCCC", fill_type="solid")
green_fill = PatternFill(start_color="CCFFCC", end_color="CCFFCC", fill_type="solid")

for row in ws.iter_rows(min_row=2, max_row=ws.max_row):
    status_cell = row[5]  # 6ème colonne (Statut)
    if status_cell.value == "ÉCHEC (Sous-tension)":
        status_cell.fill = red_fill
    elif status_cell.value == "VALIDÉ":
        status_cell.fill = green_fill
            
# Ajustement automatique de la largeur des colonnes
for column in ws.columns:
    max_length = 0
    column_letter = column[0].column_letter
    for cell in column:
        try:
            cell_value = str(cell.value) if cell.value is not None else ""
            if len(cell_value) > max_length:
                max_length = len(cell_value)
        except:
            pass
    adjusted_width = min(max_length + 2, 50)  # Maximum 50 caractères
    ws.column_dimensions[column_letter].width = adjusted_width

# Ajouter une feuille de métadonnées
ws_meta = wb.create_sheet(title="Métadonnées")
ws_meta.append(["Paramètre", "Valeur"])
ws_meta.append(["Date d'exécution", pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S")])
ws_meta.append(["Nombre de fichiers traités", len(data_files)])
ws_meta.append(["Fréquence d'échantillonnage", f"{FE} Hz"])
ws_meta.append(["Tolérance validation", f"{TOLERANCE_VMOY_SORTIE*100}%"])

wb.save(RAPPORT_FILE)
print(f"✅ Rapport Excel sauvegardé sous : {RAPPORT_FILE}")

# --- 4. ARCHIVAGE DES DONNÉES ET NETTOYAGE (shutil) ---

for file_name in data_files:
    src_path = os.path.join(INPUT_DIR, file_name)
    dest_path = os.path.join(ARCHIVE_DIR, file_name)
    shutil.move(src_path, dest_path)

print(f"✅ {len(data_files)} fichiers de mesure déplacés vers {ARCHIVE_DIR}.")

# --- 5. ENVOI DU RAPPORT PAR E-MAIL (smtplib) - CORRIGÉ ---

print("\n--- ENVOI PAR EMAIL ---")
print("ℹ️ Pour l'envoi email, vous avez 3 options:")
print("1. Utiliser un MOT DE PASSE D'APPLICATION Gmail (recommandé)")
print("2. Essayer avec votre mot de passe normal (peut échouer)")
print("3. Passer l'envoi email (le rapport est déjà sauvegardé)")

choice = input("\nVoulez-vous envoyer l'email? (o/n): ").lower()

if choice == 'o':
    # Demander le mot de passe de manière sécurisée
    print("\n⚠️ SECURITE: Ne pas utiliser votre mot de passe Gmail principal!")
    print("🔗 Créez un mot de passe d'application: https://myaccount.google.com/apppasswords")
    print("   (Sélectionnez 'Mail' et 'Autre (Nom personnalisé)' -> 'TP_Python')")
    
    email_password = getpass.getpass("Mot de passe d'application Gmail: ")
    
    if not email_password:
        print("❌ Envoi annulé: mot de passe vide")
    else:
        try:
            # Vérifier que le fichier existe
            if not os.path.exists(RAPPORT_FILE):
                print(f"❌ Fichier {RAPPORT_FILE} non trouvé")
            else:
                # Préparation du message
                msg_email = EmailMessage()
                msg_email['Subject'] = EMAIL_SUBJECT
                msg_email['From'] = EMAIL_SENDER
                msg_email['To'] = EMAIL_RECEIVER
                
                # Corps du message avec statistiques
                nb_valides = len(df_report[df_report['Statut'] == 'VALIDÉ'])
                nb_echecs = len(df_report[df_report['Statut'] == 'ÉCHEC (Sous-tension)'])
                
                corps_message = f"""Bonjour,

Rapport de caractérisation des redresseurs du TP.

RÉSUMÉ:
- Configurations testées: {len(df_report)}
- Mesures validées: {nb_valides}
- Mesures en échec: {nb_echecs}

Le rapport Excel détaillé est en pièce jointe.

Généré automatiquement par script Python.
Date: {pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S")}

Cordialement,
Script d'automatisation TP"""
                
                msg_email.set_content(corps_message)
                
                # Ajout de la pièce jointe
                with open(RAPPORT_FILE, 'rb') as f:
                    file_data = f.read()
                    msg_email.add_attachment(
                        file_data,
                        maintype='application',
                        subtype='vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                        filename=RAPPORT_FILE
                    )
                
                # Tentative de connexion avec différents ports
                try:
                    # Essai avec SMTP_SSL (port 465)
                    print("🔗 Connexion au serveur Gmail (port 465)...")
                    with smtplib.SMTP_SSL('smtp.gmail.com', 465, timeout=10) as server:
                        server.login(EMAIL_SENDER, email_password)
                        server.send_message(msg_email)
                    print(f"✅ Email envoyé avec succès à {EMAIL_RECEIVER}")
                    
                except:
                    # Fallback: SMTP avec TLS (port 587)
                    print("🔄 Essai avec le port alternatif 587...")
                    with smtplib.SMTP('smtp.gmail.com', 587, timeout=10) as server:
                        server.starttls()
                        server.login(EMAIL_SENDER, email_password)
                        server.send_message(msg_email)
                    print(f"✅ Email envoyé avec succès à {EMAIL_RECEIVER}")
                    
        except smtplib.SMTPAuthenticationError:
            print("❌ ERREUR D'AUTHENTIFICATION")
            print("🔧 Solution: Utilisez un MOT DE PASSE D'APPLICATION Gmail")
            print("   Guide: https://support.google.com/mail/?p=BadCredentials")
        except Exception as e:
            print(f"❌ Erreur lors de l'envoi: {type(e).__name__}: {e}")
else:
    print("✅ Envoi email ignoré. Le rapport est disponible localement.")

# --- 6. RÉSUMÉ FINAL ---
print("\n" + "="*50)
print("RÉSUMÉ DU PROCESSUS")
print("="*50)
print(f"📁 Fichiers traités: {len(data_files)}")
print(f"📊 Configurations analysées: {len(df_report)}")
print(f"✅ Mesures validées: {len(df_report[df_report['Statut'] == 'VALIDÉ'])}")
print(f"❌ Mesures en échec: {len(df_report[df_report['Statut'] == 'ÉCHEC (Sous-tension)'])}")
print(f"💾 Rapport généré: {RAPPORT_FILE}")
print(f"🗃️ Données archivées: {ARCHIVE_DIR}/")
print("="*50)
print("--- Fin du Processus Automatisé de Caractérisation ---")