"""Production API limits stay shared after removing Redis."""

import asyncio
from datetime import UTC, datetime, timedelta

from limits import parse
from limits.strategies import FixedWindowRateLimiter
from sqlalchemy import update
from sqlalchemy.ext.asyncio import AsyncSession

from app.config import settings
from app.core.rate_limit_storage import PostgreSQLRateLimitStorage
from app.core.state_store import is_refresh_token_valid, store_refresh_token
from app.models.expiring_state import ExpiringState


def _storage() -> PostgreSQLRateLimitStorage:
    return PostgreSQLRateLimitStorage(
        settings.DATABASE_URL.replace("postgresql+asyncpg://", "postgresql+munal://", 1)
    )


async def test_production_limits_are_shared_across_independent_workers() -> None:
    first, second = _storage(), _storage()
    try:
        limit = parse("5/minute")
        limiters = [FixedWindowRateLimiter(first), FixedWindowRateLimiter(second)]
        allowed = await asyncio.gather(
            *[asyncio.to_thread(limiters[index % 2].hit, limit, "client", "login") for index in range(12)]
        )
        assert sum(allowed) == 5
        assert not await asyncio.to_thread(limiters[0].hit, limit, "client", "login")
        assert await asyncio.to_thread(limiters[0].hit, limit, "other-client", "login")
        assert await asyncio.to_thread(first.check)
    finally:
        first.close()
        second.close()


async def test_counter_fixed_expiry_clear_and_reset_do_not_remove_sessions(db_session: AsyncSession) -> None:
    store = _storage()
    try:
        await store_refresh_token("user", "token", 300)
        assert await asyncio.to_thread(store.incr, "counter", 60) == 1
        before = await asyncio.to_thread(store.get_expiry, "counter")
        assert await asyncio.to_thread(store.incr, "counter", 60, 3) == 4
        assert await asyncio.to_thread(store.get_expiry, "counter") == before
        assert await asyncio.to_thread(store.get, "counter") == 4
        await db_session.execute(
            update(ExpiringState)
            .where(ExpiringState.key.like("api_rate:%"))
            .values(expires_at=datetime.now(UTC) - timedelta(seconds=1))
        )
        await db_session.commit()
        assert await asyncio.to_thread(store.get, "counter") == 0
        assert await asyncio.to_thread(store.incr, "counter", 60) == 1
        await asyncio.to_thread(store.clear, "counter")
        assert await asyncio.to_thread(store.get, "counter") == 0
        await asyncio.to_thread(store.incr, "next", 60)
        assert await asyncio.to_thread(store.reset) == 1
        assert await is_refresh_token_valid("user", "token")
    finally:
        store.close()
