// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

use async_trait::async_trait;

use super::super::auth_strategy::{AuthConfig, AuthStrategy, Credentials};
use super::super::errors::AuthError;

#[derive(Debug, Default)]
pub struct PatAuthStrategy;

#[async_trait]
impl AuthStrategy for PatAuthStrategy {
    async fn authenticate(&self, config: &AuthConfig) -> anyhow::Result<Credentials> {
        let token = config
            .get("token")
            .ok_or_else(|| AuthError::MissingCredentials("token".to_string()))?;

        let mut credentials = Credentials::new();
        credentials.insert("token".to_string(), token.clone());
        credentials.insert(
            "authorization_header".to_string(),
            format!("Bearer {token}"),
        );
        Ok(credentials)
    }

    fn validate_credentials(&self, credentials: &Credentials) -> bool {
        credentials
            .get("token")
            .is_some_and(|token| !token.is_empty())
    }
}

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

    #[tokio::test]
    async fn wraps_the_token_in_a_bearer_authorization_header() {
        let strategy = PatAuthStrategy;
        let config = AuthConfig::from([("token".to_string(), "abc123".to_string())]);
        let credentials = strategy.authenticate(&config).await.unwrap();
        assert_eq!(
            credentials.get("authorization_header").unwrap(),
            "Bearer abc123"
        );
    }

    #[tokio::test]
    async fn rejects_a_config_missing_the_token() {
        let strategy = PatAuthStrategy;
        assert!(strategy.authenticate(&AuthConfig::new()).await.is_err());
    }
}
