"""FastAPI dependencies for authentication."""

from typing import Annotated

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer

from .service import AuthService
from .types.repository import UserRepositoryInterface
from .auth_utils import verify_token
from .exceptions import ExpiredTokenError, InvalidTokenError, InactiveUserError
from .models import User
from .repositories import get_user_repository

# HTTP Bearer security scheme
security = HTTPBearer()


def get_auth_service(user_repository: Annotated[UserRepositoryInterface, Depends(get_user_repository)]) -> AuthService:
    return AuthService(user_repository)


async def get_current_user(credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)], user_repository: Annotated[UserRepositoryInterface, Depends(get_user_repository)]) -> User:
    """
    Get current authenticated user from JWT token.

    Args:
        credentials: HTTP Bearer credentials
        user_repository: User repository

    Returns:
        Authenticated user

    Raises:
        HTTPException: If token is invalid or user not found
    """
    token = credentials.credentials

    try:
        payload = verify_token(token)

        # Verify token type
        if payload.get("type") != "access":
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid token type",
                headers={"WWW-Authenticate": "Bearer"},
            )

        # SECURITY: Reject tokens with tfaPending: true
        # These tokens are issued after password verification but before 2FA verification
        # and should not be used for normal API requests
        if payload.get("tfaPending") is True:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="2FA verification required. Token is pending 2FA verification.",
                headers={"WWW-Authenticate": "Bearer"},
            )

        # Get user ID from token
        user_id = payload.get("sub")
        if not user_id:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid token payload",
                headers={"WWW-Authenticate": "Bearer"},
            )

        # Get user from store
        user = await user_repository.get_user_by_id(user_id)
        if user is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="User not found",
                headers={"WWW-Authenticate": "Bearer"},
            )

        # Check if user is active
        if not user.isActive:
            raise InactiveUserError("User account is inactive")

        return user

    except ExpiredTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token has expired",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except InactiveUserError:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="User account is inactive",
        )


# Type alias for dependency injection
CurrentUser = Annotated[User, Depends(get_current_user)]
AuthServiceDep = Annotated[AuthService, Depends(get_auth_service)]
