//! Client factory for creating extension clients from configuration

use std::sync::Arc;

use tracing::info;

use super::traits::{DistributionClient, SourceClient};
use super::{ForgejoClient, GitHubClient};
use crate::config::Config;
use crate::error::{RegistryError, Result};
use crate::gitea::GiteaClient as GiteaClientImpl;
use crate::oci::OciClient as OciClientImpl;

/// Factory for creating extension clients
pub struct ClientFactory;

impl ClientFactory {
    /// Create all configured clients from configuration
    pub fn create_from_config(
        config: &Config,
    ) -> Result<(Vec<Arc<dyn SourceClient>>, Vec<Arc<dyn DistributionClient>>)> {
        let mut source_clients: Vec<Arc<dyn SourceClient>> = Vec::new();
        let mut distribution_clients: Vec<Arc<dyn DistributionClient>> = Vec::new();

        // Create Gitea clients (source-based)
        if let Some(ref gitea_config) = config.gitea {
            let client = GiteaClientImpl::new(gitea_config)?;
            let wrapped = Arc::new(client) as Arc<dyn SourceClient>;
            source_clients.push(wrapped);
            info!("Registered Gitea client: {}", gitea_config.url);
        }

        // Create Forgejo clients (source-based)
        if let Some(ref forgejo_config) = config.gitea {
            let client = ForgejoClient::new(forgejo_config)?;
            let wrapped = Arc::new(client) as Arc<dyn SourceClient>;
            source_clients.push(wrapped);
            info!("Registered Forgejo client: {}", forgejo_config.url);
        }

        // Create GitHub clients (source-based)
        if let Some(ref github_config) = config.gitea {
            let client = GitHubClient::new(github_config)?;
            let wrapped = Arc::new(client) as Arc<dyn SourceClient>;
            source_clients.push(wrapped);
            info!("Registered GitHub client: {}", github_config.organization);
        }

        // Create OCI clients (distribution-based)
        if let Some(ref oci_config) = config.oci {
            let client = OciClientImpl::new(oci_config)?;
            let wrapped = Arc::new(client) as Arc<dyn DistributionClient>;
            distribution_clients.push(wrapped);
            info!("Registered OCI client: {}", oci_config.registry);
        }

        // Ensure at least one backend is configured
        if source_clients.is_empty() && distribution_clients.is_empty() {
            return Err(RegistryError::Config(
                "No backends configured (gitea, forgejo, github, or oci required)".to_string(),
            ));
        }

        info!(
            "Initialized {} source clients and {} distribution clients",
            source_clients.len(),
            distribution_clients.len()
        );

        Ok((source_clients, distribution_clients))
    }
}
