"""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 codat_bankfeeds import utils
from codat_bankfeeds._hooks import SDKHooks
from codat_bankfeeds.account_mapping import AccountMapping
from codat_bankfeeds.bank_accounts import BankAccounts
from codat_bankfeeds.companies import Companies
from codat_bankfeeds.company_information import CompanyInformation
from codat_bankfeeds.configuration import Configuration
from codat_bankfeeds.connections import Connections
from codat_bankfeeds.models import shared
from codat_bankfeeds.source_accounts import SourceAccounts
from codat_bankfeeds.sync import Sync
from codat_bankfeeds.transactions import Transactions
from codat_bankfeeds.types import OptionalNullable, UNSET
import httpx
from typing import Callable, Dict, Optional, Union, cast
import weakref


class CodatBankFeeds(BaseSDK):
    r"""Bank Feeds API: Bank Feeds API enables your SMB users to set up bank feeds from accounts in your application to supported accounting software.

    A bank feed is a connection between a source bank account in your application and a target bank account in a supported accounting software.

    [Explore product](https://docs.codat.io/bank-feeds-api/overview) | [See OpenAPI spec](https://github.com/codatio/oas)

    ---
    <!-- Start Codat Tags Table -->
    ## Endpoints

    | Endpoints | Description |
    | :- |:- |
    | Companies | Create and manage your SMB users' companies. |
    | Connections | Create new and manage existing data connections for a company. |
    | Source accounts | Provide and manage lists of source bank accounts. |
    | Account mapping | Extra functionality for building an account management UI. |
    | Company information | Get detailed information about a company from the underlying platform. |
    | Transactions | Create new bank account transactions for a company's connections, and see previous operations. |
    <!-- End Codat Tags Table -->
    """

    companies: Companies
    r"""Create and manage your SMB users' companies."""
    connections: Connections
    r"""Create new and manage existing data connections for a company."""
    account_mapping: AccountMapping
    r"""Extra functionality for building an account management UI."""
    company_information: CompanyInformation
    r"""Get detailed information about a company from the underlying accounting software."""
    source_accounts: SourceAccounts
    r"""Provide and manage lists of source bank accounts."""
    bank_accounts: BankAccounts
    r"""Access bank accounts in an SMBs accounting software."""
    transactions: Transactions
    r"""Create new bank account transactions for a company's connections, and see previous operations."""
    configuration: Configuration
    r"""Configure bank feeds for a company."""
    sync: Sync
    r"""Monitor the status of data syncs."""

    def __init__(
        self,
        security: Union[shared.Security, Callable[[], shared.Security]],
        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,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param security: The security details 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
        """
        if client is None:
            client = httpx.Client()

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

        if async_client is None:
            async_client = httpx.AsyncClient()

        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,
                async_client=async_client,
                security=security,
                server_url=server_url,
                server_idx=server_idx,
                retry_config=retry_config,
                timeout_ms=timeout_ms,
                debug_logger=debug_logger,
            ),
        )

        hooks = SDKHooks()

        current_server_url, *_ = self.sdk_configuration.get_server_details()
        server_url, self.sdk_configuration.client = hooks.sdk_init(
            current_server_url, self.sdk_configuration.client
        )
        if current_server_url != server_url:
            self.sdk_configuration.server_url = server_url

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

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

        self._init_sdks()

    def _init_sdks(self):
        self.companies = Companies(self.sdk_configuration)
        self.connections = Connections(self.sdk_configuration)
        self.account_mapping = AccountMapping(self.sdk_configuration)
        self.company_information = CompanyInformation(self.sdk_configuration)
        self.source_accounts = SourceAccounts(self.sdk_configuration)
        self.bank_accounts = BankAccounts(self.sdk_configuration)
        self.transactions = Transactions(self.sdk_configuration)
        self.configuration = Configuration(self.sdk_configuration)
        self.sync = Sync(self.sdk_configuration)

    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:
            self.sdk_configuration.client.close()

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