# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

import httpx

from ..types import account_list_params, account_create_params, account_update_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
    to_raw_response_wrapper,
    to_streamed_response_wrapper,
    async_to_raw_response_wrapper,
    async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
from ..types.account_list_response import AccountListResponse
from ..types.account_create_response import AccountCreateResponse
from ..types.account_update_response import AccountUpdateResponse
from ..types.account_retrieve_response import AccountRetrieveResponse
from ..types.account_definitions_response import AccountDefinitionsResponse

__all__ = ["AccountResource", "AsyncAccountResource"]


class AccountResource(SyncAPIResource):
    """Accounts represent companies or organizations in Lightfield.

    Each account can have contacts, opportunities, tasks, and notes associated with it.
    """

    @cached_property
    def with_raw_response(self) -> AccountResourceWithRawResponse:
        """
        This property can be used as a prefix for any HTTP method call to return
        the raw response object instead of the parsed content.

        For more information, see https://www.github.com/Lightfld/lightfield-python#accessing-raw-response-data-eg-headers
        """
        return AccountResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> AccountResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/Lightfld/lightfield-python#with_streaming_response
        """
        return AccountResourceWithStreamingResponse(self)

    def create(
        self,
        *,
        fields: account_create_params.Fields,
        relationships: account_create_params.Relationships | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountCreateResponse:
        """Creates a new account record.

        The `$name` field is required.

        If a `$website` is provided, Lightfield automatically enriches the account in
        the background. The `$howTheyMakeMoney` and `$accountStatus` fields are
        read-only and cannot be set via the API. The `$opportunity`, `$task`, and
        `$note` relationships are also read-only — manage them via the `$account`
        relationship on the opportunity or task, or the `$account`/`$opportunity` note
        relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

        **[Required scope](/using-the-api/scopes/):** `accounts:create`

        **[Rate limit category](/using-the-api/rate-limits/):** Write

        Args:
          fields: Field values for the new account. System fields use a `$` prefix (e.g. `$name`,
              `$website`); custom attributes use their bare slug (e.g. `tier`, `renewalDate`).
              Required: `$name` (string). Fields of type `SINGLE_SELECT` or `MULTI_SELECT`
              accept either an option ID or label from the field's `typeConfiguration.options`
              — call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> to
              discover available fields and options. See
              <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
              value type details.

          relationships: Relationships to set on the new account. System relationships use a `$` prefix
              (e.g. `$owner`, `$contact`); custom relationships use their bare slug. Each
              value is a single entity ID or an array of IDs. Call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> to
              list available relationship keys.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        return self._post(
            "/v1/accounts",
            body=maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                account_create_params.AccountCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountCreateResponse,
        )

    def retrieve(
        self,
        id: str,
        *,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountRetrieveResponse:
        """
        Retrieves a single account by its ID.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Read

        Args:
          id: Unique identifier of the account to retrieve.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not id:
            raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
        return self._get(
            path_template("/v1/accounts/{id}", id=id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountRetrieveResponse,
        )

    def update(
        self,
        id: str,
        *,
        fields: account_update_params.Fields | Omit = omit,
        relationships: account_update_params.Relationships | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountUpdateResponse:
        """Updates an existing account by ID.

        Only included fields and relationships are
        modified.

        The `$howTheyMakeMoney` and `$accountStatus` fields are read-only and cannot be
        updated. The `$opportunity`, `$task`, and `$note` relationships are also
        read-only — manage them via the `$account` relationship on the opportunity or
        task, or the `$account`/`$opportunity` note relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

        **[Required scope](/using-the-api/scopes/):** `accounts:update`

        **[Rate limit category](/using-the-api/rate-limits/):** Write

        Args:
          id: Unique identifier of the account to update.

          fields: Field values to update — only provided fields are modified; omitted fields are
              left unchanged. System fields use a `$` prefix (e.g. `$name`); custom attributes
              use their bare slug. `SINGLE_SELECT` and `MULTI_SELECT` fields accept an option
              ID or label — call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> for
              available options. See
              <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
              value type details.

          relationships: Relationship operations to apply. System relationships use a `$` prefix (e.g.
              `$owner`, `$contact`). Each value is an operation object with `add`, `remove`,
              or `replace`.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not id:
            raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
        return self._post(
            path_template("/v1/accounts/{id}", id=id),
            body=maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                account_update_params.AccountUpdateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountUpdateResponse,
        )

    def list(
        self,
        *,
        limit: int | Omit = omit,
        offset: int | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountListResponse:
        """Returns a paginated list of accounts.

        Use `offset` and `limit` to paginate
        through results. See <u>[List endpoints](/using-the-api/list-endpoints/)</u> for
        more information about pagination.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Search

        Args:
          limit: Maximum number of records to return. Defaults to 25, maximum 25.

          offset: Number of records to skip for pagination. Defaults to 0.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        return self._get(
            "/v1/accounts",
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=maybe_transform(
                    {
                        "limit": limit,
                        "offset": offset,
                    },
                    account_list_params.AccountListParams,
                ),
            ),
            cast_to=AccountListResponse,
        )

    def definitions(
        self,
        *,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountDefinitionsResponse:
        """
        Returns the schema for all field and relationship definitions available on
        accounts, including both system-defined and custom fields. Useful for
        understanding the shape of account data before creating or updating records. See
        <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
        more details.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Read
        """
        return self._get(
            "/v1/accounts/definitions",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountDefinitionsResponse,
        )


class AsyncAccountResource(AsyncAPIResource):
    """Accounts represent companies or organizations in Lightfield.

    Each account can have contacts, opportunities, tasks, and notes associated with it.
    """

    @cached_property
    def with_raw_response(self) -> AsyncAccountResourceWithRawResponse:
        """
        This property can be used as a prefix for any HTTP method call to return
        the raw response object instead of the parsed content.

        For more information, see https://www.github.com/Lightfld/lightfield-python#accessing-raw-response-data-eg-headers
        """
        return AsyncAccountResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> AsyncAccountResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/Lightfld/lightfield-python#with_streaming_response
        """
        return AsyncAccountResourceWithStreamingResponse(self)

    async def create(
        self,
        *,
        fields: account_create_params.Fields,
        relationships: account_create_params.Relationships | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountCreateResponse:
        """Creates a new account record.

        The `$name` field is required.

        If a `$website` is provided, Lightfield automatically enriches the account in
        the background. The `$howTheyMakeMoney` and `$accountStatus` fields are
        read-only and cannot be set via the API. The `$opportunity`, `$task`, and
        `$note` relationships are also read-only — manage them via the `$account`
        relationship on the opportunity or task, or the `$account`/`$opportunity` note
        relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

        **[Required scope](/using-the-api/scopes/):** `accounts:create`

        **[Rate limit category](/using-the-api/rate-limits/):** Write

        Args:
          fields: Field values for the new account. System fields use a `$` prefix (e.g. `$name`,
              `$website`); custom attributes use their bare slug (e.g. `tier`, `renewalDate`).
              Required: `$name` (string). Fields of type `SINGLE_SELECT` or `MULTI_SELECT`
              accept either an option ID or label from the field's `typeConfiguration.options`
              — call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> to
              discover available fields and options. See
              <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
              value type details.

          relationships: Relationships to set on the new account. System relationships use a `$` prefix
              (e.g. `$owner`, `$contact`); custom relationships use their bare slug. Each
              value is a single entity ID or an array of IDs. Call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> to
              list available relationship keys.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        return await self._post(
            "/v1/accounts",
            body=await async_maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                account_create_params.AccountCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountCreateResponse,
        )

    async def retrieve(
        self,
        id: str,
        *,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountRetrieveResponse:
        """
        Retrieves a single account by its ID.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Read

        Args:
          id: Unique identifier of the account to retrieve.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not id:
            raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
        return await self._get(
            path_template("/v1/accounts/{id}", id=id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountRetrieveResponse,
        )

    async def update(
        self,
        id: str,
        *,
        fields: account_update_params.Fields | Omit = omit,
        relationships: account_update_params.Relationships | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountUpdateResponse:
        """Updates an existing account by ID.

        Only included fields and relationships are
        modified.

        The `$howTheyMakeMoney` and `$accountStatus` fields are read-only and cannot be
        updated. The `$opportunity`, `$task`, and `$note` relationships are also
        read-only — manage them via the `$account` relationship on the opportunity or
        task, or the `$account`/`$opportunity` note relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

        **[Required scope](/using-the-api/scopes/):** `accounts:update`

        **[Rate limit category](/using-the-api/rate-limits/):** Write

        Args:
          id: Unique identifier of the account to update.

          fields: Field values to update — only provided fields are modified; omitted fields are
              left unchanged. System fields use a `$` prefix (e.g. `$name`); custom attributes
              use their bare slug. `SINGLE_SELECT` and `MULTI_SELECT` fields accept an option
              ID or label — call the
              <u>[definitions endpoint](/api/resources/account/methods/definitions)</u> for
              available options. See
              <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
              value type details.

          relationships: Relationship operations to apply. System relationships use a `$` prefix (e.g.
              `$owner`, `$contact`). Each value is an operation object with `add`, `remove`,
              or `replace`.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not id:
            raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
        return await self._post(
            path_template("/v1/accounts/{id}", id=id),
            body=await async_maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                account_update_params.AccountUpdateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountUpdateResponse,
        )

    async def list(
        self,
        *,
        limit: int | Omit = omit,
        offset: int | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountListResponse:
        """Returns a paginated list of accounts.

        Use `offset` and `limit` to paginate
        through results. See <u>[List endpoints](/using-the-api/list-endpoints/)</u> for
        more information about pagination.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Search

        Args:
          limit: Maximum number of records to return. Defaults to 25, maximum 25.

          offset: Number of records to skip for pagination. Defaults to 0.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        return await self._get(
            "/v1/accounts",
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=await async_maybe_transform(
                    {
                        "limit": limit,
                        "offset": offset,
                    },
                    account_list_params.AccountListParams,
                ),
            ),
            cast_to=AccountListResponse,
        )

    async def definitions(
        self,
        *,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AccountDefinitionsResponse:
        """
        Returns the schema for all field and relationship definitions available on
        accounts, including both system-defined and custom fields. Useful for
        understanding the shape of account data before creating or updating records. See
        <u>[Fields and relationships](/using-the-api/fields-and-relationships/)</u> for
        more details.

        **[Required scope](/using-the-api/scopes/):** `accounts:read`

        **[Rate limit category](/using-the-api/rate-limits/):** Read
        """
        return await self._get(
            "/v1/accounts/definitions",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=AccountDefinitionsResponse,
        )


class AccountResourceWithRawResponse:
    def __init__(self, account: AccountResource) -> None:
        self._account = account

        self.create = to_raw_response_wrapper(
            account.create,
        )
        self.retrieve = to_raw_response_wrapper(
            account.retrieve,
        )
        self.update = to_raw_response_wrapper(
            account.update,
        )
        self.list = to_raw_response_wrapper(
            account.list,
        )
        self.definitions = to_raw_response_wrapper(
            account.definitions,
        )


class AsyncAccountResourceWithRawResponse:
    def __init__(self, account: AsyncAccountResource) -> None:
        self._account = account

        self.create = async_to_raw_response_wrapper(
            account.create,
        )
        self.retrieve = async_to_raw_response_wrapper(
            account.retrieve,
        )
        self.update = async_to_raw_response_wrapper(
            account.update,
        )
        self.list = async_to_raw_response_wrapper(
            account.list,
        )
        self.definitions = async_to_raw_response_wrapper(
            account.definitions,
        )


class AccountResourceWithStreamingResponse:
    def __init__(self, account: AccountResource) -> None:
        self._account = account

        self.create = to_streamed_response_wrapper(
            account.create,
        )
        self.retrieve = to_streamed_response_wrapper(
            account.retrieve,
        )
        self.update = to_streamed_response_wrapper(
            account.update,
        )
        self.list = to_streamed_response_wrapper(
            account.list,
        )
        self.definitions = to_streamed_response_wrapper(
            account.definitions,
        )


class AsyncAccountResourceWithStreamingResponse:
    def __init__(self, account: AsyncAccountResource) -> None:
        self._account = account

        self.create = async_to_streamed_response_wrapper(
            account.create,
        )
        self.retrieve = async_to_streamed_response_wrapper(
            account.retrieve,
        )
        self.update = async_to_streamed_response_wrapper(
            account.update,
        )
        self.list = async_to_streamed_response_wrapper(
            account.list,
        )
        self.definitions = async_to_streamed_response_wrapper(
            account.definitions,
        )
