use crate::config::AppConfig;
use crate::tushare::TushareDataProvider;
use common_contracts::observability::TaskProgress;
use dashmap::DashMap;
use secrecy::{ExposeSecret, SecretString};
use std::sync::Arc;
use tokio::sync::RwLock;
use uuid::Uuid;

#[derive(Clone, Debug)]
pub enum ServiceOperationalStatus {
    Active,
    Degraded { reason: String },
}

#[derive(Clone)]
pub struct AppState {
    pub tasks: Arc<DashMap<Uuid, TaskProgress>>,
    pub config: Arc<AppConfig>,
    pub status: Arc<RwLock<ServiceOperationalStatus>>,
    tushare_provider: Arc<RwLock<Option<TushareDataProvider>>>,
}

impl AppState {
    pub fn new(config: AppConfig) -> Self {
        let (initial_provider, initial_status) =
            if let Some(api_key) = config.tushare_api_token.as_ref() {
                let provider = TushareDataProvider::new(
                    config.tushare_api_url.clone(),
                    api_key.expose_secret().clone(),
                );
                (Some(provider), ServiceOperationalStatus::Active)
            } else {
                (
                    None,
                    ServiceOperationalStatus::Degraded {
                        reason: "Tushare API Key is not configured.".to_string(),
                    },
                )
            };

        Self {
            tasks: Arc::new(DashMap::new()),
            config: Arc::new(config),
            status: Arc::new(RwLock::new(initial_status)),
            tushare_provider: Arc::new(RwLock::new(initial_provider)),
        }
    }

    pub async fn get_provider(&self) -> Option<TushareDataProvider> {
        self.tushare_provider.read().await.clone()
    }

    pub async fn update_provider(&self, api_key: Option<SecretString>, api_url: Option<String>) {
        let mut provider_guard = self.tushare_provider.write().await;
        let mut status_guard = self.status.write().await;

        // Default Tushare URL if not provided or empty
        let final_url = api_url
            .filter(|s| !s.trim().is_empty())
            .unwrap_or_else(|| "http://api.tushare.pro".to_string());

        if let Some(key) = api_key {
            let new_provider = TushareDataProvider::new(
                final_url,
                key.expose_secret().clone(),
            );
            *provider_guard = Some(new_provider);
            *status_guard = ServiceOperationalStatus::Active;
        } else {
            *provider_guard = None;
            *status_guard = ServiceOperationalStatus::Degraded {
                reason: "Tushare API Key is not configured.".to_string(),
            };
        }
    }
}
