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

import typing

from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.request_options import RequestOptions
from ...types.line_item_cursor_fields import LineItemCursorFields
from ...types.line_item_internal_request import LineItemInternalRequest
from ...types.line_item_pagination_response import LineItemPaginationResponse
from ...types.line_item_response import LineItemResponse
from ...types.line_items_replace_response import LineItemsReplaceResponse
from ...types.order_enum import OrderEnum
from .raw_client import AsyncRawLineItemsClient, RawLineItemsClient

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class LineItemsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawLineItemsClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawLineItemsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawLineItemsClient
        """
        return self._raw_client

    def get(
        self,
        payable_id: str,
        *,
        order: typing.Optional[OrderEnum] = None,
        limit: typing.Optional[int] = None,
        pagination_token: typing.Optional[str] = None,
        sort: typing.Optional[LineItemCursorFields] = None,
        was_created_by_user_id: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemPaginationResponse:
        """
        Get a list of all line items related to a specific payable.
        Related guide: [List all payable line items](https://docs.monite.com/accounts-payable/payables/line-items#list-all-line-items-of-a-payable)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        order : typing.Optional[OrderEnum]
            Sort order (ascending by default). Typically used together with the `sort` parameter.

        limit : typing.Optional[int]
            The number of items (0 .. 100) to return in a single page of the response. The response may contain fewer items if it is the last or only page.

        pagination_token : typing.Optional[str]
            A pagination token obtained from a previous call to this endpoint. Use it to get the next or previous page of results for your initial query. If `pagination_token` is specified, all other query parameters are ignored and inferred from the initial query.

            If not specified, the first page of results will be returned.

        sort : typing.Optional[LineItemCursorFields]
            The field to sort the results by. Typically used together with the `order` parameter.

        was_created_by_user_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemPaginationResponse
            Successful Response

        Examples
        --------
        from monite import Monite
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.get(payable_id='payable_id', )
        """
        _response = self._raw_client.get(
            payable_id,
            order=order,
            limit=limit,
            pagination_token=pagination_token,
            sort=sort,
            was_created_by_user_id=was_created_by_user_id,
            request_options=request_options,
        )
        return _response.data

    def create(
        self,
        payable_id: str,
        *,
        accounting_tax_rate_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        ledger_account_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        quantity: typing.Optional[float] = OMIT,
        tax: typing.Optional[int] = OMIT,
        unit: typing.Optional[str] = OMIT,
        unit_price: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemResponse:
        """
        Add a new line item to a specific payable.

        The `subtotal` and `total` fields of line items are automatically calculated based on the `unit_price`,
         `quantity`, and `tax` fields, therefore, are read-only and appear only in the response schema. The field
          `ledger_account_id` is required **only** for account integration, otherwise, it is optional.

        Related guide: [Add line items to a payable](https://docs.monite.com/accounts-payable/payables/line-items#add-line-items-to-a-payable)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        accounting_tax_rate_id : typing.Optional[str]
            ID of the tax rate reference used for accounting integration. May be used to override auto-picked tax rate reference in accounting platform in case of any platform-specific constraints.

        description : typing.Optional[str]
            Description of the product.

        ledger_account_id : typing.Optional[str]
            ID of the account record used to store bookkeeping entries for balance-sheet and income-statement transactions.

        name : typing.Optional[str]
            Name of the product.

        quantity : typing.Optional[float]
            The quantity of each of the goods, materials, or services listed in the payable.

        tax : typing.Optional[int]
            VAT rate in percent [minor units](https://docs.monite.com/references/currencies#minor-units). Example: 12.5% is 1250.

        unit : typing.Optional[str]
            The unit of the product

        unit_price : typing.Optional[int]
            The unit price of the product, in [minor units](https://docs.monite.com/references/currencies#minor-units). For example, $12.50 is represented as 1250.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import Monite
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.create(payable_id='payable_id', )
        """
        _response = self._raw_client.create(
            payable_id,
            accounting_tax_rate_id=accounting_tax_rate_id,
            description=description,
            ledger_account_id=ledger_account_id,
            name=name,
            quantity=quantity,
            tax=tax,
            unit=unit,
            unit_price=unit_price,
            request_options=request_options,
        )
        return _response.data

    def replace(
        self,
        payable_id: str,
        *,
        data: typing.Sequence[LineItemInternalRequest],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemsReplaceResponse:
        """
        Replaces the information of all line items of a specific payable.

        Related guide: [Replace all line items](https://docs.monite.com/accounts-payable/payables/line-items#replace-all-line-items)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        data : typing.Sequence[LineItemInternalRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemsReplaceResponse
            Successful Response

        Examples
        --------
        from monite import Monite
        from monite import LineItemInternalRequest
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.replace(payable_id='payable_id', data=[LineItemInternalRequest()], )
        """
        _response = self._raw_client.replace(payable_id, data=data, request_options=request_options)
        return _response.data

    def get_by_id(
        self, line_item_id: str, payable_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> LineItemResponse:
        """
        Get information about a specific line item with a given ID.

        Related guide: [Retrieve a line item](https://docs.monite.com/accounts-payable/payables/line-items#retrieve-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import Monite
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.get_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        """
        _response = self._raw_client.get_by_id(line_item_id, payable_id, request_options=request_options)
        return _response.data

    def delete_by_id(
        self, line_item_id: str, payable_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Delete the line item with the given ID.

        Related guide: [Remove a line item](https://docs.monite.com/accounts-payable/payables/line-items#remove-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        from monite import Monite
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.delete_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        """
        _response = self._raw_client.delete_by_id(line_item_id, payable_id, request_options=request_options)
        return _response.data

    def update_by_id(
        self,
        line_item_id: str,
        payable_id: str,
        *,
        accounting_tax_rate_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        ledger_account_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        quantity: typing.Optional[float] = OMIT,
        tax: typing.Optional[int] = OMIT,
        unit: typing.Optional[str] = OMIT,
        unit_price: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemResponse:
        """
        Edits the information of a specific line item.

        Related guide: [Update a line item](https://docs.monite.com/accounts-payable/payables/line-items#update-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        accounting_tax_rate_id : typing.Optional[str]
            ID of the tax rate reference used for accounting integration. May be used to override auto-picked tax rate reference in accounting platform in case of any platform-specific constraints.

        description : typing.Optional[str]
            Description of the product.

        ledger_account_id : typing.Optional[str]
            ID of the account record used to store bookkeeping entries for balance-sheet and income-statement transactions.

        name : typing.Optional[str]
            Name of the product.

        quantity : typing.Optional[float]
            The quantity of each of the goods, materials, or services listed in the payable.

        tax : typing.Optional[int]
            VAT rate in percent [minor units](https://docs.monite.com/references/currencies#minor-units). Example: 12.5% is 1250.

        unit : typing.Optional[str]
            The unit of the product

        unit_price : typing.Optional[int]
            The unit price of the product, in [minor units](https://docs.monite.com/references/currencies#minor-units). For example, $12.50 is represented as 1250.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import Monite
        client = Monite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        client.payables.line_items.update_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        """
        _response = self._raw_client.update_by_id(
            line_item_id,
            payable_id,
            accounting_tax_rate_id=accounting_tax_rate_id,
            description=description,
            ledger_account_id=ledger_account_id,
            name=name,
            quantity=quantity,
            tax=tax,
            unit=unit,
            unit_price=unit_price,
            request_options=request_options,
        )
        return _response.data


class AsyncLineItemsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawLineItemsClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawLineItemsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawLineItemsClient
        """
        return self._raw_client

    async def get(
        self,
        payable_id: str,
        *,
        order: typing.Optional[OrderEnum] = None,
        limit: typing.Optional[int] = None,
        pagination_token: typing.Optional[str] = None,
        sort: typing.Optional[LineItemCursorFields] = None,
        was_created_by_user_id: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemPaginationResponse:
        """
        Get a list of all line items related to a specific payable.
        Related guide: [List all payable line items](https://docs.monite.com/accounts-payable/payables/line-items#list-all-line-items-of-a-payable)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        order : typing.Optional[OrderEnum]
            Sort order (ascending by default). Typically used together with the `sort` parameter.

        limit : typing.Optional[int]
            The number of items (0 .. 100) to return in a single page of the response. The response may contain fewer items if it is the last or only page.

        pagination_token : typing.Optional[str]
            A pagination token obtained from a previous call to this endpoint. Use it to get the next or previous page of results for your initial query. If `pagination_token` is specified, all other query parameters are ignored and inferred from the initial query.

            If not specified, the first page of results will be returned.

        sort : typing.Optional[LineItemCursorFields]
            The field to sort the results by. Typically used together with the `order` parameter.

        was_created_by_user_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemPaginationResponse
            Successful Response

        Examples
        --------
        from monite import AsyncMonite
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.get(payable_id='payable_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.get(
            payable_id,
            order=order,
            limit=limit,
            pagination_token=pagination_token,
            sort=sort,
            was_created_by_user_id=was_created_by_user_id,
            request_options=request_options,
        )
        return _response.data

    async def create(
        self,
        payable_id: str,
        *,
        accounting_tax_rate_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        ledger_account_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        quantity: typing.Optional[float] = OMIT,
        tax: typing.Optional[int] = OMIT,
        unit: typing.Optional[str] = OMIT,
        unit_price: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemResponse:
        """
        Add a new line item to a specific payable.

        The `subtotal` and `total` fields of line items are automatically calculated based on the `unit_price`,
         `quantity`, and `tax` fields, therefore, are read-only and appear only in the response schema. The field
          `ledger_account_id` is required **only** for account integration, otherwise, it is optional.

        Related guide: [Add line items to a payable](https://docs.monite.com/accounts-payable/payables/line-items#add-line-items-to-a-payable)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        accounting_tax_rate_id : typing.Optional[str]
            ID of the tax rate reference used for accounting integration. May be used to override auto-picked tax rate reference in accounting platform in case of any platform-specific constraints.

        description : typing.Optional[str]
            Description of the product.

        ledger_account_id : typing.Optional[str]
            ID of the account record used to store bookkeeping entries for balance-sheet and income-statement transactions.

        name : typing.Optional[str]
            Name of the product.

        quantity : typing.Optional[float]
            The quantity of each of the goods, materials, or services listed in the payable.

        tax : typing.Optional[int]
            VAT rate in percent [minor units](https://docs.monite.com/references/currencies#minor-units). Example: 12.5% is 1250.

        unit : typing.Optional[str]
            The unit of the product

        unit_price : typing.Optional[int]
            The unit price of the product, in [minor units](https://docs.monite.com/references/currencies#minor-units). For example, $12.50 is represented as 1250.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import AsyncMonite
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.create(payable_id='payable_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.create(
            payable_id,
            accounting_tax_rate_id=accounting_tax_rate_id,
            description=description,
            ledger_account_id=ledger_account_id,
            name=name,
            quantity=quantity,
            tax=tax,
            unit=unit,
            unit_price=unit_price,
            request_options=request_options,
        )
        return _response.data

    async def replace(
        self,
        payable_id: str,
        *,
        data: typing.Sequence[LineItemInternalRequest],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemsReplaceResponse:
        """
        Replaces the information of all line items of a specific payable.

        Related guide: [Replace all line items](https://docs.monite.com/accounts-payable/payables/line-items#replace-all-line-items)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        payable_id : str

        data : typing.Sequence[LineItemInternalRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemsReplaceResponse
            Successful Response

        Examples
        --------
        from monite import AsyncMonite
        from monite import LineItemInternalRequest
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.replace(payable_id='payable_id', data=[LineItemInternalRequest()], )
        asyncio.run(main())
        """
        _response = await self._raw_client.replace(payable_id, data=data, request_options=request_options)
        return _response.data

    async def get_by_id(
        self, line_item_id: str, payable_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> LineItemResponse:
        """
        Get information about a specific line item with a given ID.

        Related guide: [Retrieve a line item](https://docs.monite.com/accounts-payable/payables/line-items#retrieve-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import AsyncMonite
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.get_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.get_by_id(line_item_id, payable_id, request_options=request_options)
        return _response.data

    async def delete_by_id(
        self, line_item_id: str, payable_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Delete the line item with the given ID.

        Related guide: [Remove a line item](https://docs.monite.com/accounts-payable/payables/line-items#remove-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        from monite import AsyncMonite
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.delete_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.delete_by_id(line_item_id, payable_id, request_options=request_options)
        return _response.data

    async def update_by_id(
        self,
        line_item_id: str,
        payable_id: str,
        *,
        accounting_tax_rate_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        ledger_account_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        quantity: typing.Optional[float] = OMIT,
        tax: typing.Optional[int] = OMIT,
        unit: typing.Optional[str] = OMIT,
        unit_price: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LineItemResponse:
        """
        Edits the information of a specific line item.

        Related guide: [Update a line item](https://docs.monite.com/accounts-payable/payables/line-items#update-a-line-item)

        See also:

        [Manage line items](https://docs.monite.com/accounts-payable/payables/line-items)

        [Collect payables](https://docs.monite.com/accounts-payable/payables/collect)

        Parameters
        ----------
        line_item_id : str

        payable_id : str

        accounting_tax_rate_id : typing.Optional[str]
            ID of the tax rate reference used for accounting integration. May be used to override auto-picked tax rate reference in accounting platform in case of any platform-specific constraints.

        description : typing.Optional[str]
            Description of the product.

        ledger_account_id : typing.Optional[str]
            ID of the account record used to store bookkeeping entries for balance-sheet and income-statement transactions.

        name : typing.Optional[str]
            Name of the product.

        quantity : typing.Optional[float]
            The quantity of each of the goods, materials, or services listed in the payable.

        tax : typing.Optional[int]
            VAT rate in percent [minor units](https://docs.monite.com/references/currencies#minor-units). Example: 12.5% is 1250.

        unit : typing.Optional[str]
            The unit of the product

        unit_price : typing.Optional[int]
            The unit price of the product, in [minor units](https://docs.monite.com/references/currencies#minor-units). For example, $12.50 is represented as 1250.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LineItemResponse
            Successful Response

        Examples
        --------
        from monite import AsyncMonite
        import asyncio
        client = AsyncMonite(monite_version="YOUR_MONITE_VERSION", monite_entity_id="YOUR_MONITE_ENTITY_ID", token="YOUR_TOKEN", )
        async def main() -> None:
            await client.payables.line_items.update_by_id(line_item_id='line_item_id', payable_id='payable_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.update_by_id(
            line_item_id,
            payable_id,
            accounting_tax_rate_id=accounting_tax_rate_id,
            description=description,
            ledger_account_id=ledger_account_id,
            name=name,
            quantity=quantity,
            tax=tax,
            unit=unit,
            unit_price=unit_price,
            request_options=request_options,
        )
        return _response.data
