"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from abc import ABC, abstractmethod
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    List,
    Optional,
    Protocol,
    Tuple,
    Union,
    runtime_checkable,
)

import httpx

if TYPE_CHECKING:
    from anncsu.common.sdkconfiguration import SDKConfiguration


class HookContext:
    config: "SDKConfiguration"
    base_url: str
    operation_id: str
    oauth2_scopes: Optional[List[str]] = None
    security_source: Optional[Union[Any, Callable[[], Any]]] = None

    def __init__(
        self,
        config: "SDKConfiguration",
        base_url: str,
        operation_id: str,
        oauth2_scopes: Optional[List[str]],
        security_source: Optional[Union[Any, Callable[[], Any]]],
    ):
        self.config = config
        self.base_url = base_url
        self.operation_id = operation_id
        self.oauth2_scopes = oauth2_scopes
        self.security_source = security_source


class BeforeRequestContext(HookContext):
    def __init__(self, hook_ctx: HookContext):
        super().__init__(
            hook_ctx.config,
            hook_ctx.base_url,
            hook_ctx.operation_id,
            hook_ctx.oauth2_scopes,
            hook_ctx.security_source,
        )


class AfterSuccessContext(HookContext):
    def __init__(self, hook_ctx: HookContext):
        super().__init__(
            hook_ctx.config,
            hook_ctx.base_url,
            hook_ctx.operation_id,
            hook_ctx.oauth2_scopes,
            hook_ctx.security_source,
        )


class AfterErrorContext(HookContext):
    def __init__(self, hook_ctx: HookContext):
        super().__init__(
            hook_ctx.config,
            hook_ctx.base_url,
            hook_ctx.operation_id,
            hook_ctx.oauth2_scopes,
            hook_ctx.security_source,
        )


class SDKInitHook(ABC):
    @abstractmethod
    def sdk_init(self, config: "SDKConfiguration") -> "SDKConfiguration":
        pass


class BeforeRequestHook(ABC):
    @abstractmethod
    def before_request(
        self, hook_ctx: BeforeRequestContext, request: httpx.Request
    ) -> Union[httpx.Request, Exception]:
        pass


class AfterSuccessHook(ABC):
    @abstractmethod
    def after_success(
        self, hook_ctx: AfterSuccessContext, response: httpx.Response
    ) -> Union[httpx.Response, Exception]:
        pass


class AfterErrorHook(ABC):
    @abstractmethod
    def after_error(
        self,
        hook_ctx: AfterErrorContext,
        response: Optional[httpx.Response],
        error: Optional[Exception],
    ) -> Union[Tuple[Optional[httpx.Response], Optional[Exception]], Exception]:
        pass


class Hooks(ABC):
    @abstractmethod
    def register_sdk_init_hook(self, hook: SDKInitHook):
        pass

    @abstractmethod
    def register_before_request_hook(self, hook: BeforeRequestHook):
        pass

    @abstractmethod
    def register_after_success_hook(self, hook: AfterSuccessHook):
        pass

    @abstractmethod
    def register_after_error_hook(self, hook: AfterErrorHook):
        pass


@runtime_checkable
class HooksProvider(Protocol):
    """Protocol for dependency injection of SDK hooks.

    This protocol defines the interface that any hooks provider must implement
    to be used with the SDK. It allows for dependency injection of pre-configured
    hooks into SDK classes.

    The protocol is runtime_checkable, so isinstance() checks work at runtime.

    Example usage:
        >>> from anncsu.common.hooks import SDKHooks, HooksProvider
        >>> from anncsu.common.hooks.modi_hook import register_modi_hook
        >>> from anncsu.common.modi import ModIConfig
        >>>
        >>> # Create and configure hooks
        >>> hooks = SDKHooks()
        >>> config = ModIConfig(...)
        >>> register_modi_hook(hooks, config=config)
        >>>
        >>> # Verify it implements the protocol
        >>> assert isinstance(hooks, HooksProvider)
        >>>
        >>> # Pass to SDK via dependency injection
        >>> sdk = AnncsuCoordinate(security=..., hooks=hooks)
    """

    def register_sdk_init_hook(self, hook: SDKInitHook) -> None:
        """Register a hook to be called during SDK initialization."""
        ...

    def register_before_request_hook(self, hook: BeforeRequestHook) -> None:
        """Register a hook to be called before each HTTP request."""
        ...

    def register_after_success_hook(self, hook: AfterSuccessHook) -> None:
        """Register a hook to be called after a successful HTTP response."""
        ...

    def register_after_error_hook(self, hook: AfterErrorHook) -> None:
        """Register a hook to be called after an HTTP error."""
        ...

    def sdk_init(self, config: "SDKConfiguration") -> "SDKConfiguration":
        """Initialize SDK configuration through all registered init hooks."""
        ...

    def before_request(
        self, hook_ctx: BeforeRequestContext, request: httpx.Request
    ) -> httpx.Request:
        """Process request through all registered before-request hooks."""
        ...

    def after_success(
        self, hook_ctx: AfterSuccessContext, response: httpx.Response
    ) -> httpx.Response:
        """Process response through all registered after-success hooks."""
        ...

    def after_error(
        self,
        hook_ctx: AfterErrorContext,
        response: Optional[httpx.Response],
        error: Optional[Exception],
    ) -> Tuple[Optional[httpx.Response], Optional[Exception]]:
        """Process error through all registered after-error hooks."""
        ...
