use crate::{models::Endereco, error::CepError, validacao::normalizar_cep};
use reqwest::{Client, StatusCode};
use serde::Deserialize;
use std::time::Duration;
#[derive(Debug, Deserialize)]
struct BrasilApiResponse {
cep: String,
street: String,
neighborhood: String,
city: String,
state: String,
#[serde(rename = "service")]
service_name: String,
}
pub async fn consultar(cep: &str) -> Result<Endereco, CepError> {
let cep_normalizado = normalizar_cep(cep)?;
let url = format!("https://brasilapi.com.br/api/cep/v1/{}", cep_normalizado);
let response = Client::new()
.get(&url)
.timeout(Duration::from_secs(2))
.send()
.await
.map_err(|e| CepError::FalhaRequisicao(e.to_string()))?;
match response.status() {
StatusCode::OK => {
let brasilapi_response: BrasilApiResponse = response.json()
.await
.map_err(|e| CepError::ParseError(e.to_string()))?;
Ok(Endereco {
cep: brasilapi_response.cep,
logradouro: Some(brasilapi_response.street),
complemento: None,
bairro: Some(brasilapi_response.neighborhood),
localidade: brasilapi_response.city,
uf: brasilapi_response.state,
ibge: None,
gia: None,
ddd: None,
siafi: None,
})
},
StatusCode::NOT_FOUND => Err(CepError::CepNaoEncontrado),
StatusCode::TOO_MANY_REQUESTS => Err(CepError::RateLimitExcedido("BrasilAPI".into())),
_ => Err(CepError::ProvedorIndisponivel("BrasilAPI".into())),
}
}