# This file was auto-generated by Fern from our API Definition.

from __future__ import annotations

import typing

import httpx
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .environment import payabliEnvironment

if typing.TYPE_CHECKING:
    from .bill.client import AsyncBillClient, BillClient
    from .boarding.client import AsyncBoardingClient, BoardingClient
    from .charge_backs.client import AsyncChargeBacksClient, ChargeBacksClient
    from .check_capture.client import AsyncCheckCaptureClient, CheckCaptureClient
    from .cloud.client import AsyncCloudClient, CloudClient
    from .customer.client import AsyncCustomerClient, CustomerClient
    from .export.client import AsyncExportClient, ExportClient
    from .hosted_payment_pages.client import AsyncHostedPaymentPagesClient, HostedPaymentPagesClient
    from .import_.client import AsyncImportClient, ImportClient
    from .invoice.client import AsyncInvoiceClient, InvoiceClient
    from .line_item.client import AsyncLineItemClient, LineItemClient
    from .money_in.client import AsyncMoneyInClient, MoneyInClient
    from .money_out.client import AsyncMoneyOutClient, MoneyOutClient
    from .notification.client import AsyncNotificationClient, NotificationClient
    from .notificationlogs.client import AsyncNotificationlogsClient, NotificationlogsClient
    from .ocr.client import AsyncOcrClient, OcrClient
    from .organization.client import AsyncOrganizationClient, OrganizationClient
    from .payment_link.client import AsyncPaymentLinkClient, PaymentLinkClient
    from .payment_method_domain.client import AsyncPaymentMethodDomainClient, PaymentMethodDomainClient
    from .paypoint.client import AsyncPaypointClient, PaypointClient
    from .query.client import AsyncQueryClient, QueryClient
    from .statistic.client import AsyncStatisticClient, StatisticClient
    from .subscription.client import AsyncSubscriptionClient, SubscriptionClient
    from .templates.client import AsyncTemplatesClient, TemplatesClient
    from .token_storage.client import AsyncTokenStorageClient, TokenStorageClient
    from .user.client import AsyncUserClient, UserClient
    from .vendor.client import AsyncVendorClient, VendorClient
    from .wallet.client import AsyncWalletClient, WalletClient


