use git::rpc::{proto as p, proto::blame_service_client::BlameServiceClient};
use session::Session;

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

impl AppService {
    pub async fn git_blame_file(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        path: String,
        rev: Option<String>,
        options: Option<p::BlameOptions>,
    ) -> Result<p::BlameFileResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = BlameServiceClient::new(self.git.clone());
        let resp = client
            .blame_file(tonic::Request::new(p::BlameFileRequest {
                repo_id: repo.id.to_string(),
                path,
                rev,
                options,
            }))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }

    pub async fn git_blame_hunk(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        path: String,
        rev: Option<String>,
        start_line: u32,
        end_line: u32,
    ) -> Result<p::BlameHunkResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = BlameServiceClient::new(self.git.clone());
        let resp = client
            .blame_hunk(tonic::Request::new(p::BlameHunkRequest {
                repo_id: repo.id.to_string(),
                path,
                rev,
                start_line,
                end_line,
            }))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }

    pub async fn git_blame_lines(
        &self,
        ctx: &Session,
        wk_name: &str,
        repo_name: &str,
        path: String,
        rev: Option<String>,
        start_line: u32,
        end_line: u32,
    ) -> Result<p::BlameLinesResponse, AppError> {
        let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
        let mut client = BlameServiceClient::new(self.git.clone());
        let resp = client
            .blame_lines(tonic::Request::new(p::BlameLinesRequest {
                repo_id: repo.id.to_string(),
                path,
                rev,
                start_line,
                end_line,
            }))
            .await
            .map_err(rpc_err)?
            .into_inner();
        Ok(resp)
    }
}
