"""Login rate limit: 5 fails / 5 min per username."""

from __future__ import annotations

import pytest
from fastapi.testclient import TestClient
from sqlalchemy import delete

from cyclone.api import app
from cyclone.auth import rate_limit, users
from cyclone.db import Session as DbSession
from cyclone.db import SessionLocal, User


@pytest.fixture(autouse=True)
def _clear(monkeypatch):
    # conftest sets AUTH_DISABLED=True so pre-auth tests keep passing
    # without a login. The auth-login-rate-limit tests need the real
    # auth path exercised (the rate limiter sits in front of /login),
    # so flip it back off here.
    monkeypatch.setattr("cyclone.auth.deps.AUTH_DISABLED", False)
    with SessionLocal()() as db:
        db.execute(delete(DbSession))
        db.execute(delete(User))
        db.commit()
    # Reset the in-memory rate-limit counter so a previous test's 5
    # failures don't poison this test. The plan recipe calls this out.
    rate_limit.reset("victim")
    yield
    with SessionLocal()() as db:
        db.execute(delete(DbSession))
        db.execute(delete(User))
        db.commit()
    rate_limit.reset("victim")


def test_5_fails_then_429():
    with SessionLocal()() as db:
        users.create(db, username="victim", password="hunter2hunter2", role="user")
    client = TestClient(app)
    for _ in range(5):
        r = client.post(
            "/api/auth/login",
            json={"username": "victim", "password": "WRONG"},
        )
        assert r.status_code == 401
    # 6th should be 429.
    r = client.post(
        "/api/auth/login",
        json={"username": "victim", "password": "WRONG"},
    )
    assert r.status_code == 429
    assert "Retry-After" in r.headers
    # And the module-level helper confirms we're now over the threshold.
    assert rate_limit.check("victim") > 0


def test_successful_login_resets_counter():
    with SessionLocal()() as db:
        users.create(db, username="victim", password="hunter2hunter2", role="user")
    client = TestClient(app)
    for _ in range(4):
        r = client.post(
            "/api/auth/login",
            json={"username": "victim", "password": "WRONG"},
        )
        assert r.status_code == 401
    # Successful login — should reset the counter.
    r = client.post(
        "/api/auth/login",
        json={"username": "victim", "password": "hunter2hunter2"},
    )
    assert r.status_code == 200
    # Counter reset — 5 more fails allowed.
    for _ in range(5):
        r = client.post(
            "/api/auth/login",
            json={"username": "victim", "password": "WRONG"},
        )
        assert r.status_code == 401
    # 6th is now throttled.
    r = client.post(
        "/api/auth/login",
        json={"username": "victim", "password": "WRONG"},
    )
    assert r.status_code == 429
