use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::ontology::{Residue, SurfaceKey};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RouteMatch {
pub platform: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub guild_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chat_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct Route {
#[serde(default)]
pub name: Option<String>,
#[serde(rename = "match")]
pub matches: RouteMatch,
pub profile: String,
#[serde(default)]
pub residue: Residue,
}
pub fn route_specificity(route: &Route) -> u8 {
let m = &route.matches;
(if m.thread_id.is_some() { 8 } else { 0 })
+ (if m.chat_id.is_some() { 4 } else { 0 })
+ (if m.guild_id.is_some() { 2 } else { 0 })
+ 1
}
pub fn resolve_route<'a>(
routes: &'a [Route],
key: &SurfaceKey,
guild_id: Option<&str>,
) -> Option<&'a str> {
let mut best: Option<&Route> = None;
for route in routes {
let m = &route.matches;
if Some(m.platform.as_str()) != key.platform.as_deref() {
continue;
}
if m.guild_id.is_some() && m.guild_id.as_deref() != guild_id {
continue;
}
if m.chat_id.is_some() && m.chat_id != key.chat_id {
continue;
}
if m.thread_id.is_some() && m.thread_id != key.thread_id {
continue;
}
if best.is_none_or(|b| route_specificity(route) > route_specificity(b)) {
best = Some(route);
}
}
best.map(|r| r.profile.as_str())
}