use tracing::{error, info};

use super::provider::MetadataProvider;
use super::providers::tmdb::TmdbProvider;
use super::types::MediaMetadata;

pub struct MetadataProviderHub {
    providers: Vec<Box<dyn MetadataProvider>>,
}

impl MetadataProviderHub {
    #[must_use]
    pub fn new() -> Self {
        Self { providers: vec![] }
    }

    #[must_use]
    pub fn configured(tmdb_api_key: Option<&str>) -> Self {
        let mut hub = Self::new();

        if let Some(api_key) = tmdb_api_key.filter(|value| !value.is_empty()) {
            hub.register(Box::new(TmdbProvider::new(api_key.to_string())));
        }

        hub
    }

    pub fn register(&mut self, provider: Box<dyn MetadataProvider>) {
        info!(
            "Registered metadata provider: {} ({})",
            provider.key(),
            provider.name()
        );
        self.providers.push(provider);
    }

    pub async fn search(&self, query: &str) -> Option<MediaMetadata> {
        for provider in &self.providers {
            if !provider.is_enabled() {
                continue;
            }

            match provider.search(query).await {
                Ok(metadata) => {
                    info!(
                        "Metadata provider {} ({}) returned result",
                        provider.key(),
                        provider.name()
                    );

                    return Some(metadata);
                }
                Err(error) => {
                    error!(
                        "Metadata provider {} ({}) failed: {}",
                        provider.key(),
                        provider.name(),
                        error
                    );
                }
            }
        }

        None
    }
}

impl Default for MetadataProviderHub {
    fn default() -> Self {
        Self::new()
    }
}
