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

import importlib
import weakref
from typing import TYPE_CHECKING, Dict, Optional, cast

import httpx

from anncsu.common.sdk import utils
from anncsu.common.hooks import SDKHooks
from anncsu.common.sdk import BaseSDK
from anncsu.common.sdk.httpclient import (
    AsyncHttpClient,
    ClientOwner,
    HttpClient,
    close_clients,
)
from anncsu.common.sdk.utils import Logger, RetryConfig, get_default_logger
from anncsu.common.sdk.types import UNSET, OptionalNullable

from .sdkconfiguration import SDKConfiguration

if TYPE_CHECKING:
    from anncsu.pa.jsonpost import JSONPost
    from anncsu.pa.pathparam import Pathparam
    from anncsu.pa.queryparam import Queryparam
    from anncsu.pa.status import Status


class Anncsu(BaseSDK):
    r"""ANNCSU REST API: API dei servizi REST di ANNCSU su PDND"""

    queryparam: "Queryparam"
    r"""Servizio con valori di input come parametro query in URI"""
    json_post: "JSONPost"
    r"""Servizio con valori di input in file JSON sottomesso POST"""
    pathparam: "Pathparam"
    r"""Servizio con valori di input come parametro path in URI"""
    status: "Status"
    _sub_sdk_map = {
        "queryparam": ("anncsu.pa.queryparam", "Queryparam"),
        "json_post": ("anncsu.pa.jsonpost", "JSONPost"),
        "pathparam": ("anncsu.pa.pathparam", "Pathparam"),
        "status": ("anncsu.pa.status", "Status"),
    }

    def __init__(
        self,
        server_idx: Optional[int] = None,
        server_url: Optional[str] = None,
        url_params: Optional[Dict[str, str]] = None,
        client: Optional[HttpClient] = None,
        async_client: Optional[AsyncHttpClient] = None,
        retry_config: OptionalNullable[RetryConfig] = UNSET,
        timeout_ms: Optional[int] = None,
        debug_logger: Optional[Logger] = None,
        security=None,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param server_idx: The index of the server to use for all methods
        :param server_url: The server URL to use for all methods
        :param url_params: Parameters to optionally template the server URL with
        :param client: The HTTP client to use for all synchronous methods
        :param async_client: The Async HTTP client to use for all asynchronous methods
        :param retry_config: The retry configuration to use for all supported methods
        :param timeout_ms: Optional request timeout applied to each operation in milliseconds
        :param security: Security configuration for authentication (e.g., Security object with bearer token)
        """
        client_supplied = True
        if client is None:
            client = httpx.Client()
            client_supplied = False

        assert issubclass(type(client), HttpClient), (
            "The provided client must implement the HttpClient protocol."
        )

        async_client_supplied = True
        if async_client is None:
            async_client = httpx.AsyncClient()
            async_client_supplied = False

        if debug_logger is None:
            debug_logger = get_default_logger()

        assert issubclass(type(async_client), AsyncHttpClient), (
            "The provided async_client must implement the AsyncHttpClient protocol."
        )

        if server_url is not None:
            if url_params is not None:
                server_url = utils.template_url(server_url, url_params)

        BaseSDK.__init__(
            self,
            SDKConfiguration(
                client=client,
                client_supplied=client_supplied,
                async_client=async_client,
                async_client_supplied=async_client_supplied,
                server_url=server_url,
                server_idx=server_idx,
                retry_config=retry_config,
                timeout_ms=timeout_ms,
                debug_logger=debug_logger,
                security=security,
            ),
        )

        hooks = SDKHooks()

        # pylint: disable=protected-access
        self.sdk_configuration.__dict__["_hooks"] = hooks

        self.sdk_configuration = hooks.sdk_init(self.sdk_configuration)

        weakref.finalize(
            self,
            close_clients,
            cast(ClientOwner, self.sdk_configuration),
            self.sdk_configuration.client,
            self.sdk_configuration.client_supplied,
            self.sdk_configuration.async_client,
            self.sdk_configuration.async_client_supplied,
        )

    def __getattr__(self, name: str):
        if name in self._sub_sdk_map:
            module_path, class_name = self._sub_sdk_map[name]
            try:
                module = importlib.import_module(module_path)
                klass = getattr(module, class_name)
                instance = klass(self.sdk_configuration)
                setattr(self, name, instance)
                return instance
            except ImportError as e:
                raise AttributeError(
                    f"Failed to import module {module_path} for attribute {name}: {e}"
                ) from e
            except AttributeError as e:
                raise AttributeError(
                    f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
                ) from e

        raise AttributeError(
            f"'{type(self).__name__}' object has no attribute '{name}'"
        )

    def __dir__(self):
        default_attrs = list(super().__dir__())
        lazy_attrs = list(self._sub_sdk_map.keys())
        return sorted(list(set(default_attrs + lazy_attrs)))

    def __enter__(self):
        return self

    async def __aenter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.client is not None
            and not self.sdk_configuration.client_supplied
        ):
            self.sdk_configuration.client.close()
        self.sdk_configuration.client = None

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.async_client is not None
            and not self.sdk_configuration.async_client_supplied
        ):
            await self.sdk_configuration.async_client.aclose()
        self.sdk_configuration.async_client = None
