/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/
pub mod account;
pub mod admin;
pub mod error;
pub mod filter_sort;
pub mod format;
pub mod home;
pub mod items;
pub mod locale;
pub mod node_card;
pub mod node_page;
pub mod props;
pub mod scaffold;
pub mod search;
pub mod stats;

use jellycommon::user::Theme;
use markup::DynRender;
use scaffold::{RenderInfo, Scaffold};
use serde::{Deserialize, Serialize};
use std::{
    path::PathBuf,
    sync::{LazyLock, Mutex},
};

pub type FlashM = Option<(String, String)>;

#[rustfmt::skip]
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct Config {
    brand: String,
    slogan: String,
    asset_path: PathBuf,
}

static CONF: LazyLock<Config> = LazyLock::new(|| {
    CONF_PRELOAD
        .lock()
        .unwrap()
        .take()
        .expect("cache config not preloaded. logic error")
});
pub static CONF_PRELOAD: Mutex<Option<Config>> = Mutex::new(None);

pub fn get_brand() -> String {
    CONF.brand.clone()
}
pub fn get_slogan() -> String {
    CONF.slogan.clone()
}

/// render as supertrait would be possible but is not
/// dyn compatible and I really dont want to expose generics
/// that generate rendering code because of compile speed.
pub trait Page {
    fn title(&self) -> String;
    fn to_render(&self) -> DynRender<'_>;
    fn class(&self) -> Option<&'static str> {
        None
    }
}

pub fn render_page(page: &dyn Page, renderinfo: RenderInfo) -> String {
    Scaffold {
        lang: renderinfo.lang,
        class: &format!(
            "{} theme-{}",
            page.class().unwrap_or("custom-page"),
            renderinfo
                .session
                .as_ref()
                .map(|s| s.user.theme)
                .unwrap_or(Theme::Dark)
                .to_str()
        ),
        renderinfo,
        title: page.title(),
        main: page.to_render(),
    }
    .to_string()
}

pub struct CustomPage {
    pub title: String,
    pub body: String,
}
impl Page for CustomPage {
    fn title(&self) -> String {
        self.title.clone()
    }
    fn to_render(&self) -> DynRender<'_> {
        markup::new!(@markup::raw(&self.body))
    }
}
