use cfg_if::cfg_if;
pub mod data;
pub mod company;
pub mod user;
pub mod auth_middleware;
pub mod opening_hours;
pub mod property;
pub mod reservation;
pub mod customer;
pub mod mail;
pub mod appearance;

#[macro_export]
macro_rules! perm_check {
    ($check:ident) => {
        use crate::backend::user::$check;
        use crate::backend::user::logged_in_user;
        use actix_web::http::StatusCode;
        use leptos_actix::ResponseOptions;
        use log::warn;

        if !$check().await {
            let response = expect_context::<ResponseOptions>();
            response.set_status(StatusCode::FORBIDDEN);

            warn!("Permission denied for user: {}", logged_in_user().await.unwrap_or_default().login);

            return Ok(ApiResponse::Error("Forbidden".to_string()))
        }
    }
}

#[macro_export]
macro_rules! user_check {
    ($check:expr) => {
        use crate::perm_check;

        perm_check!(is_logged_in);
        let user = logged_in_user().await.unwrap_or(User::default());

        if !user.admin && user.login != $check {
            let response = expect_context::<ResponseOptions>();
            response.set_status(StatusCode::FORBIDDEN);

            warn!("Try to update not owned data. User: {}", user.login);

            return Ok(ApiResponse::Error("You can change your own profile only".to_string()))
        }
    }
}

cfg_if!{
    if #[cfg(feature = "ssr")] {
        use sqlx::PgPool;
        use actix_web::web::Data;
        use leptos_actix::extract;
        use leptos::ServerFnError;
        use crate::config::Mailing;

        #[derive(Clone)]
        pub struct AppData {
            db_pool: PgPool,
            mailer: Mailing
        }

        impl AppData {
            pub fn new(db_pool: PgPool, mailer: Mailing) -> Self {
                Self {
                    db_pool,
                    mailer
                }
            }

            pub fn db_pool(&self) -> &PgPool {
                &self.db_pool
            }

            pub fn mailer(&self) -> &Mailing {
                &self.mailer
            }
        }

        pub async fn get_pool() -> Result<PgPool, ServerFnError> {
            let data = extract::<Data<AppData>>().await?;
            Ok(data.db_pool().clone())
        }

        pub async fn get_mailing() -> Result<Mailing, ServerFnError> {
            let data = extract::<Data<AppData>>().await?;
            Ok(data.mailer().clone())
        }
    }
}