"""Tests for the resolve_nous_access_token startup-burst memo (PR #66016).

The memo collapses the startup burst of managed-tool check_fn calls into a
single expensive resolution: within the short TTL, repeat calls return the
cached token without re-entering _provider_state_transaction (two
cross-process file locks + state reads) or triggering a network refresh.
"""

import json
import time

import pytest

import hermes_cli.auth as auth


@pytest.fixture(autouse=True)
def _fresh_memo(monkeypatch, tmp_path):
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    monkeypatch.delenv("HERMES_PORTAL_BASE_URL", raising=False)
    monkeypatch.delenv("NOUS_PORTAL_BASE_URL", raising=False)
    monkeypatch.setattr(auth, "_RESOLVE_TOKEN_CACHE", {})
    yield


def _write_valid_auth_file(tmp_path, token="memo-token"):
    (tmp_path / "auth.json").write_text(
        json.dumps(
            {
                "version": 1,
                "active_provider": "nous",
                "providers": {
                    "nous": {
                        "access_token": token,
                        "refresh_token": "r",
                        "client_id": "hermes-cli-vps",
                        "expires_at": time.strftime(
                            "%Y-%m-%dT%H:%M:%S+00:00", time.gmtime(time.time() + 3600)
                        ),
                    }
                },
            }
        )
    )


def _count_transactions(monkeypatch):
    calls = {"n": 0}
    real = auth._provider_state_transaction

    def _counting(provider):
        calls["n"] += 1
        return real(provider)

    monkeypatch.setattr(auth, "_provider_state_transaction", _counting)
    return calls


def test_repeat_calls_within_ttl_hit_memo(monkeypatch, tmp_path):
    _write_valid_auth_file(tmp_path)
    calls = _count_transactions(monkeypatch)

    first = auth.resolve_nous_access_token()
    second = auth.resolve_nous_access_token()
    third = auth.resolve_nous_access_token()

    assert first == second == third == "memo-token"
    assert calls["n"] == 1, (
        "repeat calls within the TTL must not re-enter the state transaction"
    )


def test_memo_expires_after_ttl(monkeypatch, tmp_path):
    _write_valid_auth_file(tmp_path)
    calls = _count_transactions(monkeypatch)

    auth.resolve_nous_access_token()
    cache_key = auth.hermes_home_key()
    cached_at, tok = auth._RESOLVE_TOKEN_CACHE[cache_key]
    monkeypatch.setattr(
        auth,
        "_RESOLVE_TOKEN_CACHE",
        {cache_key: (cached_at - auth._RESOLVE_TOKEN_CACHE_TTL_S - 1.0, tok)},
    )
    auth.resolve_nous_access_token()

    assert calls["n"] == 2, "an expired memo must re-resolve"


def test_insecure_callers_bypass_memo(monkeypatch, tmp_path):
    _write_valid_auth_file(tmp_path)
    calls = _count_transactions(monkeypatch)

    auth.resolve_nous_access_token()
    auth.resolve_nous_access_token(insecure=True)

    assert calls["n"] == 2, "insecure callers must bypass the memo entirely"


def test_memo_does_not_leak_across_multiplex_profile_contexts(tmp_path):
    """A multiplex gateway scopes each profile's context via
    hermes_constants.set_hermes_home_override (gateway/run.py,
    tui_gateway/server.py), not the HERMES_HOME env var — the memo must key
    on that same resolved home, or one profile's context can read another
    profile's already-cached Nous access token for up to the TTL window.
    """
    import hermes_constants

    profile_a = tmp_path / "profile-a"
    profile_b = tmp_path / "profile-b"
    profile_a.mkdir()
    profile_b.mkdir()
    _write_valid_auth_file(profile_a, token="token-a")
    _write_valid_auth_file(profile_b, token="token-b")

    token_a = token_b = None
    reset_token = hermes_constants.set_hermes_home_override(str(profile_a))
    try:
        token_a = auth.resolve_nous_access_token()
    finally:
        hermes_constants.reset_hermes_home_override(reset_token)

    # Still well within the 5s TTL — this is exactly the race window: profile
    # B's context calls resolve_nous_access_token() shortly after profile A's.
    reset_token = hermes_constants.set_hermes_home_override(str(profile_b))
    try:
        token_b = auth.resolve_nous_access_token()
    finally:
        hermes_constants.reset_hermes_home_override(reset_token)

    assert token_a == "token-a"
    assert token_b == "token-b", (
        "profile B's context must not receive profile A's cached access token"
    )
