"""FastAPI dependencies for authentication."""

from typing import Annotated, Any

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession

from apex.core.security.jwt import decode_token
from apex.infrastructure.database.session import get_db

# OAuth2 scheme for token extraction
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/v1/auth/login")


async def get_current_user(
    token: Annotated[str, Depends(oauth2_scheme)],
    db: Annotated[AsyncSession, Depends(get_db)],
) -> dict[str, Any]:
    """
    Dependency to get current authenticated user from JWT token.

    This is a base implementation that returns the decoded token payload.
    Users should override this to fetch the actual user from the database.

    Args:
        token: JWT token from request
        db: Database session

    Returns:
        Decoded token payload (user_id, email, etc.)

    Raises:
        HTTPException: If token is invalid or user not found
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        payload = decode_token(token)
        user_id: str | None = payload.get("sub")
        if user_id is None:
            raise credentials_exception

        # Token type validation
        token_type = payload.get("type")
        if token_type != "access":
            raise credentials_exception

        return payload

    except Exception:
        raise credentials_exception


async def get_current_active_user(
    current_user: Annotated[dict[str, Any], Depends(get_current_user)],
) -> dict[str, Any]:
    """
    Dependency to ensure current user is active.

    Args:
        current_user: Current user from get_current_user

    Returns:
        Current user payload

    Raises:
        HTTPException: If user is not active
    """
    is_active = current_user.get("is_active", True)
    if not is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Inactive user",
        )
    return current_user


async def get_current_user_optional(
    token: Annotated[str | None, Depends(oauth2_scheme)] = None,
) -> dict[str, Any] | None:
    """
    Optional authentication dependency.

    Returns user if token is valid, None otherwise.

    Args:
        token: Optional JWT token

    Returns:
        User payload or None
    """
    if not token:
        return None

    try:
        payload = decode_token(token)
        if payload.get("type") != "access":
            return None
        return payload
    except Exception:
        return None

