"""
Event system for AgentChain callbacks and hooks.
"""

from typing import Callable, Dict, List, Any, Optional
from dataclasses import dataclass
from enum import Enum
import logging


logger = logging.getLogger(__name__)


class Event(Enum):
    """Built-in events that AgentChain emits."""
    
    # Chain lifecycle
    CHAIN_START = "chain_start"
    CHAIN_COMPLETE = "chain_complete"
    CHAIN_ERROR = "chain_error"
    
    # Planning phase
    PLANNING_START = "planning_start"
    PLANNING_COMPLETE = "planning_complete"
    
    # Task execution
    TASK_START = "task_start"
    TASK_COMPLETE = "task_complete"
    TASK_FAILED = "task_failed"
    TASK_RETRY = "task_retry"
    
    # Agent invocation
    AGENT_START = "agent_start"
    AGENT_COMPLETE = "agent_complete"
    AGENT_ERROR = "agent_error"
    
    # File operations
    FILE_CREATED = "file_created"
    FILE_MODIFIED = "file_modified"
    
    # Progress
    PROGRESS = "progress"
    LOG = "log"


@dataclass
class EventData:
    """Data passed with an event."""
    event: Event
    data: Dict[str, Any]
    
    def get(self, key: str, default: Any = None) -> Any:
        return self.data.get(key, default)


# Type alias for event handlers
EventHandler = Callable[[EventData], None]


class EventEmitter:
    """
    Simple event emitter for AgentChain.
    
    Example:
        emitter = EventEmitter()
        
        @emitter.on(Event.TASK_COMPLETE)
        def on_task_done(event):
            print(f"Task completed: {event.data['task']}")
        
        emitter.emit(Event.TASK_COMPLETE, task="Build UI")
    """
    
    def __init__(self):
        self._handlers: Dict[Event, List[EventHandler]] = {}
        self._global_handlers: List[EventHandler] = []
    
    def on(self, event: Event, handler: Optional[EventHandler] = None):
        """
        Register a handler for an event.
        
        Can be used as a decorator:
            @emitter.on(Event.TASK_COMPLETE)
            def handler(event): ...
        
        Or directly:
            emitter.on(Event.TASK_COMPLETE, my_handler)
        """
        def decorator(fn: EventHandler) -> EventHandler:
            if event not in self._handlers:
                self._handlers[event] = []
            self._handlers[event].append(fn)
            return fn
        
        if handler is not None:
            return decorator(handler)
        return decorator
    
    def on_all(self, handler: EventHandler) -> EventHandler:
        """Register a handler for all events."""
        self._global_handlers.append(handler)
        return handler
    
    def off(self, event: Event, handler: EventHandler) -> None:
        """Remove a handler for an event."""
        if event in self._handlers:
            try:
                self._handlers[event].remove(handler)
            except ValueError:
                pass
    
    def emit(self, event: Event, **data) -> None:
        """
        Emit an event with data.
        
        Args:
            event: The event to emit
            **data: Data to pass to handlers
        """
        event_data = EventData(event=event, data=data)
        
        # Call global handlers
        for handler in self._global_handlers:
            try:
                handler(event_data)
            except Exception as e:
                logger.error(f"Error in global event handler: {e}")
        
        # Call event-specific handlers
        if event in self._handlers:
            for handler in self._handlers[event]:
                try:
                    handler(event_data)
                except Exception as e:
                    logger.error(f"Error in event handler for {event}: {e}")
    
    def clear(self) -> None:
        """Clear all handlers."""
        self._handlers.clear()
        self._global_handlers.clear()


class ProgressReporter:
    """
    High-level progress reporting built on EventEmitter.
    
    Provides a user-friendly interface for progress callbacks.
    """
    
    def __init__(self, emitter: EventEmitter):
        self.emitter = emitter
        self._total_tasks = 0
        self._completed_tasks = 0
    
    def set_total(self, total: int) -> None:
        """Set total number of tasks."""
        self._total_tasks = total
    
    def task_complete(self, task_name: str) -> None:
        """Mark a task as complete."""
        self._completed_tasks += 1
        self.emitter.emit(
            Event.PROGRESS,
            completed=self._completed_tasks,
            total=self._total_tasks,
            percent=round(self._completed_tasks / max(self._total_tasks, 1) * 100, 1),
            task=task_name
        )
    
    def log(self, message: str, level: str = "info") -> None:
        """Emit a log event."""
        self.emitter.emit(Event.LOG, message=message, level=level)


# Default console handlers for quick setup
def console_progress_handler(event: EventData) -> None:
    """Print progress to console."""
    if event.event == Event.PROGRESS:
        pct = event.get("percent", 0)
        task = event.get("task", "")
        print(f"[{pct}%] {task}")
    elif event.event == Event.TASK_COMPLETE:
        print(f"✓ {event.get('task', 'Task')} completed")
    elif event.event == Event.TASK_FAILED:
        print(f"✗ {event.get('task', 'Task')} failed: {event.get('error', '')}")
    elif event.event == Event.LOG:
        print(f"[{event.get('level', 'info').upper()}] {event.get('message', '')}")
