"""Teste F5: `_hits` nu creste monoton pe viata procesului.

Cheile ale caror timestamp-uri au expirat complet trebuie sterse din `_hits`
(nu doar golite), altfel dictionarul acumuleaza o intrare per IP vazut vreodata.
Semantica ferestrei glisante (permite/blocheaza) trebuie sa ramana neschimbata.
"""

from __future__ import annotations

import pytest

from app.web import ratelimit
from app.web.ratelimit import check_rate_limit


@pytest.fixture(autouse=True)
def _clean_hits():
    ratelimit._hits.clear()
    yield
    ratelimit._hits.clear()


def test_cheie_blocata_fara_timestamp_uri_valide_e_stearsa(monkeypatch):
    """max_hits=0 -> orice cerere e blocata; daca fereastra a expirat complet
    (filtrarea produce o lista goala), cheia nu trebuie sa ramana in `_hits`."""
    now = [1000.0]
    monkeypatch.setattr(ratelimit.time, "monotonic", lambda: now[0])

    key = "ip_blocat_gol"
    assert check_rate_limit(key, max_hits=0, window_s=60) is False
    # Nimic adaugat (max_hits=0 blocheaza tot) si lista era goala -> cheia disparuta.
    assert key not in ratelimit._hits


def test_cheie_activa_ramane_dupa_permis(monkeypatch):
    """O cerere permisa isi adauga timestamp-ul -> cheia activa ramane in `_hits`."""
    now = [1000.0]
    monkeypatch.setattr(ratelimit.time, "monotonic", lambda: now[0])

    key = "ip_activ"
    assert check_rate_limit(key, max_hits=2, window_s=60) is True
    assert key in ratelimit._hits
    assert ratelimit._hits[key] == [1000.0]


def test_semantica_max_hits_si_fereastra_neschimbata(monkeypatch):
    """max_hits atinse -> False; dupa expirarea ferestrei -> True din nou."""
    now = [1000.0]
    monkeypatch.setattr(ratelimit.time, "monotonic", lambda: now[0])

    key = "ip_fereastra"
    assert check_rate_limit(key, max_hits=2, window_s=10) is True
    assert check_rate_limit(key, max_hits=2, window_s=10) is True
    # A treia cerere in aceeasi fereastra -> blocata.
    assert check_rate_limit(key, max_hits=2, window_s=10) is False

    # Trece timpul peste fereastra -> toate timestamp-urile expira.
    now[0] += 11
    assert check_rate_limit(key, max_hits=2, window_s=10) is True
    # Doar noua cerere ramane in lista (cele vechi, expirate, au fost curatate).
    assert ratelimit._hits[key] == [1011.0]


def test_cheie_dispare_dupa_expirare_completa_si_reblocare(monkeypatch):
    """O cheie blocata, ramasa fara timestamp-uri valide dupa expirarea ferestrei
    (fara sa mai apara alte cereri intre timp), nu trebuie sa ramana in `_hits`
    la urmatorul apel care o gaseste goala si tot o blocheaza (max_hits=0)."""
    now = [1000.0]
    monkeypatch.setattr(ratelimit.time, "monotonic", lambda: now[0])

    key = "ip_reblocat"
    check_rate_limit(key, max_hits=0, window_s=5)
    assert key not in ratelimit._hits

    now[0] += 100
    assert check_rate_limit(key, max_hits=0, window_s=5) is False
    assert key not in ratelimit._hits
