use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use uuid::Uuid;

/// Event priority for scheduling
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum EventPriority {
    Low = 0,
    Normal = 1,
    High = 2,
    Critical = 3,
}

impl Default for EventPriority {
    fn default() -> Self {
        EventPriority::Normal
    }
}

/// Core event types in the system
#[derive(Debug, Clone, Serialize, Deserialize, Eq, Hash, PartialEq)]
pub enum EventType {
    /// Agent lifecycle events
    AgentCreated,
    AgentStarted,
    AgentStepCompleted,
    AgentStepFailed,
    AgentCompleted,
    AgentFailed,
    
    /// Tool execution events
    ToolCallRequested,
    ToolCallStarted,
    ToolCallCompleted,
    ToolCallFailed,
    ToolCallRetrying,
    
    /// Memory events
    MemoryRead,
    MemoryWrite,
    MemoryUpdated,
    
    /// LLM events
    LLMCallRequested,
    LLMCallStarted,
    LLMCallCompleted,
    LLMCallFailed,
    
    /// Workflow events
    WorkflowStarted,
    WorkflowStepCompleted,
    WorkflowCompleted,
    WorkflowFailed,
    
    /// Custom user-defined events
    Custom(String),
}

/// Event payload - flexible JSON structure
pub type EventPayload = serde_json::Value;

/// Core Event structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
    /// Unique event identifier
    pub id: Uuid,
    
    /// Event type
    pub event_type: EventType,
    
    /// Source agent/tool/component ID
    pub source: String,
    
    /// Target agent/tool/component ID (if applicable)
    pub target: Option<String>,
    
    /// Event payload (JSON)
    pub payload: EventPayload,
    
    /// Event metadata
    pub metadata: HashMap<String, String>,
    
    /// Timestamp when event was created
    pub timestamp: DateTime<Utc>,
    
    /// Priority for scheduling
    pub priority: EventPriority,
    
    /// Deterministic seed for this event (for reproducibility)
    pub seed: u64,
    
    /// Parent event ID (for event chains)
    pub parent_id: Option<Uuid>,
    
    /// Scheduled execution time (for delayed events)
    pub scheduled_at: Option<DateTime<Utc>>,
}

impl Event {
    pub fn new(
        event_type: EventType,
        source: String,
        payload: EventPayload,
        seed: u64,
    ) -> Self {
        Self {
            id: Uuid::new_v4(),
            event_type,
            source,
            target: None,
            payload,
            metadata: HashMap::new(),
            timestamp: Utc::now(),
            priority: EventPriority::Normal,
            seed,
            parent_id: None,
            scheduled_at: None,
        }
    }
    
    pub fn with_target(mut self, target: String) -> Self {
        self.target = Some(target);
        self
    }
    
    pub fn with_priority(mut self, priority: EventPriority) -> Self {
        self.priority = priority;
        self
    }
    
    pub fn with_parent(mut self, parent_id: Uuid) -> Self {
        self.parent_id = Some(parent_id);
        self
    }
    
    pub fn with_metadata(mut self, key: String, value: String) -> Self {
        self.metadata.insert(key, value);
        self
    }
    
    pub fn schedule(mut self, scheduled_at: DateTime<Utc>) -> Self {
        self.scheduled_at = Some(scheduled_at);
        self
    }
    
    /// Check if event should be executed now
    pub fn is_ready(&self) -> bool {
        self.scheduled_at
            .map(|scheduled| scheduled <= Utc::now())
            .unwrap_or(true)
    }
}

/// Event handler trait for components that process events
#[async_trait::async_trait]
pub trait EventHandler: Send + Sync {
    /// Handle an event, returning optional new events to emit
    async fn handle(&self, event: &Event) -> Result<Vec<Event>, EventError>;
    
    /// Get event types this handler is interested in
    fn interested_events(&self) -> Vec<EventType>;
}

/// Event processing errors
#[derive(Debug, thiserror::Error)]
pub enum EventError {
    #[error("Event handler error: {0}")]
    HandlerError(String),
    
    #[error("Event serialization error: {0}")]
    SerializationError(#[from] serde_json::Error),
    
    #[error("Event processing timeout")]
    Timeout,
    
    #[error("Event handler not found")]
    HandlerNotFound,
}

