//! Forgejo client implementation
//!
//! Forgejo API is fully compatible with Gitea API, so this implementation
//! uses composition to wrap GiteaClient and delegate all operations to it.
//! This allows Forgejo instances to work seamlessly with the same interface
//! while maintaining independent backend identification.

use async_trait::async_trait;
use bytes::Bytes;

use super::traits::{BackendType, ExtensionClient, ReleaseInfo, SourceClient};
use crate::error::Result;
use crate::models::{Extension, ExtensionType, ExtensionVersion};

/// Forgejo client (wraps GiteaClient since Forgejo API is Gitea-compatible)
pub struct ForgejoClient {
    backend_id: String,
    inner: crate::gitea::GiteaClient,
}

impl ForgejoClient {
    /// Create new Forgejo client with a pre-resolved token.
    ///
    /// Token resolution (file read or vault:// fetch) is the caller's
    /// responsibility.
    pub fn new(config: &crate::config::GiteaConfig, token: String) -> Result<Self> {
        let backend_id = config
            .id
            .clone()
            .unwrap_or_else(|| format!("forgejo-{}", config.organization));

        let inner = crate::gitea::GiteaClient::new(config, token)?;

        Ok(Self { backend_id, inner })
    }
}

/// ExtensionClient trait implementation for Forgejo
#[async_trait]
impl ExtensionClient for ForgejoClient {
    fn backend_id(&self) -> &str {
        &self.backend_id
    }

    fn backend_type(&self) -> BackendType {
        BackendType::Forgejo
    }

    async fn list_extensions(
        &self,
        extension_type: Option<ExtensionType>,
    ) -> Result<Vec<Extension>> {
        self.inner.list_extensions(extension_type).await
    }

    async fn get_extension(&self, extension_type: ExtensionType, name: &str) -> Result<Extension> {
        self.inner.get_extension(extension_type, name).await
    }

    async fn list_versions(
        &self,
        extension_type: ExtensionType,
        name: &str,
    ) -> Result<Vec<ExtensionVersion>> {
        self.inner.list_versions(extension_type, name).await
    }

    async fn download_extension(
        &self,
        extension_type: ExtensionType,
        name: &str,
        version: &str,
    ) -> Result<Bytes> {
        self.inner
            .download_extension(extension_type, name, version)
            .await
    }

    async fn health_check(&self) -> Result<()> {
        self.inner.health_check().await
    }
}

/// SourceClient trait implementation for Forgejo
#[async_trait]
impl SourceClient for ForgejoClient {
    async fn get_repository_url(
        &self,
        extension_type: ExtensionType,
        name: &str,
    ) -> Result<String> {
        self.inner.get_repository_url(extension_type, name).await
    }

    async fn list_releases(&self, repo_name: &str) -> Result<Vec<ReleaseInfo>> {
        self.inner.list_releases(repo_name).await
    }

    async fn get_release_notes(&self, repo_name: &str, version: &str) -> Result<String> {
        self.inner.get_release_notes(repo_name, version).await
    }
}
