"""
Abstract port interface for authentication operations.

Defines the provider-agnostic contract that all auth adapters must implement.
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional


class AuthPort(ABC):
    """
    Abstract interface for authentication providers.

    All auth adapters must implement this interface.
    """

    @abstractmethod
    def verify_token(self, token: str) -> Dict[str, Any]:
        """
        Verify and decode a JWT token (synchronous).

        Args:
            token: Raw JWT string

        Returns:
            Decoded token payload as dictionary

        Raises:
            TokenError: If token is invalid, expired, or malformed
        """
        pass

    @abstractmethod
    async def verify_token_async(self, token: str) -> Dict[str, Any]:
        """
        Verify and decode a JWT token (asynchronous).

        Args:
            token: Raw JWT string

        Returns:
            Decoded token payload as dictionary

        Raises:
            TokenError: If token is invalid, expired, or malformed
        """
        pass

    @abstractmethod
    def has_role(self, payload: Dict[str, Any], roles: List[str]) -> bool:
        """
        Check if the token payload contains any of the required roles.

        The role can come from different locations depending on the provider
        configuration (e.g., org_role for org-scoped tokens, or
        public_metadata.rol for custom roles without orgs).

        Args:
            payload: Decoded JWT payload
            roles: List of acceptable roles (e.g., ["coordinador", "admin"])

        Returns:
            True if user has at least one of the required roles
        """
        pass

    @abstractmethod
    def get_org_id(self, payload: Dict[str, Any]) -> Optional[str]:
        """
        Extract organization ID from token payload.

        Args:
            payload: Decoded JWT payload

        Returns:
            Organization ID string or None
        """
        pass

    @abstractmethod
    def get_user_id(self, payload: Dict[str, Any]) -> Optional[str]:
        """
        Extract user ID from token payload.

        Args:
            payload: Decoded JWT payload

        Returns:
            User ID string or None
        """
        pass
