use crate::archweb::{ArchwebPackage, SearchResult, ARCHWEB_ENDPOINT};
use crate::error::ReproStatusError;
use crate::package::LogType;
use rebuilderd_common::PkgRelease as RebuilderdPackage;
use reqwest::Client as HttpClient;
use url::Url;

/// Fetches the packages of the specified maintainer from archlinux.org
pub async fn fetch_archweb_packages<'a>(
    client: &'a HttpClient,
    maintainer: &'a str,
) -> Result<Vec<ArchwebPackage>, ReproStatusError> {
    let url = format!("{ARCHWEB_ENDPOINT}/?maintainer={maintainer}");
    let response = client
        .get(&url)
        .send()
        .await?
        .json::<SearchResult>()
        .await?;
    let mut results = response.results;
    if let (Some(page), Some(num_pages)) = (response.page, response.num_pages) {
        for page in (page + 1)..=num_pages {
            results.extend(
                client
                    .get(format!("{}&page={}", &url, page))
                    .send()
                    .await?
                    .json::<SearchResult>()
                    .await?
                    .results,
            )
        }
    }
    Ok(results)
}

/// Fetches the packages from the specified rebuilderd instance.
pub async fn fetch_rebuilderd_packages(
    client: &HttpClient,
    rebuilder: &Url,
) -> Result<Vec<RebuilderdPackage>, ReproStatusError> {
    let url = rebuilder.join("api/v0/pkgs/list?distro=archlinux")?;
    log::debug!("Sending request to {url}");
    Ok(client.get(url.as_str()).send().await?.json().await?)
}

/// Fetches the package logs from the specified rebuilderd instance.
pub async fn fetch_rebuilderd_logs(
    client: &HttpClient,
    rebuilder: &Url,
    build_id: i32,
    log_type: LogType,
) -> Result<String, ReproStatusError> {
    let url = rebuilder.join(&format!(
        "api/v0/builds/{}/{}",
        build_id,
        match log_type {
            LogType::Build => "log",
            LogType::Diffoscope => "diffoscope",
        },
    ))?;
    log::debug!("Sending request to {url}");
    Ok(client.get(url.as_str()).send().await?.text().await?)
}

#[cfg(test)]
mod tests {
    use super::*;
    use anyhow::Result;
    use pretty_assertions::assert_eq;

    /// Rebuilderd instance to use for testing.
    const REBUILDERD_URL: &str = "https://reproducible.archlinux.org";

    #[tokio::test]
    async fn test_fetch_archweb_packages() -> Result<()> {
        let client = HttpClient::new();
        assert_eq!(0, fetch_archweb_packages(&client, "xyz").await?.len());
        assert!(!fetch_archweb_packages(&client, "jelle").await?.is_empty());
        Ok(())
    }

    #[tokio::test]
    async fn test_fetch_rebuilderd_packages() -> Result<()> {
        let client = HttpClient::new();
        assert!(
            !fetch_rebuilderd_packages(&client, &Url::parse(REBUILDERD_URL)?)
                .await?
                .is_empty()
        );
        Ok(())
    }

    #[tokio::test]
    async fn test_fetch_rebuilderd_logs() -> Result<()> {
        let client = HttpClient::new();
        assert_eq!(
            "Not found\n",
            fetch_rebuilderd_logs(&client, &Url::parse(REBUILDERD_URL)?, 0, LogType::Build).await?
        );
        Ok(())
    }
}
