# -*- coding: utf-8 -*-
"""Location: ./tests/unit/mcpgateway/utils/test_services_auth.py
Copyright 2026
SPDX-License-Identifier: Apache-2.0
Authors: Mihai Criveti

Unit tests for mcpgateway.utils.services_auth
Author: Mihai Criveti

Covered behaviour
-----------------
* Round-trip integrity: encode_auth ➜ decode_auth
* Graceful handling of None for encode_auth / decode_auth
* get_key raises ValueError when the encryption secret is unset
"""

# Third-Party
import pytest

# First-Party
# --------------------------------------------------------------------------- #
# Import the module under test: mcpgateway.utils.services_auth                #
# --------------------------------------------------------------------------- #
from mcpgateway.utils import services_auth  # noqa: E402  (import after docstring)

encode_auth = services_auth.encode_auth
decode_auth = services_auth.decode_auth
get_key = services_auth.get_key
settings = services_auth.settings


# --------------------------------------------------------------------------- #
# Tests                                                                       #
# --------------------------------------------------------------------------- #
def test_encode_decode_roundtrip(monkeypatch):
    """Data survives an encode ➜ decode cycle unmodified."""
    monkeypatch.setattr(settings, "auth_encryption_secret", "top-secret")

    payload = {"user": "alice", "roles": ["admin", "qa"]}
    encoded = encode_auth(payload)

    assert isinstance(encoded, str) and encoded  # non-empty string

    decoded = decode_auth(encoded)
    assert decoded == payload


def test_encode_none_returns_none(monkeypatch):
    monkeypatch.setattr(settings, "auth_encryption_secret", "x")
    assert encode_auth(None) is None


def test_decode_none_returns_empty_dict(monkeypatch):
    monkeypatch.setattr(settings, "auth_encryption_secret", "x")
    assert decode_auth(None) == {}


def test_get_key_without_secret_raises(monkeypatch):
    """get_key must raise if secret is missing or empty."""
    monkeypatch.setattr(settings, "auth_encryption_secret", "")
    with pytest.raises(ValueError):
        get_key()


def test_crypto_cache_reuse(monkeypatch):
    """Verify that AESGCM and key are cached and reused."""
    from mcpgateway.utils.services_auth import clear_crypto_cache

    clear_crypto_cache()

    monkeypatch.setattr(settings, "auth_encryption_secret", "test-secret")

    # Get key twice - should return same bytes object
    key1 = get_key()
    key2 = get_key()
    assert key1 == key2
    assert isinstance(key1, bytes)


def test_clear_crypto_cache(monkeypatch):
    """Verify that clearing crypto cache works correctly."""
    from mcpgateway.utils.services_auth import clear_crypto_cache

    monkeypatch.setattr(settings, "auth_encryption_secret", "secret1")

    # Warm cache
    get_key()
    encode_auth({"test": "data"})

    # Clear cache
    clear_crypto_cache()

    # Should still work after clearing
    monkeypatch.setattr(settings, "auth_encryption_secret", "secret2")
    key = get_key()
    assert isinstance(key, bytes)


def test_encode_decode_uses_cached_aesgcm(monkeypatch):
    """Verify that encode/decode operations use cached AESGCM."""
    from mcpgateway.utils.services_auth import clear_crypto_cache

    clear_crypto_cache()

    monkeypatch.setattr(settings, "auth_encryption_secret", "cache-test")

    # Multiple encode/decode operations
    data1 = {"user": "alice"}
    data2 = {"user": "bob"}

    token1 = encode_auth(data1)
    token2 = encode_auth(data2)

    assert decode_auth(token1) == data1
    assert decode_auth(token2) == data2


def test_get_key_accepts_secretstr(monkeypatch):
    """_get_passphrase should unwrap SecretStr values."""
    from pydantic import SecretStr
    from mcpgateway.utils.services_auth import clear_crypto_cache

    clear_crypto_cache()
    monkeypatch.setattr(settings, "auth_encryption_secret", SecretStr("secretstr-value"))
    key = get_key()
    assert isinstance(key, bytes)
