from __future__ import annotations

import logging
from functools import lru_cache
from typing import Any

import jwt
from jwt import PyJWKClient

from config import CLERK_ISSUER, CLERK_JWKS_URL

logger = logging.getLogger(__name__)


@lru_cache(maxsize=1)
def _jwks_client() -> PyJWKClient:
    if not CLERK_JWKS_URL:
        raise ValueError("CLERK_JWKS_URL is not configured")
    return PyJWKClient(CLERK_JWKS_URL, cache_jwk_set=True, lifespan=300)


def verify_clerk_jwt(token: str) -> dict[str, Any]:
    """
    Verify Clerk JWT using JWKS.

    Requires:
    - CLERK_JWKS_URL: e.g. https://<your-clerk-domain>/.well-known/jwks.json
    - CLERK_ISSUER:   e.g. https://<your-clerk-domain>
    """
    if not token:
        raise ValueError("Missing token")
    if not CLERK_JWKS_URL or not CLERK_ISSUER:
        raise ValueError("Missing CLERK_JWKS_URL / CLERK_ISSUER")

    signing_key = _jwks_client().get_signing_key_from_jwt(token).key

    # Clerk tokens are typically RS256.
    # leeway=300 tolerates up to 5min clock skew (VPS clock not NTP-synced)
    payload = jwt.decode(
        token,
        signing_key,
        algorithms=["RS256"],
        issuer=CLERK_ISSUER,
        leeway=300,
        options={
            "verify_aud": False,  # allow multiple audiences in dev
        },
    )
    return payload


