use axum::{extract::multipart::MultipartError, http::StatusCode, response::IntoResponse};
use thiserror::Error;
use tower_cookies::{Cookie, Cookies};
use tracing::trace;

use crate::{constants::SESSION_COOKIE, database::db::DbError};

#[derive(Debug, Error)]
pub enum CmsError {
    #[error(transparent)]
    Db(#[from] DbError),
    #[error(transparent)]
    Password(#[from] argon2::password_hash::Error),
    #[error(transparent)]
    TokioJoin(#[from] tokio::task::JoinError),
    #[error("Problem with sending Email")]
    Brevo(#[from] brevo_mail::error::BrevoError),
    #[error("Internal Parsing Error")]
    UuidParsing(#[from] uuid::Error),
    #[error("No Session Cookie Present")]
    SessionCookieNotSet,
    #[error("Session Cookie not valid")]
    SessionCookieNotValid(Cookies),
    #[error("Unable to create file or folder")]
    IoError(#[from] std::io::Error),
    #[error("Error while handling uploaded data")]
    Multipart(#[from] MultipartError),
    #[error("Error while applying image options. {0}")]
    Image(String),
    #[error("Error with Image Crate")]
    ImageCrate(#[from] image::ImageError),
}

impl IntoResponse for CmsError {
    fn into_response(self) -> axum::response::Response {
        trace!("There was an error: {:?}", self);
        match self {
            Self::SessionCookieNotValid(cookies) => {
                cookies.remove(Cookie::new(SESSION_COOKIE, ""));
                (StatusCode::INTERNAL_SERVER_ERROR).into_response()
            }
            _ => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response(),
        }
        // TODO: create good error messages
    }
}
