use crate::repository::api::prelude::*;

#[derive(Debug)]
pub enum EmailError {
    EmailAlreadyUsed,
    EmailAlreadyConnected,
    Other(String),
}

impl std::fmt::Display for EmailError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            EmailError::EmailAlreadyUsed => write!(f, "Email is already used by another user"),
            EmailError::EmailAlreadyConnected => write!(f, "Email is already connected to this account"),
            EmailError::Other(msg) => write!(f, "{}", msg),
        }
    }
}

impl std::error::Error for EmailError {}

/// Request email confirmation for a user
pub async fn request_email_confirmation(user_id: String, email: &str) -> Result<(), EmailError> {
    let url = format!("{host}/rpc/request_email_confirmation", host=&*BACKEND_API_URL);
    log::trace!("fetching {url}", url = url.red());

    #[derive(serde::Serialize)]
    struct RequestEmailConfirmationRequest {
        email: String,
    }

    let response = reqwest::Client::new()
        .post(&url)
        .json(&RequestEmailConfirmationRequest { email: email.to_string() })
        .header("Authorization", get_auth_token().await.map_err(|e| EmailError::Other(e.to_string()))?)
        .header("Content-Type", "application/json")
        .header("X-Tg-Id", user_id)
        .send()
        .await
        .map_err(|e| EmailError::Other(e.to_string()))?;

    if !response.status().is_success() {
        return match response.status() {
            reqwest::StatusCode::CONFLICT => Err(EmailError::EmailAlreadyUsed), // 409
            reqwest::StatusCode::UNPROCESSABLE_ENTITY => Err(EmailError::EmailAlreadyConnected), // 422
            _ => {
                let error_text = response.text().await
                    .unwrap_or_else(|_| "Unknown error".to_string());
                let error_text = prettify_json_or_text(&error_text);
                log::error!("Failed to request email confirmation: {}", error_text);
                Err(EmailError::Other(error_text))
            }
        };
    }

    Ok(())
}
