use git::rpc::{proto as p, proto::tree_service_client::TreeServiceClient};
use session::Session;

use crate::{AppService, error::AppError, git::rpc_err};

impl AppService {
    pub async fn git_tree_entries(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        oid: String,
        base_path: String,
        last: bool,
    ) -> Result<p::TreeEntriesResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = TreeServiceClient::new(self.git.clone());
        let resp = client
            .tree_entries(tonic::Request::new(p::TreeEntriesRequest {
                repo_id: repo.id.to_string(),
                oid: Some(p::ObjectId { value: oid }),
                base_path,
                last,
            }))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }

    pub async fn git_tree_entry_by_path(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        tree_oid: String,
        path: String,
    ) -> Result<p::TreeEntryByPathResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = TreeServiceClient::new(self.git.clone());
        let resp = client
            .tree_entry_by_path(tonic::Request::new(
                p::TreeEntryByPathRequest {
                    repo_id: repo.id.to_string(),
                    tree_oid: Some(p::ObjectId { value: tree_oid }),
                    path,
                },
            ))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }

    pub async fn git_tree_entry_by_path_from_commit(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        commit_oid: String,
        path: String,
    ) -> Result<p::TreeEntryByPathFromCommitResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = TreeServiceClient::new(self.git.clone());
        let resp = client
            .tree_entry_by_path_from_commit(tonic::Request::new(
                p::TreeEntryByPathFromCommitRequest {
                    repo_id: repo.id.to_string(),
                    commit_oid: Some(p::ObjectId { value: commit_oid }),
                    path,
                },
            ))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }

    pub async fn git_resolve_tree(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        oid: String,
    ) -> Result<p::ResolveTreeResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = TreeServiceClient::new(self.git.clone());
        let resp = client
            .resolve_tree(tonic::Request::new(p::ResolveTreeRequest {
                repo_id: repo.id.to_string(),
                oid: Some(p::ObjectId { value: oid }),
            }))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }
}
