"""Tests for the audit outbox internals — redaction, hash chaining, idempotency."""

from __future__ import annotations

from aria_agentkit.audit.outbox import AuditOutbox
from aria_agentkit.audit.receipt import mint_receipt


class TestReceipt:
    def test_mint_receipt_deterministic(self) -> None:
        r1 = mint_receipt({"a": 1}, prev_hash="abc", idempotency_key="k1")
        r2 = mint_receipt({"a": 1}, prev_hash="abc", idempotency_key="k1")
        assert r1.receipt_hash == r2.receipt_hash

    def test_different_payload_different_hash(self) -> None:
        r1 = mint_receipt({"a": 1}, idempotency_key="k1")
        r2 = mint_receipt({"a": 2}, idempotency_key="k1")
        assert r1.receipt_hash != r2.receipt_hash

    def test_different_prev_hash_different_receipt(self) -> None:
        r1 = mint_receipt({"a": 1}, prev_hash="aaa", idempotency_key="k1")
        r2 = mint_receipt({"a": 1}, prev_hash="bbb", idempotency_key="k1")
        assert r1.receipt_hash != r2.receipt_hash

    def test_auto_generated_idempotency_key(self) -> None:
        r = mint_receipt({"x": 1})
        assert len(r.idempotency_key) == 32

    def test_to_dict_roundtrip(self) -> None:
        r = mint_receipt({"a": 1}, idempotency_key="k1")
        d = r.to_dict()
        assert d["idempotency_key"] == "k1"
        assert d["payload"] == {"a": 1}
        assert "receipt_hash" in d
        assert "prev_hash" in d


class TestOutboxRedaction:
    def test_redacts_nested_keys(self) -> None:
        redacted = AuditOutbox._redact_value(
            {"outer": {"password": "secret", "safe": "ok"}, "token": "abc"},
            frozenset({"password", "token"}),
        )
        assert redacted["outer"]["password"] == "***REDACTED***"
        assert redacted["outer"]["safe"] == "ok"
        assert redacted["token"] == "***REDACTED***"

    def test_case_insensitive_redaction(self) -> None:
        redacted = AuditOutbox._redact_value(
            {"Password": "x", "TOKEN": "y"},
            frozenset({"password", "token"}),
        )
        assert redacted["Password"] == "***REDACTED***"
        assert redacted["TOKEN"] == "***REDACTED***"

    def test_redacts_inside_lists(self) -> None:
        redacted = AuditOutbox._redact_value(
            {"args": [{"secret": "x", "ok": "y"}, {"safe": "z"}]},
            frozenset({"secret"}),
        )
        assert redacted["args"][0]["secret"] == "***REDACTED***"
        assert redacted["args"][0]["ok"] == "y"
        assert redacted["args"][1]["safe"] == "z"

    def test_redacts_deeply_nested_lists(self) -> None:
        redacted = AuditOutbox._redact_value(
            {"steps": [{"actions": [{"password": "pw", "cmd": "run"}]}]},
            frozenset({"password"}),
        )
        assert redacted["steps"][0]["actions"][0]["password"] == "***REDACTED***"
        assert redacted["steps"][0]["actions"][0]["cmd"] == "run"

    def test_leaves_non_dict_list_items_alone(self) -> None:
        redacted = AuditOutbox._redact_value(
            {"items": [1, "hello", True, None]},
            frozenset({"password"}),
        )
        assert redacted["items"] == [1, "hello", True, None]
