use std::error::Error;
use std::sync::LazyLock;
use std::time::Duration;
use reqwest::blocking::Client;
use serde::de::DeserializeOwned;
use crate::models::common::ApiResponse;
use crate::models::constructor_standings::ConstructorStandingsData;
use crate::models::driver_standings::DriverStandingsData;
use crate::models::drivers::DriverData;
use crate::models::race_results::RaceResultsData;
const BASE_URL: &str = "https://api.jolpi.ca/ergast/f1";
pub type AppResult<T> = Result<T, Box<dyn Error>>;
static CLIENT: LazyLock<Client> = LazyLock::new(|| {
Client::builder()
.timeout(Duration::from_secs(10))
.build()
.expect("failed to build reqwest client")
});
fn fetch<T: DeserializeOwned>(url: &str) -> AppResult<T> {
Ok(CLIENT.get(url).send()?.json::<T>()?)
}
pub fn fetch_driver_standings(season: &str) -> AppResult<ApiResponse<DriverStandingsData>> {
fetch(&format!("{BASE_URL}/{season}/driverstandings/"))
}
pub fn fetch_constructor_standings(
season: &str,
) -> AppResult<ApiResponse<ConstructorStandingsData>> {
fetch(&format!("{BASE_URL}/{season}/constructorstandings/"))
}
pub fn fetch_race_results(season: &str, round: &str) -> AppResult<ApiResponse<RaceResultsData>> {
fetch(&format!("{BASE_URL}/{season}/{round}/results/"))
}
pub fn fetch_driver_results(season: &str, driver: &str) -> AppResult<ApiResponse<RaceResultsData>> {
fetch(&format!("{BASE_URL}/{season}/drivers/{driver}/results/"))
}
pub fn fetch_drivers(season: &str) -> AppResult<ApiResponse<DriverData>> {
fetch(&format!("{BASE_URL}/{season}/drivers/"))
}