use std::sync::Arc;

use tonic::{Request, Response, Status};

use crate::rpc::{
    error::{spawn_blocking_error, to_status},
    proto as p,
    registry::RepoRegistry,
};

pub struct ArchiveServiceImpl {
    pub registry: Arc<RepoRegistry>,
}

#[tonic::async_trait]
impl p::archive_service_server::ArchiveService for ArchiveServiceImpl {
    async fn archive_tar(
        &self,
        req: Request<p::ArchiveTarRequest>,
    ) -> Result<Response<p::ArchiveTarResponse>, Status> {
        let inner = req.into_inner();
        let bare = self.registry.get(&inner.repo_id).await?;
        let options = inner.options.unwrap_or_default().into();
        let result =
            tokio::task::spawn_blocking(move || bare.archive_tar(options))
                .await
                .map_err(spawn_blocking_error)?
                .map_err(to_status)?;
        Ok(Response::new(p::ArchiveTarResponse { data: result.bytes }))
    }

    async fn archive_zip(
        &self,
        req: Request<p::ArchiveZipRequest>,
    ) -> Result<Response<p::ArchiveZipResponse>, Status> {
        let inner = req.into_inner();
        let bare = self.registry.get(&inner.repo_id).await?;
        let options = inner.options.unwrap_or_default().into();
        let result =
            tokio::task::spawn_blocking(move || bare.archive_zip(options))
                .await
                .map_err(spawn_blocking_error)?
                .map_err(to_status)?;
        Ok(Response::new(p::ArchiveZipResponse { data: result.bytes }))
    }
}
