use crate::TimeProvider;
use chrono::{DateTime, Utc};
use parking_lot::Mutex;
use std::sync::Arc;

// Real-time provider for paper and live trading
pub struct SystemTime;

impl SystemTime {
    pub fn new() -> Self {
        Self
    }
}

impl TimeProvider for SystemTime {
    fn now(&self) -> DateTime<Utc> {
        Utc::now()
    }

    fn sleep_until(&self, target: DateTime<Utc>) -> Result<(), String> {
        let now = Utc::now();
        if target > now {
            let duration = (target - now).to_std()
                .map_err(|e| format!("Invalid duration: {}", e))?;
            std::thread::sleep(duration);
        }
        Ok(())
    }
    
    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
}

// Simulated time for backtesting
pub struct SimulatedTime {
    current_time: Arc<Mutex<DateTime<Utc>>>,
}

impl SimulatedTime {
    pub fn new(start_time: DateTime<Utc>) -> Self {
        Self {
            current_time: Arc::new(Mutex::new(start_time)),
        }
    }

    pub fn advance_to(&self, new_time: DateTime<Utc>) {
        let mut current = self.current_time.lock();
        if new_time > *current {
            *current = new_time;
        }
    }

    pub fn advance_by(&self, duration: chrono::Duration) {
        let mut current = self.current_time.lock();
        *current = *current + duration;
    }
}

impl TimeProvider for SimulatedTime {
    fn now(&self) -> DateTime<Utc> {
        *self.current_time.lock()
    }

    fn sleep_until(&self, _target: DateTime<Utc>) -> Result<(), String> {
        // In backtest mode, we don't actually sleep
        // Time is controlled by the backtest engine
        Ok(())
    }
    
    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
}