// SPDX-License-Identifier: Apache-2.0
//! Root `<App>` component: providers, router, route tree.
//! Also exposes the SSR `shell()` function used by the axum server.

use leptos::prelude::*;
use leptos_meta::{Meta, Title, provide_meta_context};
use leptos_router::components::{Route, Router, Routes};
use leptos_router::path;

use crate::components::app_shell::AppShell;
use crate::components::toast::ToastStack;
use crate::pages::{
    // Album and photo pages
    album_detail::AlbumDetailPage,
    create_album::CreateAlbumPage,
    create_share_link::CreateShareLinkPage,
    // v2 primary nav pages
    library::LibraryPage,
    me::MePage,
    photo_viewer::PhotoViewerPage,
    share_center::ShareCenterPage,
    // Public pages
    shared_entry::SharedAlbumEntryPage,
    shared_inbox::SharedInboxPage,
    shared_viewer::SharedAlbumViewerPage,
    sharing::SharingPage,
    // Upload flow
    upload_complete::UploadCompletePage,
    upload_privacy::UploadPrivacyPage,
    upload_processing::UploadProcessingPage,
    upload_start::UploadStartPage,
};
use crate::state::AppState;

// ── SSR HTML shell ───────────────────────────────────────────────────────────
//
// `cargo-leptos` calls this on every request to produce the outer HTML
// document. `<App/>` is rendered server-side inside the `<body>`.
// `<HydrationScripts>` injects the Wasm bundle and bootstraps hydration.
// `<MetaTags>` flushes any `<Title>`/`<Meta>` set by child components.

#[cfg(feature = "ssr")]
pub fn shell(options: leptos::config::LeptosOptions) -> impl IntoView {
    use leptos::hydration::HydrationScripts;
    use leptos_meta::{HashedStylesheet, MetaTags};

    view! {
        <!DOCTYPE html>
        <html lang="en" dir="ltr">
          <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
            <meta name="theme-color" content="#FAF7F2" />
            <meta name="color-scheme" content="light" />

            // Inject the compiled CSS bundle (from styles/main.css via cargo-leptos).
            <HashedStylesheet options=options.clone() id="leptos" />

            // Google Fonts — display (Fraunces) + body (IBM Plex Sans/Mono)
            <link rel="preconnect" href="https://fonts.googleapis.com" />
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
            <link
              href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght,SOFT,WONK@9..144,300;9..144,400;9..144,500;9..144,600;9..144,700;9..144,300,30,0;9..144,500,30,1&family=IBM+Plex+Sans:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap"
              rel="stylesheet"
            />

            // Meta tags set by child components via `leptos_meta`.
            <MetaTags />

            // Injects the Wasm hydration scripts produced by cargo-leptos.
            <HydrationScripts options />
          </head>
          <body>
            <noscript>
              "hejpics needs JavaScript to run. Your photos remain private regardless."
            </noscript>
            <App />
          </body>
        </html>
    }
}

// ── Root component ───────────────────────────────────────────────────────────

/// Root Leptos component.
#[component]
pub fn App() -> impl IntoView {
    provide_meta_context();
    AppState::provide();

    view! {
        <Title text="hejpics — your photos, kept quietly" />
        <Meta name="description" content="A private photo library. Share with the people who matter, not the world." />

        <Router>
            <Routes fallback=NotFound>
                // ── Public routes (no auth, minimal shell) ───────────────────
                <Route path=path!("/share/:token") view=SharedAlbumEntryPage />
                <Route path=path!("/share/:token/view") view=SharedAlbumViewerPage />

                // ── Authenticated app routes ──────────────────────────────────
                // Primary nav (RFC 004)
                <Route path=path!("/") view=move || view! { <AppShell><LibraryPage /></AppShell> } />
                <Route path=path!("/shared") view=move || view! { <AppShell><SharedInboxPage /></AppShell> } />
                <Route path=path!("/sharing") view=move || view! { <AppShell><SharingPage /></AppShell> } />
                <Route path=path!("/me") view=move || view! { <AppShell><MePage /></AppShell> } />

                // Album and photo routes
                <Route path=path!("/albums/new") view=move || view! { <AppShell><CreateAlbumPage /></AppShell> } />
                <Route path=path!("/albums/:album_id") view=move || view! { <AppShell><AlbumDetailPage /></AppShell> } />
                <Route path=path!("/albums/:album_id/share") view=move || view! { <AppShell><ShareCenterPage /></AppShell> } />
                <Route path=path!("/albums/:album_id/share/new") view=move || view! { <AppShell><CreateShareLinkPage /></AppShell> } />
                <Route path=path!("/photos/:photo_id") view=PhotoViewerPage />

                // Upload flow
                <Route path=path!("/upload") view=move || view! { <AppShell><UploadStartPage /></AppShell> } />
                <Route path=path!("/upload/privacy") view=move || view! { <AppShell><UploadPrivacyPage /></AppShell> } />
                <Route path=path!("/upload/processing") view=move || view! { <AppShell><UploadProcessingPage /></AppShell> } />
                <Route path=path!("/upload/complete") view=move || view! { <AppShell><UploadCompletePage /></AppShell> } />

                // Legacy redirects — v1 paths forwarded to v2 destinations
                <Route path=path!("/albums") view=move || view! { <AppShell><LibraryPage /></AppShell> } />
                <Route path=path!("/settings") view=move || view! { <AppShell><MePage /></AppShell> } />
                <Route path=path!("/data") view=move || view! { <AppShell><MePage /></AppShell> } />
            </Routes>
        </Router>

        <ToastStack />
    }
}

#[component]
fn NotFound() -> impl IntoView {
    view! {
        <AppShell>
            <div class="main-region">
                <div class="empty">
                    <div class="empty__title">"This page is not here."</div>
                    <div class="empty__body">
                        "The link may have been moved, removed, or never existed. Your photos are unaffected."
                    </div>
                    <a class="btn" href="/">"Back to home"</a>
                </div>
            </div>
        </AppShell>
    }
}
