"""JWT authentication guards."""

from datetime import datetime, timedelta, timezone
from typing import Any

import jwt
from litestar.connection import ASGIConnection
from litestar.security.jwt import JWTAuth, Token

from app.config import settings
from auth.schemas import TokenPayload


async def retrieve_user_handler(token: Token, connection: ASGIConnection) -> dict[str, Any] | None:
    """Retrieve user from JWT token.

    This is a placeholder implementation. In a real application, you would:
    1. Extract the user ID from the token
    2. Fetch the user from the database
    3. Return the user object or None if not found

    Args:
        token: The decoded JWT token.
        connection: The ASGI connection.

    Returns:
        User data or None if not found.
    """
    # Example: Return token subject as user identifier
    return {"id": token.sub, "token": token}


def create_access_token(subject: str, expires_delta: timedelta | None = None) -> str:
    """Create a new JWT access token.

    Args:
        subject: The subject of the token (usually user ID).
        expires_delta: Optional custom expiration time.

    Returns:
        Encoded JWT token string.
    """
    if expires_delta is None:
        expires_delta = timedelta(minutes=settings.JWT_EXPIRATION_MINUTES)

    expire = datetime.now(timezone.utc) + expires_delta

    payload = TokenPayload(
        sub=subject,
        exp=expire,
        iat=datetime.now(timezone.utc),
    )

    return jwt.encode(
        payload.to_dict(),
        settings.JWT_SECRET,
        algorithm=settings.JWT_ALGORITHM,
    )


def decode_token(token: str) -> TokenPayload | None:
    """Decode and validate a JWT token.

    Args:
        token: The JWT token string.

    Returns:
        TokenPayload if valid, None otherwise.
    """
    try:
        payload = jwt.decode(
            token,
            settings.JWT_SECRET,
            algorithms=[settings.JWT_ALGORITHM],
        )
        return TokenPayload(
            sub=payload["sub"],
            exp=datetime.fromtimestamp(payload["exp"], tz=timezone.utc),
            iat=datetime.fromtimestamp(payload["iat"], tz=timezone.utc),
        )
    except jwt.PyJWTError:
        return None


# JWT Auth configuration
jwt_auth = JWTAuth[dict[str, Any]](
    retrieve_user_handler=retrieve_user_handler,
    token_secret=settings.JWT_SECRET,
    algorithm=settings.JWT_ALGORITHM,
    exclude=["/", "/health", "/schema"],
)
