"""Unit tests for the recently-revoked denylist (U2 / U3)."""

from __future__ import annotations

import time

from agentkit.server.auth.denylist import (
    InMemoryRecentlyRevoked,
    hash_token,
)


def test_add_then_contains_within_ttl():
    cache: InMemoryRecentlyRevoked = InMemoryRecentlyRevoked()
    h = hash_token("token-a")
    cache.add(h, ttl_seconds=10)
    assert cache.contains(h) is True


def test_contains_returns_false_after_ttl_expires():
    cache: InMemoryRecentlyRevoked = InMemoryRecentlyRevoked()
    h = hash_token("token-b")
    cache.add(h, ttl_seconds=0)
    # TTL=0 → expires immediately (or very soon)
    time.sleep(0.05)
    assert cache.contains(h) is False


def test_evicts_oldest_when_overflowed():
    cache: InMemoryRecentlyRevoked = InMemoryRecentlyRevoked(max_entries=2)
    cache.add("a", ttl_seconds=10)
    cache.add("b", ttl_seconds=10)
    cache.add("c", ttl_seconds=10)  # pushes 'a' out (LRU eviction)
    assert cache.contains("a") is False
    assert cache.contains("b") is True
    assert cache.contains("c") is True


def test_re_add_refreshes_ttl_and_lru_position():
    cache: InMemoryRecentlyRevoked = InMemoryRecentlyRevoked(max_entries=2)
    cache.add("a", ttl_seconds=10)
    cache.add("b", ttl_seconds=10)
    cache.add("a", ttl_seconds=10)  # re-add: should now be MRU
    cache.add("c", ttl_seconds=10)  # evicts oldest, which is 'b' now
    assert cache.contains("a") is True
    assert cache.contains("b") is False
    assert cache.contains("c") is True


def test_clear_drops_all_entries():
    cache: InMemoryRecentlyRevoked = InMemoryRecentlyRevoked()
    cache.add("a", ttl_seconds=10)
    cache.add("b", ttl_seconds=10)
    cache.clear()
    assert cache.contains("a") is False
    assert cache.contains("b") is False


def test_hash_token_is_stable_and_sha256_hex():
    h1 = hash_token("xyz")
    h2 = hash_token("xyz")
    assert h1 == h2
    assert len(h1) == 64
    assert all(c in "0123456789abcdef" for c in h1)
