"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
# @generated-id: 1ca5a15b9874

from .basesdk import BaseSDK
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
from .sdkconfiguration import SDKConfiguration
from .utils.logger import Logger, get_default_logger
from .utils.retries import RetryConfig
import httpx
import importlib
from mollie import models, utils
from mollie._hooks import SDKHooks
from mollie.types import OptionalNullable, UNSET
import sys
from typing import Callable, Dict, Optional, TYPE_CHECKING, Union, cast
import weakref

if TYPE_CHECKING:
    from mollie.balance_transfers import BalanceTransfers
    from mollie.balances import Balances
    from mollie.capabilities import Capabilities
    from mollie.captures import Captures
    from mollie.chargebacks_sdk import ChargebacksSDK
    from mollie.client_links import ClientLinks
    from mollie.clients import Clients
    from mollie.customers import Customers
    from mollie.delayed_routing import DelayedRouting
    from mollie.invoices import Invoices
    from mollie.mandates import Mandates
    from mollie.methods import Methods
    from mollie.onboarding import Onboarding
    from mollie.organizations import Organizations
    from mollie.payment_links import PaymentLinks
    from mollie.payments_sdk import PaymentsSDK
    from mollie.permissions import Permissions
    from mollie.profiles import Profiles
    from mollie.refunds_sdk import RefundsSDK
    from mollie.sales_invoices import SalesInvoices
    from mollie.sessions import Sessions
    from mollie.settlements import Settlements
    from mollie.subscriptions import Subscriptions
    from mollie.terminals import Terminals
    from mollie.wallets import Wallets
    from mollie.webhook_events import WebhookEvents
    from mollie.webhooks import Webhooks


class ClientSDK(BaseSDK):
    balances: "Balances"
    settlements: "Settlements"
    invoices: "Invoices"
    permissions: "Permissions"
    organizations: "Organizations"
    profiles: "Profiles"
    onboarding: "Onboarding"
    capabilities: "Capabilities"
    clients: "Clients"
    client_links: "ClientLinks"
    webhooks: "Webhooks"
    webhook_events: "WebhookEvents"
    balance_transfers: "BalanceTransfers"
    payments: "PaymentsSDK"
    sessions: "Sessions"
    methods: "Methods"
    refunds: "RefundsSDK"
    chargebacks: "ChargebacksSDK"
    captures: "Captures"
    wallets: "Wallets"
    payment_links: "PaymentLinks"
    terminals: "Terminals"
    delayed_routing: "DelayedRouting"
    customers: "Customers"
    mandates: "Mandates"
    subscriptions: "Subscriptions"
    sales_invoices: "SalesInvoices"
    _sub_sdk_map = {
        "balances": ("mollie.balances", "Balances"),
        "settlements": ("mollie.settlements", "Settlements"),
        "invoices": ("mollie.invoices", "Invoices"),
        "permissions": ("mollie.permissions", "Permissions"),
        "organizations": ("mollie.organizations", "Organizations"),
        "profiles": ("mollie.profiles", "Profiles"),
        "onboarding": ("mollie.onboarding", "Onboarding"),
        "capabilities": ("mollie.capabilities", "Capabilities"),
        "clients": ("mollie.clients", "Clients"),
        "client_links": ("mollie.client_links", "ClientLinks"),
        "webhooks": ("mollie.webhooks", "Webhooks"),
        "webhook_events": ("mollie.webhook_events", "WebhookEvents"),
        "balance_transfers": ("mollie.balance_transfers", "BalanceTransfers"),
        "payments": ("mollie.payments_sdk", "PaymentsSDK"),
        "sessions": ("mollie.sessions", "Sessions"),
        "methods": ("mollie.methods", "Methods"),
        "refunds": ("mollie.refunds_sdk", "RefundsSDK"),
        "chargebacks": ("mollie.chargebacks_sdk", "ChargebacksSDK"),
        "captures": ("mollie.captures", "Captures"),
        "wallets": ("mollie.wallets", "Wallets"),
        "payment_links": ("mollie.payment_links", "PaymentLinks"),
        "terminals": ("mollie.terminals", "Terminals"),
        "delayed_routing": ("mollie.delayed_routing", "DelayedRouting"),
        "customers": ("mollie.customers", "Customers"),
        "mandates": ("mollie.mandates", "Mandates"),
        "subscriptions": ("mollie.subscriptions", "Subscriptions"),
        "sales_invoices": ("mollie.sales_invoices", "SalesInvoices"),
    }

    def __init__(
        self,
        security: Optional[
            Union[models.Security, Callable[[], models.Security]]
        ] = None,
        profile_id: Optional[str] = None,
        testmode: Optional[bool] = None,
        custom_user_agent: Optional[str] = None,
        server_idx: Optional[int] = None,
        url_params: Optional[Dict[str, str]] = None,
        server_url: Optional[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,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param security: The security details required for authentication
        :param profile_id: Configures the profile_id parameter for all supported operations
        :param testmode: Configures the testmode parameter for all supported operations
        :param custom_user_agent: Configures the custom_user_agent parameter for all supported operations
        :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
        """
        client_supplied = True
        if client is None:
            client = httpx.Client(follow_redirects=True)
            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(follow_redirects=True)
            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)

        _globals = models.internal.Globals(
            profile_id=utils.get_global_from_env(profile_id, "CLIENT_PROFILE_ID", str),
            testmode=utils.get_global_from_env(testmode, "CLIENT_TESTMODE", bool),
            custom_user_agent=utils.get_global_from_env(
                custom_user_agent, "CLIENT_CUSTOM_USER_AGENT", str
            ),
        )

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

        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,
        )

        if not self.sdk_configuration.can_have_global_fields() and self.sdk_configuration.has_global_fields():
            raise AttributeError(
                "Global fields like testmode and profileId can only be set when using an Access or oAuth Key."
            )

    def dynamic_import(self, modname, retries=3):
        for attempt in range(retries):
            try:
                return importlib.import_module(modname)
            except KeyError:
                # Clear any half-initialized module and retry
                sys.modules.pop(modname, None)
                if attempt == retries - 1:
                    break
        raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")

    def __getattr__(self, name: str):
        if name in self._sub_sdk_map:
            module_path, class_name = self._sub_sdk_map[name]
            try:
                module = self.dynamic_import(module_path)
                klass = getattr(module, class_name)
                instance = klass(self.sdk_configuration, parent_ref=self)
                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
