#!/usr/bin/env python3
"""
Script d'automatisation pour comparer les fichiers Magento et Le Phare
VERSION OAUTH2 avec envoi email via SMTP O2switch
"""

import os
import csv
import re
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from datetime import datetime, timedelta
from pathlib import Path
import logging

# Importer la configuration
try:
    import config_oauth
    from config_oauth import *
except ImportError:
    print("❌ ERREUR: Fichier config_oauth.py non trouvé !")
    print("➡️  Copiez config_oauth_exemple.py vers config_oauth.py et remplissez vos paramètres.")
    exit(1)

# Configuration du logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class ComparateurFichiers:
    """Classe pour comparer les fichiers Magento et Le Phare"""
    
    def __init__(self):
        self.array_magento = {}
        self.array_magento_moyen = {}
        self.array_magento_status = {}
        self.array_lephare = {}
    
    def charger_magento(self, fichier_path):
        """Charge le fichier Magento CSV"""
        logger.info(f"Chargement du fichier Magento: {fichier_path}")
        
        with open(fichier_path, 'r', encoding='utf-8-sig') as f:
            reader = csv.reader(f, delimiter=',')
            for row in reader:
                if len(row) >= 6:
                    ref = row[1]
                    self.array_magento[ref] = row[3]  # date_upd
                    self.array_magento_moyen[ref] = row[4]  # moyen
                    self.array_magento_status[ref] = row[5]  # status
        
        logger.info(f"Magento: {len(self.array_magento)} références chargées")
    
    def charger_lephare(self, fichier_path):
        """Charge le fichier Le Phare CSV"""
        logger.info(f"Chargement du fichier Le Phare: {fichier_path}")
        
        with open(fichier_path, 'r', encoding='utf-8-sig') as f:
            reader = csv.reader(f, delimiter=';')
            for row in reader:
                if len(row) >= 5:
                    ref_original = row[0]
                    ref_clean = re.sub(r'-[123]$', '', ref_original)
                    self.array_lephare[ref_clean] = row[2]
                    
                    if re.search(r'-[123]$', ref_original) and row[4] == "livraison-drop":
                        try:
                            ref_plus_un = str(int(ref_clean) + 1)
                            self.array_lephare[ref_plus_un] = row[2]
                        except ValueError:
                            pass
        
        logger.info(f"Le Phare: {len(self.array_lephare)} références chargées")
    
    def comparer(self):
        """Compare les deux fichiers et retourne les résultats"""
        cmd_plateforme = []
        cmd_autres = []
        
        for ref_magento, date_upd in self.array_magento.items():
            moyen = self.array_magento_moyen.get(ref_magento, '')
            status = self.array_magento_status.get(ref_magento, '')
            
            if ref_magento not in self.array_lephare:
                message = f"Référence cmde Magento {ref_magento} (status {status}) inexistant dans le Phare"
                
                if "partenaire" in moyen.lower():
                    cmd_plateforme.append(message)
                else:
                    cmd_autres.append(message)
        
        return cmd_plateforme, cmd_autres
    
    def generer_rapport(self, cmd_plateforme, cmd_autres):
        """Génère un rapport HTML des différences"""
        html = """<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rapport de Comparaison Magento / Le Phare</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            margin: 0;
            padding: 20px;
            background: #f5f5f5;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        h1 {
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 10px;
            margin-bottom: 30px;
        }
        h2 {
            color: #34495e;
            margin-top: 30px;
            margin-bottom: 15px;
            font-size: 1.3em;
        }
        .stats {
            display: flex;
            gap: 20px;
            margin-bottom: 30px;
        }
        .stat-box {
            flex: 1;
            padding: 20px;
            border-radius: 6px;
            text-align: center;
        }
        .stat-box.plateforme {
            background: #d4edda;
            border: 2px solid #28a745;
        }
        .stat-box.autres {
            background: #fff3cd;
            border: 2px solid #ffc107;
        }
        .stat-number {
            font-size: 2em;
            font-weight: bold;
            margin-bottom: 5px;
        }
        .stat-label {
            font-size: 0.9em;
            color: #666;
        }
        .item {
            padding: 12px 15px;
            margin: 8px 0;
            background: #f8f9fa;
            border-radius: 4px;
            border-left: 4px solid;
        }
        .item.plateforme {
            border-left-color: #28a745;
        }
        .item.autres {
            border-left-color: #ffc107;
        }
        .no-diff {
            padding: 15px;
            background: #e7f3ff;
            border-left: 4px solid #3498db;
            border-radius: 4px;
            color: #1976d2;
        }
        .timestamp {
            color: #7f8c8d;
            font-size: 0.9em;
            margin-top: 30px;
            text-align: right;
        }
    </style>
</head>
<body>
    <div class="container">
"""
        
        html += f"<h1>📊 Rapport de Comparaison Magento / Le Phare</h1>"
        
        html += '<div class="stats">'
        html += f'''
            <div class="stat-box plateforme">
                <div class="stat-number">{len(cmd_plateforme)}</div>
                <div class="stat-label">Livraisons plateforme</div>
            </div>
            <div class="stat-box autres">
                <div class="stat-number">{len(cmd_autres)}</div>
                <div class="stat-label">Autres (c&c, livraison mags)</div>
            </div>
        '''
        html += '</div>'
        
        html += "<h2>🚚 Livraisons plateforme</h2>"
        if cmd_plateforme:
            for item in cmd_plateforme:
                html += f"<div class='item plateforme'>{item}</div>"
        else:
            html += "<div class='no-diff'>✅ Aucune différence détectée</div>"
        
        html += "<h2>📦 Autres (c&c, livraison mags)</h2>"
        if cmd_autres:
            for item in cmd_autres:
                html += f"<div class='item autres'>{item}</div>"
        else:
            html += "<div class='no-diff'>✅ Aucune différence détectée</div>"
        
        html += f"<div class='timestamp'>Généré le {datetime.now().strftime('%d/%m/%Y à %H:%M:%S')}</div>"
        html += "</div></body></html>"
        
        return html


