//! Aspirational RUIN app API for composition, typed context providers, and app-wide services.
//!
//! Intentionally non-compiling; this is a design sketch.

use ruin::prelude::*;

#[ruin_runtime::async_main]
async fn main() -> ruin::Result<()> {
    App::new()
        .window(Window::new().title("RUIN Workspace").size(1400.0, 900.0))
        .mount::<WorkspaceRoot>()
        .run()
        .await
}

#[component]
fn WorkspaceRoot() -> impl View {
    let route = use_router(Route::Home);
    let session = use_resource(|| async { Session::restore().await });
    let notifications = use_service::<Notifications>();

    view! {
        provide::<NotificationsContext>(notifications.clone()) {
            provide::<ThemeContext>(Theme::dark()) {
                match session.read() {
                    Pending => view! { ProgressSpinner(label = "Restoring session...") {} },
                    Ready(session) => view! {
                        provide::<SessionContext>(session?) {
                            WorkspaceShell(route = route) {}
                        }
                    },
                }
            }
        }
    }
}

#[component]
fn WorkspaceShell(route: Signal<Route>) -> impl View {
    let session = use_context::<SessionContext>();
    let notifications = use_context::<NotificationsContext>();

    use_effect(move || {
        if !session.is_authenticated() {
            notifications.info("Signed in as guest");
        }
    });

    view! {
        row(fill = true) {
            block(
                role = LandmarkRole::Navigation,
                width = 280,
                gap = 12,
                padding = 20,
            ) {
                BrandMark() {}
                NavLink(route = Route::Home, active = route.is(Route::Home)) { "Home" }
                NavLink(route = Route::Projects, active = route.is(Route::Projects)) { "Projects" }
                NavLink(route = Route::Settings, active = route.is(Route::Settings)) { "Settings" }
            }

            block(fill = true, padding = 20) {
                match route.get() {
                    Route::Home => view! { HomeScreen() {} },
                    Route::Projects => view! { ProjectsScreen() {} },
                    Route::Settings => view! { SettingsScreen() {} },
                }
            }
        }
    }
}

#[component]
fn HomeScreen() -> impl View {
    let theme = use_context::<ThemeContext>();

    view! {
        column(fill = true, gap = 16) {
            text(role = TextRole::Heading(1), size = 30, weight = FontWeight::Semibold) {
                "Workspace"
            }
            text(color = theme.muted_text()) {
                "Context should be keyed by provider identity, not only by value type. That allows \
                 multiple providers for the same `T` to coexist in the tree while descendants borrow \
                 the correct value by asking for a specific provider marker."
            }
        }
    }
}

#[component]
fn ProjectsScreen() -> impl View {
    view! {
        EmptyState(title = "Projects go here") {
            "This screen exists only to show route switching and app-level composition."
        }
    }
}

#[component]
fn SettingsScreen() -> impl View {
    view! {
        column(gap = 12) {
            text(role = TextRole::Heading(2), size = 24, weight = FontWeight::Semibold) {
                "Settings"
            }
            toggle(label = "Use reduced motion", value = Preferences::reduced_motion()) {}
            toggle(label = "Use system theme", value = Preferences::system_theme()) {}
        }
    }
}

#[context_provider(Theme)]
struct ThemeContext;

#[context_provider(Session)]
struct SessionContext;

#[context_provider(Notifications)]
struct NotificationsContext;

struct Session;
struct Notifications;
struct Theme;
struct Preferences;

#[derive(Clone, Copy)]
enum Route {
    Home,
    Projects,
    Settings,
}

impl Session {
    async fn restore() -> ruin::Result<Self> {
        Ok(Self)
    }

    fn is_authenticated(&self) -> bool {
        false
    }
}

impl Notifications {
    fn info(&self, _message: &str) {}
}

impl Theme {
    fn dark() -> Self {
        Self
    }

    fn muted_text(&self) -> Color {
        Color::rgb(0x94, 0xA3, 0xB8)
    }
}

impl Preferences {
    fn reduced_motion() -> bool {
        false
    }

    fn system_theme() -> bool {
        true
    }
}
