// Bitbucket Data Center 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;

/// Data Center Personal Access Token auth — a bearer token passed as
/// `Authorization: Bearer <token>`. Not declared in this API's OpenAPI spec
/// (which only documents Basic auth), but accepted by the server anyway;
/// added by hand alongside the spec-derived `BasicAuthStrategy`.
#[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.contains_key("authorization_header")
    }
}

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

    fn config(token: &str) -> AuthConfig {
        AuthConfig::from([("token".to_string(), token.to_string())])
    }

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

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

    #[test]
    fn validates_credentials_carrying_an_authorization_header() {
        let strategy = PatAuthStrategy;
        let credentials =
            Credentials::from([("authorization_header".to_string(), "Bearer abc".to_string())]);
        assert!(strategy.validate_credentials(&credentials));
        assert!(!strategy.validate_credentials(&Credentials::new()));
    }
}