class payabli:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.

    Parameters
    ----------
    base_url : typing.Optional[str]
        The base url to use for requests from the client.

    environment : payabliEnvironment
        The environment to use for requests from the client. from .environment import payabliEnvironment



        Defaults to payabliEnvironment.SANDBOX



    api_key : str
    headers : typing.Optional[typing.Dict[str, str]]
        Additional headers to send with every request.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.Client]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    Examples
    --------
    from payabli import payabli

    client = payabli(
        api_key="YOUR_API_KEY",
    )
    """

    def __init__(
        self,
        *,
        base_url: typing.Optional[str] = None,
        environment: payabliEnvironment = payabliEnvironment.SANDBOX,
        api_key: str,
        headers: typing.Optional[typing.Dict[str, str]] = None,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.Client] = None,
    ):
        _defaulted_timeout = (
            timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
        )
        self._client_wrapper = SyncClientWrapper(
            base_url=_get_base_url(base_url=base_url, environment=environment),
            api_key=api_key,
            headers=headers,
            httpx_client=httpx_client
            if httpx_client is not None
            else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
            if follow_redirects is not None
            else httpx.Client(timeout=_defaulted_timeout),
            timeout=_defaulted_timeout,
        )
        self._bill: typing.Optional[BillClient] = None
        self._boarding: typing.Optional[BoardingClient] = None
        self._charge_backs: typing.Optional[ChargeBacksClient] = None
        self._check_capture: typing.Optional[CheckCaptureClient] = None
        self._cloud: typing.Optional[CloudClient] = None
        self._customer: typing.Optional[CustomerClient] = None
        self._export: typing.Optional[ExportClient] = None
        self._hosted_payment_pages: typing.Optional[HostedPaymentPagesClient] = None
        self._import_: typing.Optional[ImportClient] = None
        self._invoice: typing.Optional[InvoiceClient] = None
        self._line_item: typing.Optional[LineItemClient] = None
        self._money_in: typing.Optional[MoneyInClient] = None
        self._money_out: typing.Optional[MoneyOutClient] = None
        self._notification: typing.Optional[NotificationClient] = None
        self._notificationlogs: typing.Optional[NotificationlogsClient] = None
        self._ocr: typing.Optional[OcrClient] = None
        self._organization: typing.Optional[OrganizationClient] = None
        self._payment_link: typing.Optional[PaymentLinkClient] = None
        self._payment_method_domain: typing.Optional[PaymentMethodDomainClient] = None
        self._paypoint: typing.Optional[PaypointClient] = None
        self._query: typing.Optional[QueryClient] = None
        self._statistic: typing.Optional[StatisticClient] = None
        self._subscription: typing.Optional[SubscriptionClient] = None
        self._templates: typing.Optional[TemplatesClient] = None
        self._token_storage: typing.Optional[TokenStorageClient] = None
        self._user: typing.Optional[UserClient] = None
        self._vendor: typing.Optional[VendorClient] = None
        self._wallet: typing.Optional[WalletClient] = None

    @property
    def bill(self):
        if self._bill is None:
            from .bill.client import BillClient  # noqa: E402

            self._bill = BillClient(client_wrapper=self._client_wrapper)
        return self._bill

    @property
    def boarding(self):
        if self._boarding is None:
            from .boarding.client import BoardingClient  # noqa: E402

            self._boarding = BoardingClient(client_wrapper=self._client_wrapper)
        return self._boarding

    @property
    def charge_backs(self):
        if self._charge_backs is None:
            from .charge_backs.client import ChargeBacksClient  # noqa: E402

            self._charge_backs = ChargeBacksClient(client_wrapper=self._client_wrapper)
        return self._charge_backs

    @property
    def check_capture(self):
        if self._check_capture is None:
            from .check_capture.client import CheckCaptureClient  # noqa: E402

            self._check_capture = CheckCaptureClient(client_wrapper=self._client_wrapper)
        return self._check_capture

    @property
    def cloud(self):
        if self._cloud is None:
            from .cloud.client import CloudClient  # noqa: E402

            self._cloud = CloudClient(client_wrapper=self._client_wrapper)
        return self._cloud

    @property
    def customer(self):
        if self._customer is None:
            from .customer.client import CustomerClient  # noqa: E402

            self._customer = CustomerClient(client_wrapper=self._client_wrapper)
        return self._customer

    @property
    def export(self):
        if self._export is None:
            from .export.client import ExportClient  # noqa: E402

            self._export = ExportClient(client_wrapper=self._client_wrapper)
        return self._export

    @property
    def hosted_payment_pages(self):
        if self._hosted_payment_pages is None:
            from .hosted_payment_pages.client import HostedPaymentPagesClient  # noqa: E402

            self._hosted_payment_pages = HostedPaymentPagesClient(client_wrapper=self._client_wrapper)
        return self._hosted_payment_pages

    @property
    def import_(self):
        if self._import_ is None:
            from .import_.client import ImportClient  # noqa: E402

            self._import_ = ImportClient(client_wrapper=self._client_wrapper)
        return self._import_

    @property
    def invoice(self):
        if self._invoice is None:
            from .invoice.client import InvoiceClient  # noqa: E402

            self._invoice = InvoiceClient(client_wrapper=self._client_wrapper)
        return self._invoice

    @property
    def line_item(self):
        if self._line_item is None:
            from .line_item.client import LineItemClient  # noqa: E402

            self._line_item = LineItemClient(client_wrapper=self._client_wrapper)
        return self._line_item

    @property
    def money_in(self):
        if self._money_in is None:
            from .money_in.client import MoneyInClient  # noqa: E402

            self._money_in = MoneyInClient(client_wrapper=self._client_wrapper)
        return self._money_in

    @property
    def money_out(self):
        if self._money_out is None:
            from .money_out.client import MoneyOutClient  # noqa: E402

            self._money_out = MoneyOutClient(client_wrapper=self._client_wrapper)
        return self._money_out

    @property
    def notification(self):
        if self._notification is None:
            from .notification.client import NotificationClient  # noqa: E402

            self._notification = NotificationClient(client_wrapper=self._client_wrapper)
        return self._notification

    @property
    def notificationlogs(self):
        if self._notificationlogs is None:
            from .notificationlogs.client import NotificationlogsClient  # noqa: E402

            self._notificationlogs = NotificationlogsClient(client_wrapper=self._client_wrapper)
        return self._notificationlogs

    @property
    def ocr(self):
        if self._ocr is None:
            from .ocr.client import OcrClient  # noqa: E402

            self._ocr = OcrClient(client_wrapper=self._client_wrapper)
        return self._ocr

    @property
    def organization(self):
        if self._organization is None:
            from .organization.client import OrganizationClient  # noqa: E402

            self._organization = OrganizationClient(client_wrapper=self._client_wrapper)
        return self._organization

    @property
    def payment_link(self):
        if self._payment_link is None:
            from .payment_link.client import PaymentLinkClient  # noqa: E402

            self._payment_link = PaymentLinkClient(client_wrapper=self._client_wrapper)
        return self._payment_link

    @property
    def payment_method_domain(self):
        if self._payment_method_domain is None:
            from .payment_method_domain.client import PaymentMethodDomainClient  # noqa: E402

            self._payment_method_domain = PaymentMethodDomainClient(client_wrapper=self._client_wrapper)
        return self._payment_method_domain

    @property
    def paypoint(self):
        if self._paypoint is None:
            from .paypoint.client import PaypointClient  # noqa: E402

            self._paypoint = PaypointClient(client_wrapper=self._client_wrapper)
        return self._paypoint

    @property
    def query(self):
        if self._query is None:
            from .query.client import QueryClient  # noqa: E402

            self._query = QueryClient(client_wrapper=self._client_wrapper)
        return self._query

    @property
    def statistic(self):
        if self._statistic is None:
            from .statistic.client import StatisticClient  # noqa: E402

            self._statistic = StatisticClient(client_wrapper=self._client_wrapper)
        return self._statistic

    @property
    def subscription(self):
        if self._subscription is None:
            from .subscription.client import SubscriptionClient  # noqa: E402

            self._subscription = SubscriptionClient(client_wrapper=self._client_wrapper)
        return self._subscription

    @property
    def templates(self):
        if self._templates is None:
            from .templates.client import TemplatesClient  # noqa: E402

            self._templates = TemplatesClient(client_wrapper=self._client_wrapper)
        return self._templates

    @property
    def token_storage(self):
        if self._token_storage is None:
            from .token_storage.client import TokenStorageClient  # noqa: E402

            self._token_storage = TokenStorageClient(client_wrapper=self._client_wrapper)
        return self._token_storage

    @property
    def user(self):
        if self._user is None:
            from .user.client import UserClient  # noqa: E402

            self._user = UserClient(client_wrapper=self._client_wrapper)
        return self._user

    @property
    def vendor(self):
        if self._vendor is None:
            from .vendor.client import VendorClient  # noqa: E402

            self._vendor = VendorClient(client_wrapper=self._client_wrapper)
        return self._vendor

    @property
    def wallet(self):
        if self._wallet is None:
            from .wallet.client import WalletClient  # noqa: E402

            self._wallet = WalletClient(client_wrapper=self._client_wrapper)
        return self._wallet


class Asyncpayabli:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.

    Parameters
    ----------
    base_url : typing.Optional[str]
        The base url to use for requests from the client.

    environment : payabliEnvironment
        The environment to use for requests from the client. from .environment import payabliEnvironment



        Defaults to payabliEnvironment.SANDBOX



    api_key : str
    headers : typing.Optional[typing.Dict[str, str]]
        Additional headers to send with every request.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.AsyncClient]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    Examples
    --------
    from payabli import Asyncpayabli

    client = Asyncpayabli(
        api_key="YOUR_API_KEY",
    )
    """

    def __init__(
        self,
        *,
        base_url: typing.Optional[str] = None,
        environment: payabliEnvironment = payabliEnvironment.SANDBOX,
        api_key: str,
        headers: typing.Optional[typing.Dict[str, str]] = None,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
    ):
        _defaulted_timeout = (
            timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
        )
        self._client_wrapper = AsyncClientWrapper(
            base_url=_get_base_url(base_url=base_url, environment=environment),
            api_key=api_key,
            headers=headers,
            httpx_client=httpx_client
            if httpx_client is not None
            else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
            if follow_redirects is not None
            else httpx.AsyncClient(timeout=_defaulted_timeout),
            timeout=_defaulted_timeout,
        )
        self._bill: typing.Optional[AsyncBillClient] = None
        self._boarding: typing.Optional[AsyncBoardingClient] = None
        self._charge_backs: typing.Optional[AsyncChargeBacksClient] = None
        self._check_capture: typing.Optional[AsyncCheckCaptureClient] = None
        self._cloud: typing.Optional[AsyncCloudClient] = None
        self._customer: typing.Optional[AsyncCustomerClient] = None
        self._export: typing.Optional[AsyncExportClient] = None
        self._hosted_payment_pages: typing.Optional[AsyncHostedPaymentPagesClient] = None
        self._import_: typing.Optional[AsyncImportClient] = None
        self._invoice: typing.Optional[AsyncInvoiceClient] = None
        self._line_item: typing.Optional[AsyncLineItemClient] = None
        self._money_in: typing.Optional[AsyncMoneyInClient] = None
        self._money_out: typing.Optional[AsyncMoneyOutClient] = None
        self._notification: typing.Optional[AsyncNotificationClient] = None
        self._notificationlogs: typing.Optional[AsyncNotificationlogsClient] = None
        self._ocr: typing.Optional[AsyncOcrClient] = None
        self._organization: typing.Optional[AsyncOrganizationClient] = None
        self._payment_link: typing.Optional[AsyncPaymentLinkClient] = None
        self._payment_method_domain: typing.Optional[AsyncPaymentMethodDomainClient] = None
        self._paypoint: typing.Optional[AsyncPaypointClient] = None
        self._query: typing.Optional[AsyncQueryClient] = None
        self._statistic: typing.Optional[AsyncStatisticClient] = None
        self._subscription: typing.Optional[AsyncSubscriptionClient] = None
        self._templates: typing.Optional[AsyncTemplatesClient] = None
        self._token_storage: typing.Optional[AsyncTokenStorageClient] = None
        self._user: typing.Optional[AsyncUserClient] = None
        self._vendor: typing.Optional[AsyncVendorClient] = None
        self._wallet: typing.Optional[AsyncWalletClient] = None

    @property
    def bill(self):
        if self._bill is None:
            from .bill.client import AsyncBillClient  # noqa: E402

            self._bill = AsyncBillClient(client_wrapper=self._client_wrapper)
        return self._bill

    @property
    def boarding(self):
        if self._boarding is None:
            from .boarding.client import AsyncBoardingClient  # noqa: E402

            self._boarding = AsyncBoardingClient(client_wrapper=self._client_wrapper)
        return self._boarding

    @property
    def charge_backs(self):
        if self._charge_backs is None:
            from .charge_backs.client import AsyncChargeBacksClient  # noqa: E402

            self._charge_backs = AsyncChargeBacksClient(client_wrapper=self._client_wrapper)
        return self._charge_backs

    @property
    def check_capture(self):
        if self._check_capture is None:
            from .check_capture.client import AsyncCheckCaptureClient  # noqa: E402

            self._check_capture = AsyncCheckCaptureClient(client_wrapper=self._client_wrapper)
        return self._check_capture

    @property
    def cloud(self):
        if self._cloud is None:
            from .cloud.client import AsyncCloudClient  # noqa: E402

            self._cloud = AsyncCloudClient(client_wrapper=self._client_wrapper)
        return self._cloud

    @property
    def customer(self):
        if self._customer is None:
            from .customer.client import AsyncCustomerClient  # noqa: E402

            self._customer = AsyncCustomerClient(client_wrapper=self._client_wrapper)
        return self._customer

    @property
    def export(self):
        if self._export is None:
            from .export.client import AsyncExportClient  # noqa: E402

            self._export = AsyncExportClient(client_wrapper=self._client_wrapper)
        return self._export

    @property
    def hosted_payment_pages(self):
        if self._hosted_payment_pages is None:
            from .hosted_payment_pages.client import AsyncHostedPaymentPagesClient  # noqa: E402

            self._hosted_payment_pages = AsyncHostedPaymentPagesClient(client_wrapper=self._client_wrapper)
        return self._hosted_payment_pages

    @property
    def import_(self):
        if self._import_ is None:
            from .import_.client import AsyncImportClient  # noqa: E402

            self._import_ = AsyncImportClient(client_wrapper=self._client_wrapper)
        return self._import_

    @property
    def invoice(self):
        if self._invoice is None:
            from .invoice.client import AsyncInvoiceClient  # noqa: E402

            self._invoice = AsyncInvoiceClient(client_wrapper=self._client_wrapper)
        return self._invoice

    @property
    def line_item(self):
        if self._line_item is None:
            from .line_item.client import AsyncLineItemClient  # noqa: E402

            self._line_item = AsyncLineItemClient(client_wrapper=self._client_wrapper)
        return self._line_item

    @property
    def money_in(self):
        if self._money_in is None:
            from .money_in.client import AsyncMoneyInClient  # noqa: E402

            self._money_in = AsyncMoneyInClient(client_wrapper=self._client_wrapper)
        return self._money_in

    @property
    def money_out(self):
        if self._money_out is None:
            from .money_out.client import AsyncMoneyOutClient  # noqa: E402

            self._money_out = AsyncMoneyOutClient(client_wrapper=self._client_wrapper)
        return self._money_out

    @property
    def notification(self):
        if self._notification is None:
            from .notification.client import AsyncNotificationClient  # noqa: E402

            self._notification = AsyncNotificationClient(client_wrapper=self._client_wrapper)
        return self._notification

    @property
    def notificationlogs(self):
        if self._notificationlogs is None:
            from .notificationlogs.client import AsyncNotificationlogsClient  # noqa: E402

            self._notificationlogs = AsyncNotificationlogsClient(client_wrapper=self._client_wrapper)
        return self._notificationlogs

    @property
    def ocr(self):
        if self._ocr is None:
            from .ocr.client import AsyncOcrClient  # noqa: E402

            self._ocr = AsyncOcrClient(client_wrapper=self._client_wrapper)
        return self._ocr

    @property
    def organization(self):
        if self._organization is None:
            from .organization.client import AsyncOrganizationClient  # noqa: E402

            self._organization = AsyncOrganizationClient(client_wrapper=self._client_wrapper)
        return self._organization

    @property
    def payment_link(self):
        if self._payment_link is None:
            from .payment_link.client import AsyncPaymentLinkClient  # noqa: E402

            self._payment_link = AsyncPaymentLinkClient(client_wrapper=self._client_wrapper)
        return self._payment_link

    @property
    def payment_method_domain(self):
        if self._payment_method_domain is None:
            from .payment_method_domain.client import AsyncPaymentMethodDomainClient  # noqa: E402

            self._payment_method_domain = AsyncPaymentMethodDomainClient(client_wrapper=self._client_wrapper)
        return self._payment_method_domain

    @property
    def paypoint(self):
        if self._paypoint is None:
            from .paypoint.client import AsyncPaypointClient  # noqa: E402

            self._paypoint = AsyncPaypointClient(client_wrapper=self._client_wrapper)
        return self._paypoint

    @property
    def query(self):
        if self._query is None:
            from .query.client import AsyncQueryClient  # noqa: E402

            self._query = AsyncQueryClient(client_wrapper=self._client_wrapper)
        return self._query

    @property
    def statistic(self):
        if self._statistic is None:
            from .statistic.client import AsyncStatisticClient  # noqa: E402

            self._statistic = AsyncStatisticClient(client_wrapper=self._client_wrapper)
        return self._statistic

    @property
    def subscription(self):
        if self._subscription is None:
            from .subscription.client import AsyncSubscriptionClient  # noqa: E402

            self._subscription = AsyncSubscriptionClient(client_wrapper=self._client_wrapper)
        return self._subscription

    @property
    def templates(self):
        if self._templates is None:
            from .templates.client import AsyncTemplatesClient  # noqa: E402

            self._templates = AsyncTemplatesClient(client_wrapper=self._client_wrapper)
        return self._templates

    @property
    def token_storage(self):
        if self._token_storage is None:
            from .token_storage.client import AsyncTokenStorageClient  # noqa: E402

            self._token_storage = AsyncTokenStorageClient(client_wrapper=self._client_wrapper)
        return self._token_storage

    @property
    def user(self):
        if self._user is None:
            from .user.client import AsyncUserClient  # noqa: E402

            self._user = AsyncUserClient(client_wrapper=self._client_wrapper)
        return self._user

    @property
    def vendor(self):
        if self._vendor is None:
            from .vendor.client import AsyncVendorClient  # noqa: E402

            self._vendor = AsyncVendorClient(client_wrapper=self._client_wrapper)
        return self._vendor

    @property
    def wallet(self):
        if self._wallet is None:
            from .wallet.client import AsyncWalletClient  # noqa: E402

            self._wallet = AsyncWalletClient(client_wrapper=self._client_wrapper)
        return self._wallet


def _get_base_url(*, base_url: typing.Optional[str] = None, environment: payabliEnvironment) -> str:
    if base_url is not None:
        return base_url
    elif environment is not None:
        return environment.value
    else:
        raise Exception("Please pass in either base_url or environment to construct the client")