class RecuperateurOutlookOAuth:
    """Classe pour récupérer les emails via Microsoft Graph API avec OAuth2"""
    
    def __init__(self, tenant_id, client_id, client_secret, user_email):
        """Initialise la connexion OAuth2"""
        self.tenant_id = tenant_id
        self.client_id = client_id
        self.client_secret = client_secret
        self.user_email = user_email
        self.access_token = None
        
        try:
            import requests
            self.requests = requests
        except ImportError:
            logger.error("❌ Module 'requests' non installé. Installez avec: pip install requests")
            raise
        
        self._obtenir_token()
    
    def _obtenir_token(self):
        """Obtient un access token via OAuth2 Client Credentials Flow"""
        url = f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"
        
        data = {
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'scope': 'https://graph.microsoft.com/.default',
            'grant_type': 'client_credentials'
        }
        
        try:
            response = self.requests.post(url, data=data)
            response.raise_for_status()
            self.access_token = response.json()['access_token']
            logger.info(f"✅ Token OAuth2 obtenu pour {self.user_email}")
        except Exception as e:
            logger.error(f"❌ Erreur lors de l'obtention du token: {e}")
            raise
    
    def _graph_api_request(self, endpoint, params=None):
        """Effectue une requête à Microsoft Graph API"""
        headers = {
            'Authorization': f'Bearer {self.access_token}',
            'Content-Type': 'application/json'
        }
        
        url = f"https://graph.microsoft.com/v1.0{endpoint}"
        response = self.requests.get(url, headers=headers, params=params)
        response.raise_for_status()
        return response.json()
    
    def recuperer_piece_jointe(self, expediteur, nom_fichier_contient, jours_retour=7, dossier_sortie='./'):
        """Récupère la dernière pièce jointe d'un expéditeur spécifique"""
        date_limite = datetime.now() - timedelta(days=jours_retour)
        date_str = date_limite.strftime('%Y-%m-%dT%H:%M:%SZ')
        
        logger.info(f"🔍 Recherche d'emails de {expediteur} depuis {date_limite.strftime('%d/%m/%Y')}")
        
        try:
            # Construire le filtre OData
            filter_query = f"from/emailAddress/address eq '{expediteur}' and receivedDateTime ge {date_str}"
            
            # Rechercher les messages
            endpoint = f"/users/{self.user_email}/messages"
            params = {
                '$filter': filter_query,
                '$orderby': 'receivedDateTime desc',
                '$top': 10,
                '$select': 'id,subject,receivedDateTime,hasAttachments'
            }
            
            messages_data = self._graph_api_request(endpoint, params)
            messages = messages_data.get('value', [])
            
            if not messages:
                logger.warning(f"⚠️  Aucun email trouvé de {expediteur}")
                return None
            
            # Parcourir les messages pour trouver les pièces jointes
            for message in messages:
                if not message.get('hasAttachments'):
                    continue
                
                message_id = message['id']
                
                # Récupérer les pièces jointes
                attachments_endpoint = f"/users/{self.user_email}/messages/{message_id}/attachments"
                attachments_data = self._graph_api_request(attachments_endpoint)
                attachments = attachments_data.get('value', [])
                
                for attachment in attachments:
                    nom_fichier = attachment.get('name', '')
                    
                    if nom_fichier_contient.lower() in nom_fichier.lower():
                        # Télécharger la pièce jointe
                        content_bytes = attachment.get('contentBytes')
                        if content_bytes:
                            import base64
                            file_content = base64.b64decode(content_bytes)
                            
                            chemin_fichier = os.path.join(dossier_sortie, nom_fichier)
                            with open(chemin_fichier, 'wb') as f:
                                f.write(file_content)
                            
                            date_email = message.get('receivedDateTime', 'inconnue')
                            logger.info(f"✅ Fichier téléchargé: {nom_fichier} (email du {date_email})")
                            return chemin_fichier
            
            logger.warning(f"⚠️  Aucun fichier trouvé contenant '{nom_fichier_contient}'")
            return None
            
        except Exception as e:
            logger.error(f"❌ Erreur lors de la recherche: {e}")
            return None


