#!/usr/bin/env python3
"""
SessionManager - Segmente les actions en sessions pour détecter les workflows
"""

from datetime import datetime, timedelta
from typing import List, Dict, Any, Optional, Callable
from dataclasses import dataclass, field


@dataclass
class Session:
    """Représente une session d'actions utilisateur."""
    session_id: str
    start_time: datetime
    end_time: Optional[datetime] = None
    actions: List[Dict[str, Any]] = field(default_factory=list)
    window: Optional[str] = None
    
    @property
    def duration(self) -> timedelta:
        """Durée de la session."""
        if self.end_time:
            return self.end_time - self.start_time
        return datetime.now() - self.start_time
    
    @property
    def action_count(self) -> int:
        """Nombre d'actions dans la session."""
        return len(self.actions)


class SessionManager:
    """
    Gestionnaire de sessions pour segmenter les actions en sessions.
    Une session = groupe d'actions dans une fenêtre de temps.
    """
    
    def __init__(self, logger, config: Dict[str, Any]):
        """
        Initialise le gestionnaire de sessions.
        
        Args:
            logger: Logger pour journalisation
            config: Configuration globale
        """
        self.logger = logger
        self.config = config
        
        # Configuration
        self.session_timeout = config.get("workflow", {}).get(
            "session_timeout", 300  # 5 minutes par défaut
        )
        
        # Session courante
        self.current_session: Optional[Session] = None
        
        # Historique des sessions
        self.sessions: List[Session] = []
        
        # Callback pour session complétée
        self.on_session_completed: Optional[Callable] = None
        
        if self.logger:
            self.logger.log_action({
                "action": "session_manager_initialized",
                "session_timeout": self.session_timeout
            })
    
    def add_action(self, action: Dict[str, Any]):
        """
        Ajoute une action à la session courante.
        Crée une nouvelle session si nécessaire.
        
        Args:
            action: Action à ajouter
        """
        # Vérifier si on doit créer une nouvelle session
        if self.should_start_new_session(action):
            self.finalize_current_session()
            self.start_new_session(action)
        
        # Ajouter l'action à la session courante
        if self.current_session:
            self.current_session.actions.append(action)
    
    def should_start_new_session(self, action: Dict[str, Any]) -> bool:
        """
        Détermine si une nouvelle session doit être créée.
        
        Args:
            action: Action à évaluer
            
        Returns:
            True si nouvelle session nécessaire
        """
        # Pas de session courante
        if not self.current_session:
            return True
        
        # Vérifier le timeout
        if self.current_session.actions:
            last_action = self.current_session.actions[-1]
            last_time = last_action.get("timestamp")
            
            if last_time:
                if isinstance(last_time, str):
                    last_time = datetime.fromisoformat(last_time)
                
                current_time = action.get("timestamp")
                if isinstance(current_time, str):
                    current_time = datetime.fromisoformat(current_time)
                elif not current_time:
                    current_time = datetime.now()
                
                time_gap = (current_time - last_time).total_seconds()
                
                if time_gap > self.session_timeout:
                    return True
        
        # Changement de fenêtre majeur
        current_window = action.get("window")
        if current_window and self.current_session.window:
            if current_window != self.current_session.window:
                return True
        
        return False
    
    def start_new_session(self, first_action: Dict[str, Any]):
        """
        Démarre une nouvelle session.
        
        Args:
            first_action: Première action de la session
        """
        session_id = f"session_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        
        timestamp = first_action.get("timestamp")
        if isinstance(timestamp, str):
            timestamp = datetime.fromisoformat(timestamp)
        elif not timestamp:
            timestamp = datetime.now()
        
        self.current_session = Session(
            session_id=session_id,
            start_time=timestamp,
            window=first_action.get("window")
        )
        
        if self.logger:
            self.logger.log_action({
                "action": "session_started",
                "session_id": session_id,
                "window": first_action.get("window")
            })
    
    def finalize_current_session(self):
        """Finalise la session courante."""
        if not self.current_session:
            return
        
        # Marquer la fin
        self.current_session.end_time = datetime.now()
        
        # Ajouter à l'historique
        self.sessions.append(self.current_session)
        
        # Callback (l'Orchestrator loggera avec plus de détails)
        if self.on_session_completed:
            self.on_session_completed(self.current_session)
        
        # Réinitialiser
        self.current_session = None
    
    def force_finalize_session(self):
        """Force la finalisation de la session courante."""
        self.finalize_current_session()
    
    def get_recent_sessions(self, n: int = 10) -> List[Session]:
        """
        Retourne les N sessions les plus récentes.
        
        Args:
            n: Nombre de sessions à retourner
            
        Returns:
            Liste des sessions récentes
        """
        return self.sessions[-n:] if len(self.sessions) >= n else self.sessions
    
    def get_stats(self) -> Dict[str, Any]:
        """Retourne les statistiques des sessions."""
        return {
            "total_sessions": len(self.sessions),
            "current_session_actions": self.current_session.action_count if self.current_session else 0,
            "avg_session_duration": sum(s.duration.total_seconds() for s in self.sessions) / len(self.sessions) if self.sessions else 0,
            "avg_actions_per_session": sum(s.action_count for s in self.sessions) / len(self.sessions) if self.sessions else 0
        }
