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

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
from flexprice import models, utils
from flexprice._hooks import SDKHooks
from flexprice.types import OptionalNullable, UNSET
import httpx
import importlib
import sys
from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union, cast
import weakref

if TYPE_CHECKING:
    from flexprice.addons import Addons
    from flexprice.alerts import Alerts
    from flexprice.costs import Costs
    from flexprice.coupons import Coupons
    from flexprice.credit_grants import CreditGrants
    from flexprice.credit_notes import CreditNotes
    from flexprice.customers import Customers
    from flexprice.entitlements import Entitlements
    from flexprice.entity_integration_mappings import EntityIntegrationMappings
    from flexprice.events import Events
    from flexprice.features import Features
    from flexprice.groups import Groups
    from flexprice.integrations import Integrations
    from flexprice.invoices import Invoices
    from flexprice.payments import Payments
    from flexprice.plans import Plans
    from flexprice.price_units import PriceUnits
    from flexprice.prices import Prices
    from flexprice.rbac import Rbac
    from flexprice.scheduled_tasks import ScheduledTasks
    from flexprice.secrets import Secrets
    from flexprice.subscriptions import Subscriptions
    from flexprice.tasks import Tasks
    from flexprice.tax_associations import TaxAssociations
    from flexprice.tax_rates import TaxRates
    from flexprice.tenants import Tenants
    from flexprice.users import Users
    from flexprice.wallets import Wallets
    from flexprice.webhooks import Webhooks
    from flexprice.workflows import Workflows


class Flexprice(BaseSDK):
    r"""Flexprice API: Flexprice API Service"""

    addons: "Addons"
    entitlements: "Entitlements"
    alerts: "Alerts"
    costs: "Costs"
    coupons: "Coupons"
    credit_grants: "CreditGrants"
    credit_notes: "CreditNotes"
    customers: "Customers"
    wallets: "Wallets"
    invoices: "Invoices"
    entity_integration_mappings: "EntityIntegrationMappings"
    events: "Events"
    features: "Features"
    groups: "Groups"
    payments: "Payments"
    plans: "Plans"
    prices: "Prices"
    price_units: "PriceUnits"
    rbac: "Rbac"
    secrets: "Secrets"
    integrations: "Integrations"
    subscriptions: "Subscriptions"
    tasks: "Tasks"
    scheduled_tasks: "ScheduledTasks"
    tax_associations: "TaxAssociations"
    tax_rates: "TaxRates"
    tenants: "Tenants"
    users: "Users"
    webhooks: "Webhooks"
    workflows: "Workflows"
    _sub_sdk_map = {
        "addons": ("flexprice.addons", "Addons"),
        "entitlements": ("flexprice.entitlements", "Entitlements"),
        "alerts": ("flexprice.alerts", "Alerts"),
        "costs": ("flexprice.costs", "Costs"),
        "coupons": ("flexprice.coupons", "Coupons"),
        "credit_grants": ("flexprice.credit_grants", "CreditGrants"),
        "credit_notes": ("flexprice.credit_notes", "CreditNotes"),
        "customers": ("flexprice.customers", "Customers"),
        "wallets": ("flexprice.wallets", "Wallets"),
        "invoices": ("flexprice.invoices", "Invoices"),
        "entity_integration_mappings": (
            "flexprice.entity_integration_mappings",
            "EntityIntegrationMappings",
        ),
        "events": ("flexprice.events", "Events"),
        "features": ("flexprice.features", "Features"),
        "groups": ("flexprice.groups", "Groups"),
        "payments": ("flexprice.payments", "Payments"),
        "plans": ("flexprice.plans", "Plans"),
        "prices": ("flexprice.prices", "Prices"),
        "price_units": ("flexprice.price_units", "PriceUnits"),
        "rbac": ("flexprice.rbac", "Rbac"),
        "secrets": ("flexprice.secrets", "Secrets"),
        "integrations": ("flexprice.integrations", "Integrations"),
        "subscriptions": ("flexprice.subscriptions", "Subscriptions"),
        "tasks": ("flexprice.tasks", "Tasks"),
        "scheduled_tasks": ("flexprice.scheduled_tasks", "ScheduledTasks"),
        "tax_associations": ("flexprice.tax_associations", "TaxAssociations"),
        "tax_rates": ("flexprice.tax_rates", "TaxRates"),
        "tenants": ("flexprice.tenants", "Tenants"),
        "users": ("flexprice.users", "Users"),
        "webhooks": ("flexprice.webhooks", "Webhooks"),
        "workflows": ("flexprice.workflows", "Workflows"),
    }

    def __init__(
        self,
        api_key_auth: Union[str, Callable[[], str]],
        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 api_key_auth: The api_key_auth required for authentication
        :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."

        security: Any = None
        if callable(api_key_auth):
            # pylint: disable=unnecessary-lambda-assignment
            security = lambda: models.Security(api_key_auth=api_key_auth())
        else:
            security = models.Security(api_key_auth=api_key_auth)

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

    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