def envoyer_rapport_par_email_smtp(fichier_rapport, destinataires, nb_plateforme, nb_autres):
    """Envoie le rapport par email via le serveur SMTP O2switch"""
    
    logger.info(f"📧 Envoi du rapport par email via SMTP...")
    
    # Récupérer la configuration SMTP
    smtp_host = getattr(config_oauth, 'SMTP_HOST', 'localhost')
    smtp_port = getattr(config_oauth, 'SMTP_PORT', 587)
    smtp_user = getattr(config_oauth, 'SMTP_USER', EMAIL_OUTLOOK)
    smtp_password = getattr(config_oauth, 'SMTP_PASSWORD', '')
    smtp_from = getattr(config_oauth, 'SMTP_FROM', EMAIL_OUTLOOK)
    
    # Préparer la liste des destinataires
    if isinstance(destinataires, str):
        destinataires = [destinataires]
    
    try:
        # Créer le message
        msg = MIMEMultipart('alternative')
        msg['From'] = smtp_from
        msg['To'] = ', '.join(destinataires)
        msg['Subject'] = f"Rapport Magento/Le Phare - {datetime.now().strftime('%d/%m/%Y')} - {nb_plateforme} plateforme, {nb_autres} autres"
        
        # Corps du message en HTML
        html_body = f"""
        <html>
        <head>
            <style>
                body {{ font-family: Arial, sans-serif; line-height: 1.6; color: #333; }}
                .header {{ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; }}
                .stats {{ display: flex; gap: 20px; margin: 20px 0; }}
                .stat-box {{ flex: 1; padding: 15px; border-radius: 6px; text-align: center; }}
                .plateforme {{ background: #d4edda; border: 2px solid #28a745; }}
                .autres {{ background: #fff3cd; border: 2px solid #ffc107; }}
                .footer {{ color: #7f8c8d; font-size: 0.9em; margin-top: 30px; padding-top: 20px; border-top: 1px solid #e0e0e0; }}
            </style>
        </head>
        <body>
            <div class="header">
                <h2 style="margin: 0;">📊 Rapport de Comparaison Magento / Le Phare</h2>
                <p style="margin: 5px 0 0 0; opacity: 0.9;">Rapport quotidien du {datetime.now().strftime('%d/%m/%Y')}</p>
            </div>
            
            <div style="padding: 20px;">
                <p>Bonjour,</p>
                <p>Voici le résumé de la comparaison quotidienne :</p>
                
                <div class="stats">
                    <div class="stat-box plateforme">
                        <div style="font-size: 2em; font-weight: bold; color: #28a745;">{nb_plateforme}</div>
                        <div>Livraisons plateforme</div>
                    </div>
                    <div class="stat-box autres">
                        <div style="font-size: 2em; font-weight: bold; color: #ffc107;">{nb_autres}</div>
                        <div>Autres (c&c, livraison mags)</div>
                    </div>
                </div>
                
                <p>Le rapport détaillé complet est disponible en pièce jointe.</p>
                
                <div class="footer">
                    <p>
                        Ce rapport est généré automatiquement tous les jours à 9h00.<br>
                        Généré le {datetime.now().strftime('%d/%m/%Y à %H:%M:%S')}
                    </p>
                </div>
            </div>
        </body>
        </html>
        """
        
        # Version texte simple (fallback)
        text_body = f"""
Rapport Magento/Le Phare - {datetime.now().strftime('%d/%m/%Y')}

Résumé de la comparaison :
- Livraisons plateforme : {nb_plateforme} différence(s)
- Autres (c&c, livraison mags) : {nb_autres} différence(s)

Le rapport détaillé est disponible en pièce jointe.

Généré le {datetime.now().strftime('%d/%m/%Y à %H:%M:%S')}
        """
        
        # Attacher les deux versions
        part_text = MIMEText(text_body, 'plain', 'utf-8')
        part_html = MIMEText(html_body, 'html', 'utf-8')
        msg.attach(part_text)
        msg.attach(part_html)
        
        # Attacher le fichier rapport
        with open(fichier_rapport, 'rb') as f:
            attachment = MIMEBase('text', 'html')
            attachment.set_payload(f.read())
            encoders.encode_base64(attachment)
            attachment.add_header('Content-Disposition', f'attachment; filename="{os.path.basename(fichier_rapport)}"')
            msg.attach(attachment)
        
        # Envoyer l'email
        if smtp_password:
            # Avec authentification
            server = smtplib.SMTP(smtp_host, smtp_port)
            server.starttls()
            server.login(smtp_user, smtp_password)
        else:
            # Sans authentification (localhost)
            server = smtplib.SMTP(smtp_host, smtp_port)
        
        server.send_message(msg)
        server.quit()
        
        logger.info(f"✅ Rapport envoyé par email à {', '.join(destinataires)}")
        return True
        
    except Exception as e:
        logger.error(f"❌ Erreur lors de l'envoi email: {e}")
        return False


