# 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.item_commodity_code import ItemCommodityCode
from ..types.item_description import ItemDescription
from ..types.item_product_code import ItemProductCode
from ..types.item_product_name import ItemProductName
from ..types.item_unitof_measure import ItemUnitofMeasure
from ..types.line_item_query_record import LineItemQueryRecord
from ..types.payabli_api_response_6 import PayabliApiResponse6
from ..types.query_response_items import QueryResponseItems
from .raw_client import AsyncRawLineItemClient, RawLineItemClient
from .types.delete_item_response import DeleteItemResponse

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


class LineItemClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawLineItemClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        RawLineItemClient
        """
        return self._raw_client

    def add_item(
        self,
        entry: str,
        *,
        item_cost: float,
        item_qty: int,
        idempotency_key: typing.Optional[str] = None,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse6:
        """
        Adds products and services to an entrypoint's catalog. These are used as line items for invoicing and transactions. In the response, "responseData" displays the item's code.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        idempotency_key : typing.Optional[str]
            A unique ID you can include to prevent duplicating objects or transactions if a request is sent more than once. This key isn't generated in Payabli, you must generate it yourself.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        PayabliApiResponse6
            Success

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.line_item.add_item(
            entry="47cae3d74",
            item_product_code="M-DEPOSIT",
            item_product_name="Materials deposit",
            item_description="Deposit for materials",
            item_commodity_code="010",
            item_unit_of_measure="SqFt",
            item_cost=12.45,
            item_qty=1,
            item_mode=0,
        )
        """
        _response = self._raw_client.add_item(
            entry,
            item_cost=item_cost,
            item_qty=item_qty,
            idempotency_key=idempotency_key,
            item_categories=item_categories,
            item_commodity_code=item_commodity_code,
            item_description=item_description,
            item_mode=item_mode,
            item_product_code=item_product_code,
            item_product_name=item_product_name,
            item_unit_of_measure=item_unit_of_measure,
            request_options=request_options,
        )
        return _response.data

    def delete_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteItemResponse:
        """
        Deletes an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        DeleteItemResponse
            Success

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.line_item.delete_item(
            line_item_id=700,
        )
        """
        _response = self._raw_client.delete_item(line_item_id, request_options=request_options)
        return _response.data

    def get_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> LineItemQueryRecord:
        """
        Gets an item by ID.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        LineItemQueryRecord
            Success

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.line_item.get_item(
            line_item_id=700,
        )
        """
        _response = self._raw_client.get_item(line_item_id, request_options=request_options)
        return _response.data

    def list_line_items(
        self,
        entry: str,
        *,
        from_record: typing.Optional[int] = None,
        limit_record: typing.Optional[int] = None,
        parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
        sort_by: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> QueryResponseItems:
        """
        Retrieves a list of line items and their details from an entrypoint. Line items are also known as items, products, and services. Use filters to limit results.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        from_record : typing.Optional[int]
            The number of records to skip before starting to collect the result set.

        limit_record : typing.Optional[int]
            Max number of records to return for the query. Use `0` or negative value to return all records.

        parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]

            Collection of field names, conditions, and values used to filter the query
            <Info>
              **You must remove `parameters=` from the request before you send it, otherwise Payabli will ignore the filters.**

              Because of a technical limitation, you can't make a request that includes filters from the API console on this page. The response won't be filtered. Instead, copy the request, remove `parameters=` and run the request in a different client.

              For example:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?parameters=totalAmount(gt)=1000&limitRecord=20

              should become:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?totalAmount(gt)=1000&limitRecord=20

            </Info>
            See [Filters and Conditions Reference](/developers/developer-guides/pay-ops-reporting-engine-overview#filters-and-conditions-reference) for help.

            List of field names accepted:

              - `categories` (ct, nct)
              - `code` (ne, eq, ct, nct)
              - `commodityCode` (ne, eq, ct, nct)
              - `createdDate` (gt, ge, lt, le, eq, ne)
              - `description` (ne, eq, ct, nct)
              - `externalPaypointID` (ct, nct, ne, eq)
              - `mode` (eq, ne)
              - `name` (ne, eq, ct, nct)
              - `orgName` (ne, eq, ct, nct)
              - `paypointDba` (ne, eq, ct, nct)
              - `paypointId` (ne, eq)
              - `paypointLegal` (ne, eq, ct, nct)
              - `quantity` (gt, ge, lt, le, eq, ne)
              - `uom` (ne, eq, ct, nct)
              - `updatedDate` (gt, ge, lt, le, eq, ne)
              - `value` (gt, ge, lt, le, eq, ne)

            List of comparison accepted - enclosed between parentheses:

            - eq or empty => equal
            - gt => greater than
            - ge => greater or equal
            - lt => less than
            - le => less or equal
            - ne => not equal
            - ct => contains
            - nct => not contains
            - in => inside array separated by "|"
            - nin => not inside array separated by "|"

            List of parameters accepted:
            - limitRecord : max number of records for query (default="20", "0" or negative value for all)
            - fromRecord : initial record in query

            Example: name(ct)=john return all records with name containing john

        sort_by : typing.Optional[str]
            The field name to use for sorting results. Use `desc(field_name)` to sort descending by `field_name`, and use `asc(field_name)` to sort ascending by `field_name`.

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

        Returns
        -------
        QueryResponseItems
            Success

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.line_item.list_line_items(
            entry="8cfec329267",
            from_record=251,
            limit_record=0,
            sort_by="desc(field_name)",
        )
        """
        _response = self._raw_client.list_line_items(
            entry,
            from_record=from_record,
            limit_record=limit_record,
            parameters=parameters,
            sort_by=sort_by,
            request_options=request_options,
        )
        return _response.data

    def update_item(
        self,
        line_item_id: int,
        *,
        item_cost: float,
        item_qty: int,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse6:
        """
        Updates an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        PayabliApiResponse6
            Success

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.line_item.update_item(
            line_item_id=700,
            item_cost=12.45,
            item_qty=1,
        )
        """
        _response = self._raw_client.update_item(
            line_item_id,
            item_cost=item_cost,
            item_qty=item_qty,
            item_categories=item_categories,
            item_commodity_code=item_commodity_code,
            item_description=item_description,
            item_mode=item_mode,
            item_product_code=item_product_code,
            item_product_name=item_product_name,
            item_unit_of_measure=item_unit_of_measure,
            request_options=request_options,
        )
        return _response.data


class AsyncLineItemClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawLineItemClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        AsyncRawLineItemClient
        """
        return self._raw_client

    async def add_item(
        self,
        entry: str,
        *,
        item_cost: float,
        item_qty: int,
        idempotency_key: typing.Optional[str] = None,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse6:
        """
        Adds products and services to an entrypoint's catalog. These are used as line items for invoicing and transactions. In the response, "responseData" displays the item's code.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        idempotency_key : typing.Optional[str]
            A unique ID you can include to prevent duplicating objects or transactions if a request is sent more than once. This key isn't generated in Payabli, you must generate it yourself.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        PayabliApiResponse6
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.line_item.add_item(
                entry="47cae3d74",
                item_product_code="M-DEPOSIT",
                item_product_name="Materials deposit",
                item_description="Deposit for materials",
                item_commodity_code="010",
                item_unit_of_measure="SqFt",
                item_cost=12.45,
                item_qty=1,
                item_mode=0,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.add_item(
            entry,
            item_cost=item_cost,
            item_qty=item_qty,
            idempotency_key=idempotency_key,
            item_categories=item_categories,
            item_commodity_code=item_commodity_code,
            item_description=item_description,
            item_mode=item_mode,
            item_product_code=item_product_code,
            item_product_name=item_product_name,
            item_unit_of_measure=item_unit_of_measure,
            request_options=request_options,
        )
        return _response.data

    async def delete_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteItemResponse:
        """
        Deletes an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        DeleteItemResponse
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.line_item.delete_item(
                line_item_id=700,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete_item(line_item_id, request_options=request_options)
        return _response.data

    async def get_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> LineItemQueryRecord:
        """
        Gets an item by ID.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        LineItemQueryRecord
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.line_item.get_item(
                line_item_id=700,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_item(line_item_id, request_options=request_options)
        return _response.data

    async def list_line_items(
        self,
        entry: str,
        *,
        from_record: typing.Optional[int] = None,
        limit_record: typing.Optional[int] = None,
        parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
        sort_by: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> QueryResponseItems:
        """
        Retrieves a list of line items and their details from an entrypoint. Line items are also known as items, products, and services. Use filters to limit results.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        from_record : typing.Optional[int]
            The number of records to skip before starting to collect the result set.

        limit_record : typing.Optional[int]
            Max number of records to return for the query. Use `0` or negative value to return all records.

        parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]

            Collection of field names, conditions, and values used to filter the query
            <Info>
              **You must remove `parameters=` from the request before you send it, otherwise Payabli will ignore the filters.**

              Because of a technical limitation, you can't make a request that includes filters from the API console on this page. The response won't be filtered. Instead, copy the request, remove `parameters=` and run the request in a different client.

              For example:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?parameters=totalAmount(gt)=1000&limitRecord=20

              should become:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?totalAmount(gt)=1000&limitRecord=20

            </Info>
            See [Filters and Conditions Reference](/developers/developer-guides/pay-ops-reporting-engine-overview#filters-and-conditions-reference) for help.

            List of field names accepted:

              - `categories` (ct, nct)
              - `code` (ne, eq, ct, nct)
              - `commodityCode` (ne, eq, ct, nct)
              - `createdDate` (gt, ge, lt, le, eq, ne)
              - `description` (ne, eq, ct, nct)
              - `externalPaypointID` (ct, nct, ne, eq)
              - `mode` (eq, ne)
              - `name` (ne, eq, ct, nct)
              - `orgName` (ne, eq, ct, nct)
              - `paypointDba` (ne, eq, ct, nct)
              - `paypointId` (ne, eq)
              - `paypointLegal` (ne, eq, ct, nct)
              - `quantity` (gt, ge, lt, le, eq, ne)
              - `uom` (ne, eq, ct, nct)
              - `updatedDate` (gt, ge, lt, le, eq, ne)
              - `value` (gt, ge, lt, le, eq, ne)

            List of comparison accepted - enclosed between parentheses:

            - eq or empty => equal
            - gt => greater than
            - ge => greater or equal
            - lt => less than
            - le => less or equal
            - ne => not equal
            - ct => contains
            - nct => not contains
            - in => inside array separated by "|"
            - nin => not inside array separated by "|"

            List of parameters accepted:
            - limitRecord : max number of records for query (default="20", "0" or negative value for all)
            - fromRecord : initial record in query

            Example: name(ct)=john return all records with name containing john

        sort_by : typing.Optional[str]
            The field name to use for sorting results. Use `desc(field_name)` to sort descending by `field_name`, and use `asc(field_name)` to sort ascending by `field_name`.

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

        Returns
        -------
        QueryResponseItems
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.line_item.list_line_items(
                entry="8cfec329267",
                from_record=251,
                limit_record=0,
                sort_by="desc(field_name)",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list_line_items(
            entry,
            from_record=from_record,
            limit_record=limit_record,
            parameters=parameters,
            sort_by=sort_by,
            request_options=request_options,
        )
        return _response.data

    async def update_item(
        self,
        line_item_id: int,
        *,
        item_cost: float,
        item_qty: int,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse6:
        """
        Updates an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        PayabliApiResponse6
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.line_item.update_item(
                line_item_id=700,
                item_cost=12.45,
                item_qty=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update_item(
            line_item_id,
            item_cost=item_cost,
            item_qty=item_qty,
            item_categories=item_categories,
            item_commodity_code=item_commodity_code,
            item_description=item_description,
            item_mode=item_mode,
            item_product_code=item_product_code,
            item_product_name=item_product_name,
            item_unit_of_measure=item_unit_of_measure,
            request_options=request_options,
        )
        return _response.data
