use serde::{Deserialize, Serialize};
use std::sync::OnceLock;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteInfo {
    pub method: String,
    pub path: String,
    pub handler: String,
}

static REGISTRY: OnceLock<std::sync::Mutex<Vec<RouteInfo>>> = OnceLock::new();

fn registry() -> &'static std::sync::Mutex<Vec<RouteInfo>> {
    REGISTRY.get_or_init(|| std::sync::Mutex::new(Vec::new()))
}

pub fn register(routes: Vec<RouteInfo>) {
    if let Ok(mut guard) = registry().lock() {
        guard.extend(routes);
    }
}

pub fn list() -> Vec<RouteInfo> {
    registry().lock().map(|g| g.clone()).unwrap_or_default()
}

/// Declarative route registration macro.
///
/// Usage:
/// ```ignore
/// register_routes![
///     (GET,  "/users",     "list_users"),
///     (POST, "/users",     "create_user"),
/// ];
/// ```
#[macro_export]
macro_rules! register_routes {
    [ $( ($method:ident, $path:literal, $handler:literal) ),* $(,)? ] => {
        $crate::registry::register(vec![
            $(
                $crate::registry::RouteInfo {
                    method:  stringify!($method).to_string(),
                    path:    $path.to_string(),
                    handler: $handler.to_string(),
                },
            )*
        ]);
    };
}

/// Passthrough wrapper macro — registers nothing at compile time.
/// Use `register_routes!` separately to populate the registry.
#[macro_export]
macro_rules! rok_routes {
    ($router:expr) => {
        $router
    };
}
