import pytest
from cryptography.fernet import Fernet


class TestKeyEncryptionBasic:
    """基础加密解密测试"""

    def test_encrypt_decrypt_roundtrip(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        plaintext = "sk-1234567890abcdef"
        ciphertext = encryption.encrypt(plaintext)
        decrypted = encryption.decrypt(ciphertext)
        assert decrypted == plaintext

    def test_encrypted_content_differs_from_plaintext(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        plaintext = "sk-1234567890abcdef"
        ciphertext = encryption.encrypt(plaintext)
        assert ciphertext != plaintext
        assert ciphertext != plaintext.encode()

    def test_same_plaintext_produces_different_ciphertext(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        plaintext = "sk-1234567890abcdef"
        ciphertext1 = encryption.encrypt(plaintext)
        ciphertext2 = encryption.encrypt(plaintext)
        assert ciphertext1 != ciphertext2


class TestKeyEncryptionEdgeCases:
    """边界情况测试"""

    def test_encrypt_empty_string_raises_error(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        with pytest.raises(ValueError, match="Cannot encrypt empty string"):
            encryption.encrypt("")

    def test_decrypt_empty_string_raises_error(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        with pytest.raises(ValueError, match="Cannot decrypt empty string"):
            encryption.decrypt("")

    def test_encrypt_special_characters(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        plaintext = "sk-中文测试!@#$%^&*()_+-=[]{}|;':\",./<>?"
        ciphertext = encryption.encrypt(plaintext)
        decrypted = encryption.decrypt(ciphertext)
        assert decrypted == plaintext

    def test_encrypt_unicode_characters(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        plaintext = "sk-日本語テスト한국어"
        ciphertext = encryption.encrypt(plaintext)
        decrypted = encryption.decrypt(ciphertext)
        assert decrypted == plaintext


class TestKeyEncryptionInvalidInputs:
    """无效输入测试"""

    def test_decrypt_invalid_ciphertext_raises_error(self):
        from app.services.key_encryption import KeyEncryption

        encryption = KeyEncryption(encryption_key="test-key-for-encryption-12345")
        with pytest.raises(ValueError, match="Invalid ciphertext or key"):
            encryption.decrypt("invalid-ciphertext-that-cannot-be-decrypted")

    def test_decrypt_with_wrong_key_raises_error(self):
        from app.services.key_encryption import KeyEncryption

        encryption1 = KeyEncryption(encryption_key="key-one-for-encryption-1234")
        encryption2 = KeyEncryption(encryption_key="key-two-for-encryption-1234")

        plaintext = "sk-1234567890abcdef"
        ciphertext = encryption1.encrypt(plaintext)

        with pytest.raises(ValueError, match="Invalid ciphertext or key"):
            encryption2.decrypt(ciphertext)


class TestKeyEncryptionKeyFormats:
    """密钥格式测试"""

    def test_valid_fernet_key_format(self):
        from app.services.key_encryption import KeyEncryption

        valid_key = Fernet.generate_key().decode()
        encryption = KeyEncryption(encryption_key=valid_key)
        plaintext = "sk-1234567890abcdef"
        ciphertext = encryption.encrypt(plaintext)
        decrypted = encryption.decrypt(ciphertext)
        assert decrypted == plaintext

    def test_password_based_key_derivation(self):
        from app.services.key_encryption import KeyEncryption

        password = "my-secret-password-12345"
        encryption = KeyEncryption(encryption_key=password)
        plaintext = "sk-1234567890abcdef"
        ciphertext = encryption.encrypt(plaintext)
        decrypted = encryption.decrypt(ciphertext)
        assert decrypted == plaintext


class TestKeyEncryptionSingleton:
    """全局实例测试"""

    def test_get_key_encryption_returns_instance(self):
        from app.services.key_encryption import get_key_encryption

        instance = get_key_encryption()
        assert instance is not None
        assert hasattr(instance, "encrypt")
        assert hasattr(instance, "decrypt")

    def test_reset_key_encryption_clears_singleton(self):
        from app.services.key_encryption import get_key_encryption, reset_key_encryption

        instance1 = get_key_encryption()
        reset_key_encryption()
        instance2 = get_key_encryption()
        assert instance1 is not instance2


class TestAPIKeyManagerEncryption:
    """APIKeyManager集成测试"""

    def test_api_key_manager_uses_fernet_encryption(self):
        from app.services.api_key_manager import APIKeyManager

        manager = APIKeyManager()
        original_key = "sk-1234567890abcdef"
        config = manager.add_key("chatgpt", original_key)

        assert config.encrypted_key != original_key
        assert not config.encrypted_key.startswith("sk-")

        decrypted = manager.get_key("chatgpt")
        assert decrypted == original_key

    def test_encrypted_key_is_not_base64_of_plaintext(self):
        from app.services.api_key_manager import APIKeyManager
        import base64

        manager = APIKeyManager()
        original_key = "sk-1234567890abcdef"
        config = manager.add_key("chatgpt", original_key)

        plain_base64 = base64.b64encode(original_key.encode()).decode()
        assert config.encrypted_key != plain_base64
