use http::{
    self,
    method::Method,
    uri::{PathAndQuery, Uri},
};

static PRODUCTION_HOST: &'static str = "api.billecta.com";
static TEST_HOST: &'static str = "apitest.billecta.com";

enum Target {
    Production,
    Test,
    Custom(String),
}

impl Target {
    fn url(&self) -> &str {
        match self {
            Self::Production => PRODUCTION_HOST,
            Self::Test => TEST_HOST,
            Self::Custom(inner) => inner,
        }
    }
}

pub struct Client {
    auth_token: String,
    target: Target,
    pub(crate) client: eiktyrner::HttpsClient,
}

impl Client {
    pub fn new(token: impl AsRef<str>) -> Self {
        Self {
            client: eiktyrner::HttpsClient::new(),
            auth_token: format!("SecureToken {}", token.as_ref()),
            target: Target::Production,
        }
    }

    pub fn new_test(token: impl AsRef<str>) -> Self {
        Self {
            client: eiktyrner::HttpsClient::new(),
            auth_token: format!("SecureToken {}", token.as_ref()),
            target: Target::Test,
        }
    }

    pub fn new_with_url(token: impl AsRef<str>, url: impl AsRef<str>) -> Self {
        Self {
            client: eiktyrner::HttpsClient::new(),
            auth_token: format!("SecureToken {}", token.as_ref()),
            target: Target::Custom(url.as_ref().into()),
        }
    }

    pub(crate) fn new_request(
        &self,
        method: Method,
        path_and_query: PathAndQuery,
    ) -> http::request::Builder {
        let uri = match &self.target {
            Target::Custom(_) => {
                if self.target.url().starts_with("https://") {
                    Uri::builder()
                        .scheme("https")
                        .authority(self.target.url().replace("https://", "").as_str())
                        .path_and_query(path_and_query)
                        .build()
                        .expect("Building base url")
                } else {
                    Uri::builder()
                        .scheme("http")
                        .authority(self.target.url().replace("http://", "").as_str())
                        .path_and_query(path_and_query)
                        .build()
                        .expect("Building base url")
                }
            }
            _ => Uri::builder()
                .scheme("https")
                .authority(self.target.url())
                .path_and_query(path_and_query)
                .build()
                .expect("Building base url"),
        };

        http::Request::builder()
            .method(method)
            .header("Authorization", &self.auth_token)
            .uri(uri)
    }
}