def main():
    """Fonction principale"""
    
    # Créer le dossier de travail
    Path(DOSSIER_TRAVAIL).mkdir(exist_ok=True)
    
    try:
        print("\n" + "="*70)
        print("🚀 DÉMARRAGE DE LA COMPARAISON AUTOMATIQUE (OAuth2 + SMTP)")
        print("="*70 + "\n")
        
        # 1. Connexion via OAuth2
        logger.info("📧 Connexion à Microsoft 365 via OAuth2...")
        outlook = RecuperateurOutlookOAuth(
            TENANT_ID,
            CLIENT_ID,
            CLIENT_SECRET,
            EMAIL_OUTLOOK
        )
        
        # 2. Récupération des fichiers
        logger.info("\n📥 Récupération des fichiers...")
        fichier_magento = outlook.recuperer_piece_jointe(
            EXPEDITEUR_MAGENTO,
            FICHIER_MAGENTO_CONTIENT,
            JOURS_RECHERCHE,
            DOSSIER_TRAVAIL
        )
        
        fichier_lephare = outlook.recuperer_piece_jointe(
            EXPEDITEUR_LEPHARE,
            FICHIER_LEPHARE_CONTIENT,
            JOURS_RECHERCHE,
            DOSSIER_TRAVAIL
        )
        
        # 3. Vérifier que les deux fichiers ont été trouvés
        if not fichier_magento:
            logger.error("❌ Fichier Magento non trouvé !")
            print("\n💡 Conseil: Vérifiez EXPEDITEUR_MAGENTO et FICHIER_MAGENTO_CONTIENT dans config_oauth.py")
            return
        
        if not fichier_lephare:
            logger.error("❌ Fichier Le Phare non trouvé !")
            print("\n💡 Conseil: Vérifiez EXPEDITEUR_LEPHARE et FICHIER_LEPHARE_CONTIENT dans config_oauth.py")
            return
        
        # 4. Comparaison des fichiers
        logger.info("\n⚙️  Comparaison des fichiers en cours...")
        comparateur = ComparateurFichiers()
        comparateur.charger_magento(fichier_magento)
        comparateur.charger_lephare(fichier_lephare)
        
        cmd_plateforme, cmd_autres = comparateur.comparer()
        
        # 5. Génération du rapport
        rapport_html = comparateur.generer_rapport(cmd_plateforme, cmd_autres)
        
        fichier_rapport = f"rapport_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
        with open(fichier_rapport, 'w', encoding='utf-8') as f:
            f.write(rapport_html)
        
        logger.info(f"✅ Rapport généré: {fichier_rapport}")
        
        # 6. Envoyer le rapport par email (si configuré)
        if hasattr(config_oauth, 'DESTINATAIRES_EMAIL') and DESTINATAIRES_EMAIL:
            envoyer_rapport_par_email_smtp(
                fichier_rapport, 
                DESTINATAIRES_EMAIL,
                len(cmd_plateforme),
                len(cmd_autres)
            )
        
        # 7. Afficher le résumé
        print("\n" + "="*70)
        print("📊 RÉSUMÉ DE LA COMPARAISON")
        print("="*70)
        print(f"🚚 Livraisons plateforme: {len(cmd_plateforme)} différence(s)")
        print(f"📦 Autres (c&c, livraison mags): {len(cmd_autres)} différence(s)")
        print(f"\n📄 Rapport détaillé: {fichier_rapport}")
        print("="*70 + "\n")
        
        logger.info("✅ TRAITEMENT TERMINÉ AVEC SUCCÈS")
        
    except Exception as e:
        logger.error(f"❌ Erreur lors du traitement: {str(e)}", exc_info=True)
        print("\n💡 Vérifiez vos paramètres dans config_oauth.py")
        raise


if __name__ == "__main__":
    main()
