use crate::event::{Event, EventError};
use crate::event_bus::EventBus;
use crate::scheduler::EventScheduler;
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio::time::{sleep, Duration, Instant};
use tracing::{error, info, warn};
use chrono::Utc;

/// Main runtime orchestrating the event loop
pub struct Runtime {
    event_bus: Arc<EventBus>,
    scheduler: Arc<EventScheduler>,
    running: Arc<RwLock<bool>>,
    max_events_per_tick: usize,
    tick_interval_ms: u64,
}

impl Runtime {
    pub fn new(max_history_size: usize, max_events_per_tick: usize, tick_interval_ms: u64) -> Self {
        Self {
            event_bus: Arc::new(EventBus::new(max_history_size)),
            scheduler: Arc::new(EventScheduler::new()),
            running: Arc::new(RwLock::new(false)),
            max_events_per_tick,
            tick_interval_ms,
        }
    }
    
    pub fn event_bus(&self) -> Arc<EventBus> {
        self.event_bus.clone()
    }
    
    pub fn scheduler(&self) -> Arc<EventScheduler> {
        self.scheduler.clone()
    }
    
    /// Start the event loop
    pub async fn start(&self) {
        let mut running = self.running.write().await;
        if *running {
            warn!("Runtime already running");
            return;
        }
        *running = true;
        drop(running);
        
        info!("Starting Lumina runtime event loop");
        
        let event_bus = self.event_bus.clone();
        let scheduler = self.scheduler.clone();
        let running = self.running.clone();
        let _max_events = self.max_events_per_tick;
        let tick_interval = Duration::from_millis(self.tick_interval_ms);
        
        tokio::spawn(async move {
            while *running.read().await {
                let tick_start = Instant::now();
                
                // Process scheduled events
                let ready_events = scheduler.get_ready_events().await;
                for event in ready_events {
                    match event_bus.publish(event).await {
                        Ok(new_events) => {
                            // Publish any new events generated by handlers
                            for new_event in new_events {
                                if let Err(e) = event_bus.publish(new_event).await {
                                    error!("Error publishing generated event: {}", e);
                                }
                            }
                        }
                        Err(e) => {
                            error!("Error processing scheduled event: {}", e);
                        }
                    }
                }
                
                // Check if we should continue
                if !*running.read().await {
                    break;
                }
                
                // Sleep to prevent busy-waiting
                let elapsed = tick_start.elapsed();
                if elapsed < tick_interval {
                    sleep(tick_interval - elapsed).await;
                }
            }
            
            info!("Runtime event loop stopped");
        });
    }
    
    /// Stop the event loop
    pub async fn stop(&self) {
        let mut running = self.running.write().await;
        *running = false;
        info!("Stopping Lumina runtime");
    }
    
    /// Check if runtime is running
    pub async fn is_running(&self) -> bool {
        *self.running.read().await
    }
    
    /// Publish an event immediately
    pub async fn publish(&self, event: Event) -> Result<Vec<Event>, EventError> {
        // If event has a scheduled time, use scheduler
        if let Some(scheduled_at) = event.scheduled_at {
            if scheduled_at > Utc::now() {
                self.scheduler.schedule(event, scheduled_at).await;
                return Ok(Vec::new());
            }
        }
        
        // Otherwise publish immediately
        self.event_bus.publish(event).await
    }
    
    /// Get runtime statistics
    pub async fn stats(&self) -> RuntimeStats {
        RuntimeStats {
            is_running: self.is_running().await,
            handler_count: self.event_bus.handler_count().await,
            scheduled_events: self.scheduler.queue_size().await,
            event_history_size: self.event_bus.get_history(None).await.len(),
        }
    }
}

/// Runtime statistics
#[derive(Debug, Clone)]
pub struct RuntimeStats {
    pub is_running: bool,
    pub handler_count: usize,
    pub scheduled_events: usize,
    pub event_history_size: usize,
}

impl Default for Runtime {
    fn default() -> Self {
        Self::new(10000, 100, 10)
    }
}

