use super::client_adapters::OpencodeAdapter;
use axum::http::HeaderMap;
use once_cell::sync::Lazy;
use std::sync::Arc;
pub trait ClientAdapter: Send + Sync {
    fn matches(&self, headers: &HeaderMap) -> bool;
    fn let_it_crash(&self) -> bool {
        false
    }
    fn signature_buffer_strategy(&self) -> SignatureBufferStrategy {
        SignatureBufferStrategy::Default
    }
    fn inject_beta_headers(&self, _headers: &mut HeaderMap) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignatureBufferStrategy {
    Default,
    Fifo,
}
pub static CLIENT_ADAPTERS: Lazy<Vec<Arc<dyn ClientAdapter>>> =
    Lazy::new(|| vec![Arc::new(OpencodeAdapter)]);
pub fn get_user_agent(headers: &HeaderMap) -> Option<String> {
    headers
        .get("user-agent")
        .and_then(|v| v.to_str().ok())
        .map(|s| s.to_string())
}

#[cfg(test)]
mod tests {
    use super::*;
    use axum::http::HeaderValue;

    struct TestAdapter;

    impl ClientAdapter for TestAdapter {
        fn matches(&self, headers: &HeaderMap) -> bool {
            get_user_agent(headers)
                .map(|ua| ua.contains("test-client"))
                .unwrap_or(false)
        }
    }

    #[test]
    fn test_adapter_matches() {
        let adapter = TestAdapter;

        let mut headers = HeaderMap::new();
        headers.insert("user-agent", HeaderValue::from_static("test-client/1.0"));

        assert!(adapter.matches(&headers));
    }

    #[test]
    fn test_adapter_no_match() {
        let adapter = TestAdapter;

        let mut headers = HeaderMap::new();
        headers.insert("user-agent", HeaderValue::from_static("other-client/1.0"));

        assert!(!adapter.matches(&headers));
    }

    #[test]
    fn test_get_user_agent() {
        let mut headers = HeaderMap::new();
        headers.insert("user-agent", HeaderValue::from_static("opencode/1.0"));

        assert_eq!(get_user_agent(&headers), Some("opencode/1.0".to_string()));
    }
}