// {{ 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 ApiKeyStrategy;

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

        let mut credentials = Credentials::new();
        credentials.insert("api_key".to_string(), api_key.clone());
        Ok(credentials)
    }

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

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

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

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

    #[test]
    fn rejects_an_empty_api_key_as_invalid() {
        let strategy = ApiKeyStrategy;
        let credentials = Credentials::from([("api_key".to_string(), String::new())]);
        assert!(!strategy.validate_credentials(&credentials));
    }
}
