"""Refresh token reuse detection (rotated token replay)."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from server.application.services.auth_service import AuthService
from server.domain.models import Admin


@pytest.mark.asyncio
async def test_refresh_reuse_invalidates_all_sessions(monkeypatch):
    admin = Admin(id=1, username="admin", password_hash="x", is_active=True, token_version=2)
    service = AuthService(
        admin_repo=AsyncMock(),
        attempt_repo=AsyncMock(),
        audit_repo=AsyncMock(),
    )
    service.admin_repo.get_by_id = AsyncMock(return_value=admin)
    service.admin_repo.update = AsyncMock(return_value=admin)
    service._audit = AsyncMock()
    service._delete_all_refresh_tokens = AsyncMock()
    service._remove_refresh_token = AsyncMock()
    service._store_refresh_token = AsyncMock()
    service._create_access_token = MagicMock(return_value="access")
    service._create_refresh_token = MagicMock(return_value="new:1:2")

    token = "oldsecret:1:2"

    async def membership(_admin_id, _token):
        return False

    monkeypatch.setattr(service, "_refresh_token_membership", membership)

    result = await service.refresh_token(token, ip_address="127.0.0.1")

    assert result["success"] is False
    assert admin.token_version == 3
    service.admin_repo.update.assert_awaited_once()
    service._delete_all_refresh_tokens.assert_awaited_once_with(1)
    service._audit.assert_awaited()
    assert service._audit.await_args[0][0] == "refresh_token_reuse"


@pytest.mark.asyncio
async def test_refresh_redis_down_returns_unavailable(monkeypatch):
    admin = Admin(id=1, username="admin", password_hash="x", is_active=True, token_version=1)
    service = AuthService(AsyncMock(), AsyncMock(), AsyncMock())
    service.admin_repo.get_by_id = AsyncMock(return_value=admin)
    service._audit = AsyncMock()

    async def membership(_admin_id, _token):
        return None

    monkeypatch.setattr(service, "_refresh_token_membership", membership)

    result = await service.refresh_token("t:1:1", ip_address="")

    assert result["success"] is False
    assert result["reason"] == "service_unavailable"
