use anyhow::Result;
use async_trait::async_trait;

use super::config::NexusPhpConfig;
use super::engine::NexusPhpEngine;
use super::profile::NexusPhpSite;
use crate::site::capabilities::SiteCapabilities;
use crate::site::provider::SiteProvider;
use crate::site::query::MediaResourceQuery;
use crate::site::types::{ResolvedSiteDownload, ResourceCandidate};
use crate::types::{Provider, ProviderStatus};

pub struct NexusPhpProvider<'a> {
    site: &'a NexusPhpSite,
    engine: NexusPhpEngine<'a>,
}

impl<'a> NexusPhpProvider<'a> {
    pub fn new(config: &'a NexusPhpConfig, site: &'a NexusPhpSite) -> Result<Self> {
        Ok(Self {
            engine: NexusPhpEngine::new(config, site)?,
            site,
        })
    }
}

#[async_trait]
impl<'a> Provider for NexusPhpProvider<'a> {
    fn key(&self) -> &str {
        &self.site.key
    }

    fn name(&self) -> &str {
        &self.site.name
    }

    async fn health_check(&self) -> ProviderStatus {
        match self.engine.check_alive().await {
            Ok(latency_ms) => ProviderStatus::Healthy { latency_ms },
            Err(_) => ProviderStatus::Unhealthy,
        }
    }
}

#[async_trait]
impl<'a> SiteProvider for NexusPhpProvider<'a> {
    async fn search_resources(&self, query: &MediaResourceQuery) -> Result<Vec<ResourceCandidate>> {
        self.engine.search_resources(query).await
    }

    async fn latest_resources(&self) -> Result<Vec<ResourceCandidate>> {
        self.engine.latest_resources().await
    }

    async fn resolve(&self, candidate: &ResourceCandidate) -> Result<ResolvedSiteDownload> {
        self.engine.resolve(candidate).await
    }

    fn capabilities(&self) -> SiteCapabilities {
        SiteCapabilities::SEARCH
            | SiteCapabilities::DIRECT_DOWNLOAD
            | SiteCapabilities::DETAIL_LOOKUP
    }
}
