"""Authentication test helpers.

This module contains utilities for generating test tokens and other
authentication-related test helpers. These functions should ONLY be
used in test code, never in production.
"""

from datetime import datetime, timedelta, timezone

import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa


def generate_test_token(
    issuer: str = "https://test-issuer.example.com",
    audience: str = "m4-api",
    subject: str = "test-user",
    scopes: list[str] | None = None,
    expires_in: int = 3600,
) -> str:
    """Generate a test JWT token for development/testing.

    This function creates a self-signed JWT token for testing purposes.
    The token is signed with a randomly generated RSA key, so it cannot
    be validated against real OAuth2 providers.

    Args:
        issuer: The token issuer URL
        audience: The intended audience for the token
        subject: The subject (user ID) for the token
        scopes: List of scopes to include in the token
        expires_in: Token expiration time in seconds (default: 1 hour)

    Returns:
        A signed JWT token string

    Example:
        token = generate_test_token(
            subject="test-user-123",
            scopes=["read:mimic-data", "write:mimic-data"],
        )

    Warning:
        This function is for TESTING ONLY. Never use generated tokens
        in production environments.
    """
    if scopes is None:
        scopes = ["read:mimic-data"]

    now = datetime.now(timezone.utc)
    claims = {
        "iss": issuer,
        "aud": audience,
        "sub": subject,
        "iat": int(now.timestamp()),
        "exp": int((now + timedelta(seconds=expires_in)).timestamp()),
        "scope": " ".join(scopes),
        "email": f"{subject}@example.com",
    }

    # Generate a test key (DO NOT use in production)
    private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)

    private_pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption(),
    )

    # Sign the token
    token = jwt.encode(claims, private_pem, algorithm="RS256")

    return token
