use crate::{MarketDataSource, MarketUpdate};
use chrono::{DateTime, Utc};
use parking_lot::Mutex;
use std::collections::VecDeque;
use super::mock_data_generator::MockDataGenerator;

// Historical data source for backtesting
pub struct HistoricalDataSource {
    data_queue: Mutex<VecDeque<MarketUpdate>>,
    current_position: Mutex<usize>,
}

impl HistoricalDataSource {
    pub fn new() -> Self {
        Self {
            data_queue: Mutex::new(VecDeque::new()),
            current_position: Mutex::new(0),
        }
    }

    // This would be called by the orchestrator to load data
    pub fn load_data(&self, data: Vec<MarketUpdate>) {
        eprintln!("HistoricalDataSource::load_data called with {} items", data.len());
        
        // Log first few items
        for (i, update) in data.iter().take(3).enumerate() {
            eprintln!("  Item {}: symbol={}, time={}", i, update.symbol, update.timestamp);
        }
        
        let mut queue = self.data_queue.lock();
        queue.clear();
        queue.extend(data);
        *self.current_position.lock() = 0;
        
        eprintln!("Data loaded successfully. Queue size: {}", queue.len());
    }
    
    pub fn data_len(&self) -> usize {
        self.data_queue.lock().len()
    }
    
    // Generate mock data for testing
    pub fn generate_mock_data(
        &self, 
        symbol: String, 
        start_time: DateTime<Utc>, 
        end_time: DateTime<Utc>,
        seed: Option<u64>
    ) {
        let mut generator = MockDataGenerator::new(seed.unwrap_or(42));
        let data = generator.generate_mixed_data(symbol, start_time, end_time);
        self.load_data(data);
    }
}

#[async_trait::async_trait]
impl MarketDataSource for HistoricalDataSource {
    async fn get_next_update(&mut self) -> Option<MarketUpdate> {
        let queue = self.data_queue.lock();
        let mut position = self.current_position.lock();
        
        if *position < queue.len() {
            let update = queue[*position].clone();
            *position += 1;
            Some(update)
        } else {
            None
        }
    }

    fn seek_to_time(&mut self, timestamp: DateTime<Utc>) -> Result<(), String> {
        let queue = self.data_queue.lock();
        let mut position = self.current_position.lock();
        
        eprintln!("HistoricalDataSource::seek_to_time called");
        eprintln!("  Target time: {}", timestamp);
        eprintln!("  Queue size: {}", queue.len());
        
        if queue.is_empty() {
            eprintln!("  WARNING: Queue is empty!");
            return Ok(());
        }
        
        eprintln!("  First item time: {}", queue.front().map(|u| u.timestamp.to_string()).unwrap_or("N/A".to_string()));
        eprintln!("  Last item time: {}", queue.back().map(|u| u.timestamp.to_string()).unwrap_or("N/A".to_string()));
        
        // Binary search for the timestamp
        match queue.binary_search_by_key(&timestamp, |update| update.timestamp) {
            Ok(pos) => {
                *position = pos;
                eprintln!("  Found exact match at position {}", pos);
                Ok(())
            }
            Err(pos) => {
                // Position where it would be inserted
                *position = pos;
                eprintln!("  No exact match, would insert at position {}", pos);
                Ok(())
            }
        }
    }
    
    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
    
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
        self
    }
}

// Live data source for paper and live trading
pub struct LiveDataSource {
    // Channel to receive data from the orchestrator
    data_receiver: tokio::sync::Mutex<Option<tokio::sync::mpsc::Receiver<MarketUpdate>>>,
}

impl LiveDataSource {
    pub fn new() -> Self {
        Self {
            data_receiver: tokio::sync::Mutex::new(None),
        }
    }

    pub async fn set_receiver(&self, receiver: tokio::sync::mpsc::Receiver<MarketUpdate>) {
        *self.data_receiver.lock().await = Some(receiver);
    }
}

#[async_trait::async_trait]
impl MarketDataSource for LiveDataSource {
    async fn get_next_update(&mut self) -> Option<MarketUpdate> {
        let mut receiver_guard = self.data_receiver.lock().await;
        if let Some(receiver) = receiver_guard.as_mut() {
            receiver.recv().await
        } else {
            None
        }
    }

    fn seek_to_time(&mut self, _timestamp: DateTime<Utc>) -> Result<(), String> {
        Err("Cannot seek in live data source".to_string())
    }
    
    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
    
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
        self
    }
}