use std::sync::Arc;
use tokio::sync::broadcast;

use crate::{
    client::ClientManager, config::AppConfig, database::DbPool, logging::RequestLogger,
    models::registry::ModelRegistry, providers::ProviderManager, rate_limiting::RateLimitManager,
};

/// Shared application state
#[derive(Clone)]
pub struct AppState {
    pub config: Arc<AppConfig>,
    pub provider_manager: ProviderManager,
    pub db_pool: DbPool,
    pub rate_limit_manager: Arc<RateLimitManager>,
    pub client_manager: Arc<ClientManager>,
    pub request_logger: Arc<RequestLogger>,
    pub model_registry: Arc<ModelRegistry>,
    pub dashboard_tx: broadcast::Sender<serde_json::Value>,
    pub auth_tokens: Vec<String>,
}

impl AppState {
    pub fn new(
        config: Arc<AppConfig>,
        provider_manager: ProviderManager,
        db_pool: DbPool,
        rate_limit_manager: RateLimitManager,
        model_registry: ModelRegistry,
        auth_tokens: Vec<String>,
    ) -> Self {
        let client_manager = Arc::new(ClientManager::new(db_pool.clone()));
        let (dashboard_tx, _) = broadcast::channel(100);
        let request_logger = Arc::new(RequestLogger::new(db_pool.clone(), dashboard_tx.clone()));

        Self {
            config,
            provider_manager,
            db_pool,
            rate_limit_manager: Arc::new(rate_limit_manager),
            client_manager,
            request_logger,
            model_registry: Arc::new(model_registry),
            dashboard_tx,
            auth_tokens,
        }
    }
}
