pub mod app;
mod components;

#[cfg(feature = "hydrate")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub fn hydrate() {
    use crate::app::*;
    console_error_panic_hook::set_once();
    leptos::mount::hydrate_body(App);
}

#[cfg(feature = "ssr")]
pub use appstate::{AppState, Config};

#[cfg(feature = "ssr")]
mod appstate {
    use axum::extract::FromRef;
    use figment::{providers::Format, Figment};
    use leptos::config::LeptosOptions;
    use reqwest::Client;
    use serde::Deserialize;
    use std::path::PathBuf;
    use url::Url;

    #[derive(Deserialize, Debug, Clone)]
    pub struct Config {
        pub credentials_directory: PathBuf,
        pub ntfy_instance: Url,
    }

    impl Config {
        pub fn parse() -> Self {
            let config_path = std::env::var_os("TLATERNET_CONFIG")
                .map(PathBuf::from)
                .or_else(|| {
                    std::env::current_dir()
                        .map(|dir| dir.join("config.toml"))
                        .ok()
                });

            let config: Result<Config, figment::Error> = if let Some(config_path) = config_path {
                Figment::new().merge(figment::providers::Toml::file(config_path))
            } else {
                Figment::new()
            }
            .merge(figment::providers::Env::raw().only(&["CREDENTIALS_DIRECTORY"]))
            .merge(figment::providers::Env::prefixed("TLATERNET_"))
            .extract();

            match config {
                Ok(config) => {
                    if !config.credentials_directory.join("ntfy-topic").exists() {
                        leptos::logging::error!("Failed to find ntfy-topic credential");
                        std::process::exit(1);
                    }

                    config
                }
                Err(error) => {
                    leptos::logging::error!("Failed to parse configuration: {:?}", error);
                    std::process::exit(1);
                }
            }
        }
    }

    #[derive(FromRef, Debug, Clone)]
    pub struct AppState {
        pub config: Config,
        pub http_client: Client,
        pub leptos_options: LeptosOptions,
    }
}
