from fastapi import Response

from bluefox_auth.cookies import clear_auth_cookies, set_auth_cookies
from bluefox_auth.settings import AuthSettings

SECRET = "test-secret-key-that-is-long-enough-for-validation"
SETTINGS = AuthSettings(secret_key=SECRET, cookie_secure=False)


def _get_cookies(response: Response, name: str) -> list[str]:
    """Extract set-cookie headers matching a cookie name from raw response headers."""
    results = []
    for key, value in response.raw_headers:
        if key == b"set-cookie":
            decoded = value.decode()
            if decoded.startswith(f"{name}="):
                results.append(decoded)
    return results


def test_set_auth_cookies__sets_access_token():
    response = Response()
    set_auth_cookies(response, "access-tok", "refresh-tok", SETTINGS)
    cookies = _get_cookies(response, "bf_access_token")
    assert len(cookies) == 1
    assert "httponly" in cookies[0].lower()


def test_set_auth_cookies__sets_refresh_token():
    response = Response()
    set_auth_cookies(response, "access-tok", "refresh-tok", SETTINGS)
    cookies = _get_cookies(response, "bf_refresh_token")
    assert len(cookies) == 1
    assert "httponly" in cookies[0].lower()
    assert "/auth" in cookies[0]


def test_set_auth_cookies__sets_csrf_token_not_httponly():
    response = Response()
    csrf = set_auth_cookies(response, "access-tok", "refresh-tok", SETTINGS)
    cookies = _get_cookies(response, "bf_csrf_token")
    assert len(cookies) == 1
    assert csrf  # non-empty string
    # CSRF cookie must NOT be httponly so JS can read it
    assert "httponly" not in cookies[0].lower()


def test_set_auth_cookies__returns_csrf_token():
    response = Response()
    csrf = set_auth_cookies(response, "access-tok", "refresh-tok", SETTINGS)
    assert len(csrf) > 20  # token_urlsafe(32) produces ~43 chars


def test_clear_auth_cookies__deletes_all_cookies():
    response = Response()
    clear_auth_cookies(response, SETTINGS)
    names = {"bf_access_token", "bf_refresh_token", "bf_csrf_token"}
    for name in list(names):
        cookies = _get_cookies(response, name)
        assert len(cookies) >= 1, f"Cookie {name} not found in response"
        raw = cookies[0]
        # Deleted cookies have max-age=0 or expire in the past
        assert "max-age=0" in raw.lower() or "01 jan 1970" in raw.lower()
        names.discard(name)
    assert len(names) == 0, f"Cookies not cleared: {names}"
