use crate::{models::Endereco, error::CepError, validacao::normalizar_cep};
use reqwest::{Client, StatusCode}; use serde::Deserialize;
use std::time::Duration;
use serde_json::Value;
#[derive(Debug, Deserialize)]
struct ViaCepResponse {
cep: String,
logradouro: String,
complemento: String,
bairro: String,
localidade: String,
uf: String,
ibge: Option<String>,
gia: Option<String>,
ddd: Option<String>,
siafi: Option<String>,
#[serde(default)]
erro: bool,
}
pub async fn consultar(cep: &str) -> Result<Endereco, CepError> {
let cep_normalizado = normalizar_cep(cep)?;
let url = format!("https://viacep.com.br/ws/{}/json/", cep_normalizado);
let response = Client::new()
.get(&url)
.timeout(Duration::from_secs(2))
.send()
.await?;
match response.status() {
StatusCode::OK => {
let viacep_response: ViaCepResponse = response.json().await?;
if viacep_response.erro {
return Err(CepError::CepNaoEncontrado);
}
Ok(Endereco {
cep: viacep_response.cep,
logradouro: Some(viacep_response.logradouro)
.filter(|s| !s.is_empty()),
complemento: Some(viacep_response.complemento)
.filter(|s| !s.is_empty()),
bairro: Some(viacep_response.bairro)
.filter(|s| !s.is_empty()),
localidade: viacep_response.localidade,
uf: viacep_response.uf,
ibge: viacep_response.ibge,
gia: viacep_response.gia,
ddd: viacep_response.ddd,
siafi: viacep_response.siafi,
})
},
StatusCode::BAD_REQUEST => Err(CepError::CepInvalido),
StatusCode::TOO_MANY_REQUESTS => Err(CepError::RateLimitExcedido("ViaCEP".into())),
_ => Err(CepError::ProvedorIndisponivel("ViaCEP".into())),
}
}