use super::{Alliance, AllianceIcon};
use crate::{get_public, Esi, EsiResult, Response};

impl Esi {
  /**
   * List all active player alliances
   * esi: https://esi.evetech.net/latest/alliances/
   */
  pub async fn get_alliances(&self, etag: Option<&str>) -> EsiResult<Response<Vec<i32>>> {
    let result = get_public::<Vec<i32>>("alliances/", self, None, etag).await?;
    Ok(result)
  }

  /**
   * Public information about an alliance
   * esi: https://esi.evetech.net/latest/alliances/{alliance_id}/
   */
  pub async fn get_alliance(
    &self,
    alliance_id: i32,
    etag: Option<&str>,
  ) -> EsiResult<Response<Alliance>> {
    let result =
      get_public::<Alliance>(&format!("alliances/{}", alliance_id), self, None, etag).await?;
    Ok(result)
  }

  /**
   * List all current member corporations of an alliance
   * esi: https://esi.evetech.net/latest/alliances/{alliance_id}/corporations/
   */
  pub async fn get_alliance_corporations(
    &self,
    alliance_id: i32,
    etag: Option<&str>,
  ) -> EsiResult<Response<Vec<i32>>> {
    let result = get_public::<Vec<i32>>(
      &format!("alliances/{}/corporations/", alliance_id),
      self,
      None,
      etag,
    )
    .await?;
    Ok(result)
  }

  /**
   * Get the icon urls for a alliance
   * esi: https://esi.evetech.net/latest/alliances/{alliance_id}/icons/
   */
  pub async fn get_alliance_icons(
    &self,
    alliance_id: i32,
    etag: Option<&str>,
  ) -> EsiResult<Response<AllianceIcon>> {
    let result = get_public::<AllianceIcon>(
      &format!("alliances/{}/icons/", alliance_id),
      self,
      None,
      etag,
    )
    .await?;
    Ok(result)
  }
}

#[cfg(test)]
mod tests {
  use crate::Esi;

  const OWNER_ID: &str = "1234567890";
  const CLIENT_ID: &str = "1234567890";
  const CLIENT_SECRET: &str = "1234567890";
  const CALLBACK_URL: &str = "https://example.com/callback";

  async fn get_alliance_id() -> i32 {
    let esi = Esi::new(OWNER_ID, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL, 10);
    assert!(esi.is_ok());
    let esi = esi.unwrap();
    let result = esi.get_alliances(None).await;
    assert!(result.is_ok());
    let alliances = result.unwrap().data;
    assert!(!alliances.is_empty());
    alliances[0]
  }

  #[tokio::test]
  async fn test_get_alliances() {
    let esi = Esi::new(OWNER_ID, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL, 10);
    assert!(esi.is_ok());
    let esi = esi.unwrap();
    let result = esi.get_alliances(None).await;
    assert!(result.is_ok());
    let etag = result.unwrap().headers.etag;
    let result = esi.get_alliances(Some(&etag)).await;
    assert!(result.is_err_and(|x| x.status() == 304));
  }

  #[tokio::test]
  async fn test_get_alliance() {
    let esi = Esi::new(OWNER_ID, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL, 10);
    assert!(esi.is_ok());
    let esi = esi.unwrap();
    let alliance_id = get_alliance_id().await;
    let result = esi.get_alliance(alliance_id, None).await;
    assert!(result.is_ok());
    let etag = result.unwrap().headers.etag;
    let result = esi.get_alliance(alliance_id, Some(&etag)).await;
    assert!(result.is_err_and(|x| x.status() == 304));
  }

  #[tokio::test]
  async fn test_get_alliance_corporations() {
    let esi = Esi::new(OWNER_ID, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL, 10);
    assert!(esi.is_ok());
    let esi = esi.unwrap();
    let alliance_id = get_alliance_id().await;
    let result = esi.get_alliance_corporations(alliance_id, None).await;
    assert!(result.is_ok());
    let etag = result.unwrap().headers.etag;
    let result = esi
      .get_alliance_corporations(alliance_id, Some(&etag))
      .await;
    assert!(result.is_err_and(|x| x.status() == 304));
  }

  #[tokio::test]
  async fn test_get_alliance_icons() {
    let esi = Esi::new(OWNER_ID, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL, 10);
    assert!(esi.is_ok());
    let esi = esi.unwrap();
    let alliance_id = get_alliance_id().await;
    let result = esi.get_alliance_icons(alliance_id, None).await;
    assert!(result.is_ok());
    let etag = result.unwrap().headers.etag;
    let result = esi.get_alliance_icons(alliance_id, Some(&etag)).await;
    assert!(result.is_err_and(|x| x.status() == 304));
  }
}
