from .base_agent import BaseAgent
from typing import Dict, Any, Optional
import logging
import json
import os
import sys
from datetime import datetime

# Ajout du chemin des utilitaires au PATH pour pouvoir les importer
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from loaders.ticket_data_loader import TicketDataLoader

logger = logging.getLogger("AgentTicketAnalyser")

class AgentTicketAnalyser(BaseAgent):
    """
    Agent pour analyser les tickets (JSON ou Markdown) et en extraire les informations importantes.
    Remplace l'ancien AgentJsonAnalyser avec des fonctionnalités améliorées.
    """
    def __init__(self, llm):
        super().__init__("AgentTicketAnalyser", llm)
        
        # Configuration locale de l'agent
        self.temperature = 0.1  # Besoin d'analyse très précise
        self.top_p = 0.8
        self.max_tokens = 2500
        
        # Centralisation des objectifs d'analyse
        self.objectifs_analyse = """
Ta mission principale :

1. Identifier le client et le contexte du ticket (demande "name" et "description")
   - Récupère le nom de l'auteur si présent
   - Indique si un `user_id` est disponible
   - Conserve uniquement les informations d'identification utiles (pas d'adresse ou signature de mail inutile)

2. Mettre en perspective le `name` du ticket
   - Il peut contenir une ou plusieurs questions implicites
   - Reformule ces questions de façon explicite

3. Analyser la `description`
   - Elle fournit souvent le vrai point d'entrée technique
   - Repère les formulations interrogatives ou les demandes spécifiques
   - Identifie si cette partie complète ou précise les questions du nom

4. Structurer le fil de discussion
    - Conserve uniquement les échanges pertinents:
        - supprime mentions légales, signatures automatiques, liens inutiles...
        - Conserve les références documentation, FAQ, liens utiles ...
    - Identifie clairement chaque intervenant (client / support)
    - Distingue les types de contenus (réponses, conseils, confirmations, demandes d'information, etc.)
    - Classe les informations par ordre chronologique avec date et rôle

5. Préparer la transmission à l'agent suivant
    - Nettoie le fil sans perte d'information technique: normes, FAQ, liens...
    - Préserve tous les éléments utiles à l'analyse d'image : modules cités, options évoquées, comportements décrits
    - Mentionne si des images sont attachées au ticket
"""
        # Centralisation de la structure de réponse
        self.structure_reponse = """
Structure ta réponse :

1. Résumé du contexte
   - Client (nom, email si disponible)
   - Sujet du ticket reformulé en une ou plusieurs questions
   - Description technique synthétique

2. Informations techniques détectées
   - Logiciels/modules mentionnés
   - Paramètres évoqués
   - Fonctionnalités impactées
   - Conditions spécifiques (multi-laboratoire, utilisateur non valide, etc.)

3. Fil de discussion (filtrée, nettoyée, classée)
   - Intervenant (Client/Support)
   - Date et contenu synthétique de chaque échange
   - Résumés techniques et suggestions
   - Liens documentaires s'ils sont utiles (manuel, FAQ…)

4. Éléments liés à l'analyse visuelle
   - Nombre d'images attachées
   - Références aux interfaces ou options à visualiser
   - Points à vérifier dans les captures (listes incomplètes, cases à cocher, utilisateurs grisés, etc.)

IMPORTANT :
- Ne propose aucune solution ni interprétation.
- Ne génère pas de tableau.
- Ne reformule pas les messages, conserve les formulations exactes sauf nettoyage de forme.
"""
        # Construction du prompt système
        self.system_prompt = f"""Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab pour la société CBAO.
Tu interviens avant l'analyse des captures d'écran pour contextualiser le ticket, identifier les questions posées, et structurer les échanges de manière claire.
{self.objectifs_analyse}
Tu travailles à partir d'un ticket au format JSON.
Ton rôle est d'extraire, nettoyer, structurer et enrichir le contexte de la demande.
Ton analyse sera transmise à un autre agent chargé d'analyser les images liées au ticket.
Elle doit donc être :
- Factuelle
- Structurée
- Dépourvue d'informations inutiles
- Adaptée à une suite d'analyse multimodale
{self.structure_reponse}"""
        
        # Initialiser le loader de données
        self.ticket_loader = TicketDataLoader()
        
        # Appliquer la configuration au LLM
        self._appliquer_config_locale()
        
        logger.info("AgentTicketAnalyser initialisé")
    
    def _appliquer_config_locale(self) -> None:
        """
        Applique la configuration locale au modèle LLM.
        """
        # Appliquer le prompt système
        if hasattr(self.llm, "prompt_system"):
            self.llm.prompt_system = self.system_prompt
        
        # Appliquer les paramètres
        if hasattr(self.llm, "configurer"):
            params = {
                "temperature": self.temperature,
                "top_p": self.top_p,
                "max_tokens": self.max_tokens
            }
            
            self.llm.configurer(**params)
    
    def _generer_prompt_analyse(self, ticket_formate: str, source_format: str) -> str:
        """
        Génère le prompt d'analyse standardisé
        
        Args:
            ticket_formate: Texte du ticket formaté pour l'analyse
            source_format: Format source du ticket (JSON, Markdown, etc.)
            
        Returns:
            Prompt formaté pour l'analyse du ticket
        """
        return f"""Tu es un agent expert en analyse de tickets techniques pour BRG-Lab pour la société CBAO.
Ta mission est de préparer une synthèse propre, structurée et exploitable par un second agent chargé d'analyser les images liées au ticket.

{ticket_formate}

Concentre-toi sur les points suivants :

1. Compréhension du problème initial
- Analyse le champ `name` (nom de la demande) : identifie s'il contient une ou plusieurs questions explicites ou implicites.
- Analyse la `description` : reformule les éventuelles interrogations techniques formulées par le client.
- Résume la problématique en une ou deux phrases claires.

2. Identification du client
- Récupère le nom et email du demandeur si disponibles (à partir de `author_id`, `partner_id_email_from` ou équivalents).
- Ignore les signatures ou mentions inutiles.
- Vérifie si un `user_id` est associé.

3. Informations techniques à extraire
- Logiciels, modules, interfaces mentionnées
- Paramètres visibles ou évoqués (ex: utilisateurs valides/invalides, filtres actifs, options)
- Conditions spécifiques (multi-laboratoire, profils, permissions, etc.)
- Références à des documents, normes ou configurations

4. Synthèse du fil de discussion
- Classe les échanges par ordre chronologique
- Indique clairement qui parle (Client ou Support)
- Nettoie les mentions légales, signatures ou lignes non pertinentes
- Garde uniquement les contenus ayant une valeur technique ou informative

5. Préparation à l'analyse visuelle
- Si des captures d'écran sont présentes : indique combien, et si elles semblent liées à des options, interfaces ou comportements cités.
- Identifie les éléments qui devraient apparaître visuellement : boutons, filtres, listes d'utilisateurs, champs à cocher, erreurs affichées.
- Résume en 3-5 bullet points les éléments que le prochain agent devra observer sur les images.

IMPORTANT :
- Ne propose pas de diagnostic ni de solution
- Reste strictement factuel
- N'invente rien : base-toi uniquement sur les données visibles

Ce ticket provient d'un fichier au format {source_format.upper()}.
Réponds de manière factuelle, en te basant uniquement sur les informations fournies."""
    
    def executer(self, ticket_data: Dict[str, Any]) -> str:
        """
        Analyse un ticket pour en extraire les informations pertinentes
        
        Args:
            ticket_data: Dictionnaire contenant les données du ticket à analyser
                ou chemin vers un fichier de ticket (JSON ou Markdown)
            
        Returns:
            Réponse formatée contenant l'analyse du ticket
        """
        # Détecter si ticket_data est un chemin de fichier ou un dictionnaire
        if isinstance(ticket_data, str) and os.path.exists(ticket_data):
            try:
                ticket_data = self.ticket_loader.charger(ticket_data)
                logger.info(f"Données chargées depuis le fichier: {ticket_data}")
            except Exception as e:
                error_message = f"Erreur lors du chargement du fichier: {str(e)}"
                logger.error(error_message)
                return f"ERREUR: {error_message}"
        
        # Vérifier que les données sont bien un dictionnaire
        if not isinstance(ticket_data, dict):
            error_message = "Les données du ticket doivent être un dictionnaire ou un chemin de fichier valide"
            logger.error(error_message)
            return f"ERREUR: {error_message}"
        
        ticket_code = ticket_data.get('code', 'Inconnu')
        logger.info(f"Analyse du ticket: {ticket_code}")
        print(f"AgentTicketAnalyser: Analyse du ticket {ticket_code}")
        
        # Récupérer les métadonnées sur la source des données
        source_format = "inconnu"
        source_file = "non spécifié"
        if "metadata" in ticket_data and isinstance(ticket_data["metadata"], dict):
            source_format = ticket_data["metadata"].get("format", "inconnu")
            source_file = ticket_data["metadata"].get("source_file", "non spécifié")
        
        logger.info(f"Format source: {source_format}, Fichier source: {source_file}")
        
        # Préparer le ticket pour l'analyse
        ticket_formate = self._formater_ticket_pour_analyse(ticket_data)
        
        # Créer le prompt pour l'analyse, adapté au format source
        prompt = self._generer_prompt_analyse(ticket_formate, source_format)
        
        try:
            logger.info("Interrogation du LLM")
            response = self.llm.interroger(prompt)
            logger.info(f"Réponse reçue: {len(response)} caractères")
            print(f"  Analyse terminée: {len(response)} caractères")
        except Exception as e:
            error_message = f"Erreur lors de l'analyse du ticket: {str(e)}"
            logger.error(error_message)
            response = f"ERREUR: {error_message}"
            print(f"  ERREUR: {error_message}")
        
        # Enregistrer l'historique avec le prompt complet pour la traçabilité
        self.ajouter_historique("analyse_ticket", 
                               {
                                   "ticket_id": ticket_code,
                                   "format_source": source_format,
                                   "source_file": source_file,
                                   "prompt": prompt,
                                   "temperature": self.temperature,
                                   "top_p": self.top_p,
                                   "max_tokens": self.max_tokens,
                                   "timestamp": self._get_timestamp()
                               }, 
                               response)
        
        return response
    
    def _formater_ticket_pour_analyse(self, ticket_data: Dict) -> str:
        """
        Formate les données du ticket pour l'analyse LLM, avec une meilleure
        gestion des différents formats et structures de données.
        
        Args:
            ticket_data: Les données du ticket
            
        Returns:
            Représentation textuelle formatée du ticket
        """
        # Initialiser avec les informations de base
        ticket_name = ticket_data.get('name', 'Sans titre')
        ticket_code = ticket_data.get('code', 'Inconnu')
        
        info = f"## TICKET {ticket_code}: {ticket_name}\n\n"
        info += f"## NOM DE LA DEMANDE (PROBLÈME INITIAL)\n{ticket_name}\n\n"
        
        # Ajouter la description
        description = ticket_data.get('description', '')
        if description:
            info += f"## DESCRIPTION DU PROBLÈME\n{description}\n\n"
        
        # Ajouter les informations du ticket (exclure certains champs spécifiques)
        champs_a_exclure = ['code', 'name', 'description', 'messages', 'metadata']
        info += "## INFORMATIONS TECHNIQUES DU TICKET\n"
        for key, value in ticket_data.items():
            if key not in champs_a_exclure and value:
                # Formater les valeurs complexes si nécessaire
                if isinstance(value, (dict, list)):
                    value = json.dumps(value, ensure_ascii=False, indent=2)
                info += f"- {key}: {value}\n"
        info += "\n"
        
        # Ajouter les messages (conversations) avec un formatage amélioré pour distinguer client/support
        messages = ticket_data.get('messages', [])
        if messages:
            info += "## CHRONOLOGIE DES ÉCHANGES CLIENT/SUPPORT\n"
            for i, msg in enumerate(messages):
                # Vérifier que le message est bien un dictionnaire
                if not isinstance(msg, dict):
                    continue
                    
                sender = msg.get('from', 'Inconnu')
                date = msg.get('date', 'Date inconnue')
                content = msg.get('content', '')
                
                # Identifier si c'est client ou support
                sender_type = "CLIENT" if "client" in sender.lower() else "SUPPORT" if "support" in sender.lower() else "AUTRE"
                
                # Formater correctement la date si possible
                try:
                    if date != 'Date inconnue':
                        # Essayer différents formats de date
                        for date_format in ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d', '%d/%m/%Y']:
                            try:
                                date_obj = datetime.strptime(date, date_format)
                                date = date_obj.strftime('%d/%m/%Y %H:%M')
                                break
                            except ValueError:
                                continue
                except Exception:
                    pass  # Garder la date d'origine en cas d'erreur
                
                info += f"### Message {i+1} - [{sender_type}] De: {sender} - Date: {date}\n{content}\n\n"
        
        # Ajouter les métadonnées techniques si présentes
        metadata = ticket_data.get('metadata', {})
        # Exclure certaines métadonnées internes
        for key in ['source_file', 'format']:
            if key in metadata:
                metadata.pop(key)
                
        if metadata:
            info += "## MÉTADONNÉES TECHNIQUES\n"
            for key, value in metadata.items():
                if isinstance(value, (dict, list)):
                    value = json.dumps(value, ensure_ascii=False, indent=2)
                info += f"- {key}: {value}\n"
            info += "\n"
        
        return info
    
    def analyser_depuis_fichier(self, chemin_fichier: str) -> str:
        """
        Analyse un ticket à partir d'un fichier (JSON ou Markdown)
        
        Args:
            chemin_fichier: Chemin vers le fichier à analyser
            
        Returns:
            Résultat de l'analyse
        """
        try:
            ticket_data = self.ticket_loader.charger(chemin_fichier)
            return self.executer(ticket_data)
        except Exception as e:
            error_message = f"Erreur lors de l'analyse du fichier {chemin_fichier}: {str(e)}"
            logger.error(error_message)
            return f"ERREUR: {error_message}"
    
    def _get_timestamp(self) -> str:
        """Retourne un timestamp au format YYYYMMDD_HHMMSS"""
        return datetime.now().strftime("%Y%m%d_%H%M%S") 