use crate::*;

#[uniffi::export(async_runtime = "tokio")]
impl GotchaCore {
    pub async fn commits(
        &self,
        owner: String,
        repository: String,
        branch: Option<String>,
        path: String,
        pages: u32,
    ) -> Result<CommitPage, GotchaError> {
        let server = self.server()?;
        let default_branch = self
            .state
            .lock()
            .unwrap()
            .repositories
            .iter()
            .find(|candidate| candidate.owner == owner && candidate.name == repository)
            .map(|candidate| candidate.default_branch.clone())
            .unwrap_or_else(|| "main".into());
        let branches = load_branches(&server, &owner, &repository, &default_branch).await?;
        let path = (!path.is_empty()).then_some(path.as_str());
        let commits = match branch.as_deref() {
            Some(branch) => {
                load_branch_commits(&server, &owner, &repository, branch, path, pages.max(1))
                    .await?
            }
            None => {
                load_all_commits(&server, &owner, &repository, &branches, path, pages.max(1))
                    .await?
            }
        };
        Ok(commit_page(
            branches,
            &commits.items,
            branch.is_none(),
            commits.has_more,
        ))
    }

    pub async fn repository_contents(
        &self,
        owner: String,
        repository: String,
        path: String,
    ) -> Result<Vec<RepositoryContentRow>, GotchaError> {
        Ok(repository_content_rows(
            load_repository_contents(&self.server()?, &owner, &repository, &path).await?,
        ))
    }

    pub async fn repository_file(
        &self,
        owner: String,
        repository: String,
        path: String,
    ) -> Result<RepositoryFilePage, GotchaError> {
        let data = load_repository_file(&self.server()?, &owner, &repository, &path).await?;
        Ok(repository_file_page(&path, data))
    }

    pub async fn commit_details(
        &self,
        owner: String,
        repository: String,
        sha: String,
        branch: Option<String>,
    ) -> Result<CommitDetailsPage, GotchaError> {
        Ok(commit_details_page(
            load_commit(&self.server()?, &owner, &repository, &sha).await?,
            branch,
        ))
    }

    pub async fn commit_diff(
        &self,
        owner: String,
        repository: String,
        sha: String,
        path: String,
    ) -> Result<DiffPage, GotchaError> {
        Ok(diff_page(
            &path,
            load_commit_diff(&self.server()?, &owner, &repository, &sha, &path).await?,
        ))
    }

    pub async fn pull_diff(
        &self,
        owner: String,
        repository: String,
        number: i64,
        path: String,
    ) -> Result<DiffPage, GotchaError> {
        Ok(diff_page(
            &path,
            load_pull_diff(&self.server()?, &owner, &repository, number, &path).await?,
        ))
    }
}
