"""Tests for aablocks.cached_token module."""

from __future__ import annotations

import threading

from aablocks.cached_token import clear_cached_token, get_cached_token, set_cached_token

DOMAIN = "auth.atlas.aalphabio.com"


class TestCachedToken:
    def setup_method(self):
        """Start each test with a clean cache."""
        clear_cached_token(DOMAIN)

    def test_get_returns_none_when_empty(self):
        """Getting from an empty cache returns None."""
        assert get_cached_token(DOMAIN) is None

    def test_set_and_get_roundtrip(self):
        """A token stored with set can be retrieved with get."""
        token = {"id_token": "abc123", "expires_at": 9999999999}
        set_cached_token(DOMAIN, token)
        assert get_cached_token(DOMAIN) == token

    def test_clear_removes_token(self):
        """Clearing the cache makes get return None."""
        set_cached_token(DOMAIN, {"id_token": "abc123"})
        clear_cached_token(DOMAIN)
        assert get_cached_token(DOMAIN) is None

    def test_set_overwrites_previous(self):
        """A second set replaces the previously stored token."""
        set_cached_token(DOMAIN, {"id_token": "first"})
        set_cached_token(DOMAIN, {"id_token": "second"})
        assert get_cached_token(DOMAIN)["id_token"] == "second"

    def test_separate_domains(self):
        """Tokens for different auth domains are stored independently."""
        set_cached_token("domain-a", {"id_token": "token_a"})
        set_cached_token("domain-b", {"id_token": "token_b"})
        assert get_cached_token("domain-a")["id_token"] == "token_a"
        assert get_cached_token("domain-b")["id_token"] == "token_b"
        clear_cached_token("domain-a")
        assert get_cached_token("domain-a") is None
        assert get_cached_token("domain-b")["id_token"] == "token_b"
        clear_cached_token("domain-b")

    def test_thread_safety(self):
        """Concurrent set/get operations should not raise or corrupt data."""
        results = []
        barrier = threading.Barrier(10)

        def writer(i: int):
            barrier.wait()
            set_cached_token(DOMAIN, {"id_token": f"token_{i}"})

        def reader():
            barrier.wait()
            val = get_cached_token(DOMAIN)
            results.append(val)

        threads = []
        for i in range(5):
            threads.append(threading.Thread(target=writer, args=(i,)))
            threads.append(threading.Thread(target=reader))

        for t in threads:
            t.start()
        for t in threads:
            t.join()

        # After all writers, cache should hold a valid token
        final = get_cached_token(DOMAIN)
        assert final is not None
        assert "id_token" in final
