mod components;
mod pages;

use leptos::*;
use leptos_meta::*;
use leptos_router::*;
use pages::{
    auth::{
        forgot::ForgotPage, login::LoginPage, logout::LogoutPage, register::RegisterPage,
        reset::ResetPage,
    },
    dashboard::DashboardPage,
    error::{AppError, ErrorTemplate},
    oauth2::authorize::AuthorizePage,
};

use crate::domain::api::prelude::User;

#[component]
pub fn App() -> impl IntoView {
    provide_meta_context();

    let trigger_update = create_rw_signal(false);
    let trigger_direct = create_rw_signal(None::<String>);

    let user_signal = create_rw_signal(None::<User>);

    let user_resource = create_local_resource(trigger_update, move |_| async move {
        let user = super::check_user().await.unwrap();
        user_signal.set(user);
    });

    view! {
        // https://fontawesome.com/v5/search
        <Stylesheet id="font-awesome" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"/>
        <Stylesheet id="avam" href="/pkg/avam.css"/>

        <Meta name="viewport" content="width=device-width, initial-scale=1"/>

        <Link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
        <Link rel="icon" type_="image/png" sizes="32x32" href="/favicon-32x32.png"/>
        <Link rel="icon" type_="image/png" sizes="16x16" href="/favicon-16x16.png"/>
        <Link rel="manifest" href="/site.webmanifest"/>

        <Title text={ crate::PROJECT_NAME }/>

        <Router fallback=|| {
            let mut outside_errors = Errors::default();
            outside_errors.insert_with_default_key(AppError::NotFound);
            view! {
                <ErrorTemplate outside_errors/>
            }
            .into_view()
        }>
            <main class="h-screen overflow-auto dark:base-100 dark:text-white">
                <Routes>
                    <Route path="auth" view=move || {
                        view! {
                            <Suspense>
                                <Show when=move || user_resource().is_some_and(|_|user_signal().is_some())>
                                    <Redirect path={ trigger_direct().unwrap_or(String::from("/")) } />
                                </Show>
                            </Suspense>
                            <Outlet />
                        }
                    }>
                        <Route path="login" view=move || view! { <LoginPage trigger_signal=trigger_update direct_signal=trigger_direct /> } />
                        <Route path="register" view=RegisterPage />
                        <Route path="forgot" view=ForgotPage />
                        <Route path="reset/:token" view=ResetPage />
                    </Route> // auth

                    <Route path="" view=move || {
                        view! {
                            <Suspense>
                                <Show when=move || user_resource().is_some_and(|_|user_signal().is_none())>
                                    <Redirect path={
                                        use base64::prelude::*;
                                        format!("/auth/login?c={}", BASE64_URL_SAFE_NO_PAD.encode(format!("{}{}", (leptos_router::use_location().pathname)(), (leptos_router::use_location().query)().to_query_string())))
                                    } />
                                </Show>
                            </Suspense>
                            <Outlet />
                        }
                    }>
                        <Route path="" view=move || view! {
                            <Suspense>
                                <Show when=move || user_signal().is_some()>
                                    <DashboardPage user={ user_signal().unwrap() } />
                                </Show>
                            </Suspense>
                        } />

                        <Route path="oauth2/authorize" view=move || view! {
                            <Suspense>
                                <Show when=move || user_signal().is_some()>
                                    <AuthorizePage user={ user_signal } />
                                </Show>
                            </Suspense>
                        } />

                    </Route> // Logged in
                    <Route path="auth/logout" view=move || view! { <LogoutPage trigger_signal=trigger_update user_signal /> } />
                </Routes>
            </main>
        </Router>
    }
}
