"""JWT encode/decode round-trips."""

from __future__ import annotations

from datetime import datetime, timedelta, timezone

import jwt as pyjwt
import pytest

from notify_bridge_server.auth.jwt import (
    ALGORITHM,
    create_access_token,
    create_refresh_token,
    decode_token,
)
from notify_bridge_server.config import settings


def test_access_token_round_trip() -> None:
    token = create_access_token(user_id=1, role="admin", token_version=3)
    payload = decode_token(token)
    assert payload["sub"] == "1"
    assert payload["type"] == "access"
    assert payload["role"] == "admin"
    assert payload["ver"] == 3
    assert payload["iss"] == settings.jwt_issuer
    assert payload["aud"] == settings.jwt_audience


def test_refresh_token_round_trip() -> None:
    token = create_refresh_token(user_id=7, token_version=2)
    payload = decode_token(token)
    assert payload["type"] == "refresh"
    assert payload["sub"] == "7"


def test_decode_rejects_wrong_audience() -> None:
    """A token signed with our key but for a different audience is rejected."""
    now = datetime.now(timezone.utc)
    forged = pyjwt.encode(
        {
            "iss": settings.jwt_issuer,
            "aud": "other-service",
            "sub": "1",
            "type": "access",
            "ver": 1,
            "iat": now,
            "exp": now + timedelta(minutes=5),
        },
        settings.secret_key,
        algorithm=ALGORITHM,
    )
    with pytest.raises(pyjwt.InvalidAudienceError):
        decode_token(forged)


def test_decode_rejects_none_alg() -> None:
    """An ``alg: none`` token must never be accepted."""
    now = datetime.now(timezone.utc)
    forged = pyjwt.encode(
        {
            "iss": settings.jwt_issuer,
            "aud": settings.jwt_audience,
            "sub": "1",
            "type": "access",
            "ver": 1,
            "iat": now,
            "exp": now + timedelta(minutes=5),
        },
        "",
        algorithm="none",
    )
    with pytest.raises(pyjwt.InvalidAlgorithmError):
        decode_token(forged)
