#[cfg(test)]
mod tests;

#[cfg(all(feature = "serialize", feature = "variations"))]
pub(crate) mod ser_str;

pub(crate) mod string_u64 {
	use serde::Deserialize;
	#[cfg(feature = "serialize")]
	use serde::{Serialize, Serializer};

	#[cfg(feature = "serialize")]
	pub(crate) fn serialize<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		value.to_string().serialize(serializer)
	}
	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
	where
		D: serde::Deserializer<'de>,
	{
		let value = String::deserialize(deserializer)?;
		value.parse().map_err(|_| {
			serde::de::Error::invalid_type(serde::de::Unexpected::Str(&value), &"a u64")
		})
	}
}

macro_rules! construct_url {
	($base:expr, $params:expr) => {{
		let mut url = $base.to_string();
		if let Some(params) = $params {
			let params_str = serde_qs::to_string(params).expect("Expected valid params");
			url.reserve_exact(params_str.len() + 1);
			url.push('?');
			url.push_str(&params_str);
		}
		url
	}};
}
pub(crate) use construct_url;

macro_rules! make_request {
	($base:literal [ $($var:expr),* ] $($params:expr)?) => {{
		let url = format!($base, $($var),*);
		$(let url = $crate::helpers::construct_url!(url, $params);)?
		$crate::Result::from(
			reqwest::get(&url)
				.await?
				.json::<$crate::types::DeResult<_>>()
				.await?
		)
	}};
}
pub(crate) use make_request;

#[cfg(feature = "blocking")]
macro_rules! make_request_blocking {
	($base:literal [ $($var:expr),* ] $($params:expr)?) => {{
		let url = format!($base, $($var),*);
		$(let url = $crate::helpers::construct_url!(url, $params);)?
		$crate::Result::from(
			reqwest::blocking::get(&url)?
				.json::<$crate::types::DeResult<_>>()?
		)
	}};
}
#[cfg(feature = "blocking")]
pub(crate) use make_request_blocking;
