# import logging
from uuid import UUID

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt

from app.core.config import settings

oauth2_optional = OAuth2PasswordBearer(
    tokenUrl="keycloak", auto_error=False
)

# logger = logging.getLogger(__name__)


def _decode_keycloak_token(token: str) -> dict:
    if not settings.KEYCLOAK_PUBLIC_KEY:
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="Keycloak public key is not configured",
        )

    key = settings.KEYCLOAK_PUBLIC_KEY.replace("\\n", "\n")

    return jwt.decode(
        token,
        key,
        algorithms=[settings.KEYCLOAK_ALGORITHM],
        audience=settings.KEYCLOAK_AUDIENCE or None,
    )


async def get_current_keycloak_payload(
    token: str | None = Depends(oauth2_optional),
) -> dict:
    if not token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Not authenticated",
            headers={"WWW-Authenticate": "Bearer"},
        )

    try:
        return _decode_keycloak_token(token)
    except JWTError as exc:
        # logger.warning("Keycloak token validation failed: %s", exc)
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token",
            headers={"WWW-Authenticate": "Bearer"},
        ) from exc


async def get_current_keycloak_sub(
    payload: dict = Depends(get_current_keycloak_payload),
) -> UUID:
    sub = payload.get("sub")
    if not sub:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Missing subject claim",
            headers={"WWW-Authenticate": "Bearer"},
        )

    try:
        return UUID(sub)
    except ValueError as exc:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid subject claim",
            headers={"WWW-Authenticate": "Bearer"},
        ) from exc


async def get_current_keycloak_username(
    payload: dict = Depends(get_current_keycloak_payload),
) -> str:
    username = payload.get("preferred_username") or payload.get("username")
    if not username:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Missing username claim",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return str(username)
