"""Test fixtures for vikdata-auth SDK."""

import json
import time
from typing import Any
from uuid import uuid4

import pytest
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

import jwt


@pytest.fixture
def rsa_key_pair():
    """Generate RSA key pair for testing."""
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend(),
    )
    public_key = private_key.public_key()
    return private_key, public_key


@pytest.fixture
def kid():
    """Generate a unique key ID."""
    return f"test-key-{uuid4().hex[:8]}"


@pytest.fixture
def jwks(rsa_key_pair, kid):
    """Generate JWKS from RSA key pair."""
    _, public_key = rsa_key_pair

    # Get public key numbers
    public_numbers = public_key.public_numbers()

    # Convert to base64url encoding
    import base64

    def int_to_base64url(value: int, length: int) -> str:
        data = value.to_bytes(length, byteorder="big")
        return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")

    n = int_to_base64url(public_numbers.n, 256)  # 2048 bits = 256 bytes
    e = int_to_base64url(public_numbers.e, 3)  # 65537 fits in 3 bytes

    return {
        "keys": [
            {
                "kty": "RSA",
                "use": "sig",
                "alg": "RS256",
                "kid": kid,
                "n": n,
                "e": e,
            }
        ]
    }


@pytest.fixture
def create_token(rsa_key_pair, kid):
    """Factory fixture to create signed JWTs."""
    private_key, _ = rsa_key_pair

    def _create_token(
        sub: str = str(uuid4()),
        tenant_id: str = str(uuid4()),
        email: str = "test@example.com",
        name: str = "Test User",
        permissions: list[str] | None = None,
        roles: list[str] | None = None,
        exp: int | None = None,
        iat: int | None = None,
        iss: str = "https://api.vikdata.com",
        aud: str = "vikdata",
        jti: str | None = None,
        entity_type: str = "user",
        custom_kid: str | None = None,
    ) -> str:
        now = int(time.time())
        payload = {
            "sub": sub,
            "tenant_id": tenant_id,
            "email": email,
            "name": name,
            "permissions": permissions or ["vessels:read"],
            "roles": roles or ["viewer"],
            "exp": exp or now + 3600,
            "iat": iat or now,
            "iss": iss,
            "aud": aud,
            "entity_type": entity_type,
        }
        if jti:
            payload["jti"] = jti

        return jwt.encode(
            payload,
            private_key,
            algorithm="RS256",
            headers={"kid": custom_kid or kid},
        )

    return _create_token


@pytest.fixture
def expired_token(create_token):
    """Create an expired token."""
    return create_token(exp=int(time.time()) - 3600)


@pytest.fixture
def valid_token(create_token):
    """Create a valid token with default claims."""
    return create_token()


@pytest.fixture
def token_with_permissions(create_token):
    """Factory to create token with specific permissions."""

    def _token_with_permissions(permissions: list[str]) -> str:
        return create_token(permissions=permissions)

    return _token_with_permissions
