import base64

import pytest

from amcs.crypto.encryption import decrypt_field, encrypt_field


def test_encrypt_decrypt_roundtrip() -> None:
    key = b"k" * 32
    aad = {
        "agent_id": "agent-1",
        "event_id": "evt-1",
        "event_type": "interaction.append",
    }
    plaintext = b"secret-memory"

    enc = encrypt_field(plaintext, key, "kid-1", aad)
    dec = decrypt_field(enc, key, aad)

    assert enc["alg"] == "AES-GCM"
    assert enc["kid"] == "kid-1"
    assert dec == plaintext


def test_decrypt_fails_on_tampering() -> None:
    key = b"k" * 32
    aad = {
        "agent_id": "agent-1",
        "event_id": "evt-1",
        "event_type": "interaction.append",
    }
    enc = encrypt_field(b"secret-memory", key, "kid-1", aad)

    raw = bytearray(base64.b64decode(enc["ciphertext_b64"]))
    raw[-1] ^= 0x01
    tampered = dict(enc)
    tampered["ciphertext_b64"] = base64.b64encode(bytes(raw)).decode("ascii")

    with pytest.raises(Exception):
        decrypt_field(tampered, key, aad)


def test_decrypt_fails_on_aad_mismatch() -> None:
    key = b"k" * 32
    aad = {
        "agent_id": "agent-1",
        "event_id": "evt-1",
        "event_type": "interaction.append",
    }
    enc = encrypt_field(b"secret-memory", key, "kid-1", aad)

    wrong_aad = {
        "agent_id": "agent-1",
        "event_id": "evt-2",
        "event_type": "interaction.append",
    }

    with pytest.raises(Exception):
        decrypt_field(enc, key, wrong_aad)


def test_encrypt_rejects_invalid_key_length() -> None:
    aad = {
        "agent_id": "agent-1",
        "event_id": "evt-1",
        "event_type": "interaction.append",
    }
    with pytest.raises(ValueError, match="AES-GCM key must be 16, 24, or 32 bytes"):
        encrypt_field(b"secret-memory", b"short", "kid-1", aad)


def test_decrypt_rejects_invalid_key_length() -> None:
    key = b"k" * 32
    aad = {
        "agent_id": "agent-1",
        "event_id": "evt-1",
        "event_type": "interaction.append",
    }
    enc = encrypt_field(b"secret-memory", key, "kid-1", aad)
    with pytest.raises(ValueError, match="AES-GCM key must be 16, 24, or 32 bytes"):
        decrypt_field(enc, b"short", aad)
