"""Middleware to require MetaInfo authentication."""

from fastapi import Request

from hezor_common.transfer.base_sdk.meta_info import MetaInfo
from hezor_common.transfer.middlewares.constants import ERR_RES_HEADER_META_INFO


class RequireMetaInfo:
    """Dependency factory for MetaInfo authentication with configurable realm.

    This class can be instantiated with a custom realm parameter or used as
    a default instance for backward compatibility.

    Parameters
    ----------
    realm : str, optional
        The authentication realm for WWW-Authenticate header
        (default: "Access to the protected resource")

    Examples
    --------
    >>> from fastapi import Depends
    >>> # Using default instance (backward compatible)
    >>> @app.get("/protected")
    >>> async def protected_route(meta: MetaInfo = Depends(require_meta_info)):
    ...     return {"subject": meta.subject, "subject_code": meta.subject_code}
    >>> # Using custom realm
    >>> @app.get("/admin")
    >>> async def admin_route(meta: MetaInfo = Depends(RequireMetaInfo("Admin area"))):
    ...     return {"subject": meta.subject}
    """

    def __init__(self, realm: str = "Access to the protected resource"):
        """Initialize the MetaInfo dependency with custom realm.

        Parameters
        ----------
        realm : str, optional
            The authentication realm for WWW-Authenticate header
        """
        self.realm = realm

    def __call__(self, request: Request) -> MetaInfo:
        """Dependency to extract and require valid MetaInfo.

        Parameters
        ----------
        request : Request
            FastAPI request object

        Returns
        -------
        MetaInfo
            Validated MetaInfo object

        Raises
        ------
        HTTPException
            If MetaInfo is missing or invalid
        """
        from fastapi import HTTPException

        if hasattr(request.state, "meta_info_error") and request.state.meta_info_error:
            raise HTTPException(
                status_code=401,
                detail=request.state.meta_info_error,
                headers=ERR_RES_HEADER_META_INFO(realm=self.realm),
            )

        if not hasattr(request.state, "meta_info") or request.state.meta_info is None:
            raise HTTPException(
                status_code=401,
                detail="MetaInfo required",
                headers=ERR_RES_HEADER_META_INFO(realm=self.realm),
            )

        return request.state.meta_info


class GetMetaInfo:
    """Dependency factory for optional MetaInfo extraction.

    This class can be instantiated or used as a default instance for backward compatibility.

    Examples
    --------
    >>> from fastapi import Depends
    >>> # Using default instance (backward compatible)
    >>> @app.get("/optional")
    >>> async def optional_route(meta: MetaInfo | None = Depends(get_meta_info)):
    ...     if meta:
    ...         return {"subject": meta.subject}
    ...     return {"message": "No MetaInfo provided"}
    """

    def __call__(self, request: Request) -> MetaInfo | None:
        """Dependency to optionally extract MetaInfo.

        Parameters
        ----------
        request : Request
            FastAPI request object

        Returns
        -------
        MetaInfo | None
            MetaInfo object if present and valid, None otherwise
        """
        if hasattr(request.state, "meta_info"):
            return request.state.meta_info
        return None


# Default instances for backward compatibility
require_meta_info = RequireMetaInfo()
get_meta_info = GetMetaInfo()
