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

from __future__ import annotations

import httpx

from ..types import opportunity_list_params, opportunity_create_params, opportunity_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.opportunity_list_response import OpportunityListResponse
from ..types.opportunity_create_response import OpportunityCreateResponse
from ..types.opportunity_update_response import OpportunityUpdateResponse
from ..types.opportunity_retrieve_response import OpportunityRetrieveResponse
from ..types.opportunity_definitions_response import OpportunityDefinitionsResponse

__all__ = ["OpportunityResource", "AsyncOpportunityResource"]


class OpportunityResource(SyncAPIResource):
    """Opportunities represent potential deals or sales in Lightfield.

    Each opportunity belongs to an account and can have tasks and notes associated with it.
    """

    @cached_property
    def with_raw_response(self) -> OpportunityResourceWithRawResponse:
        """
        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 OpportunityResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> OpportunityResourceWithStreamingResponse:
        """
        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 OpportunityResourceWithStreamingResponse(self)

    def create(
        self,
        *,
        fields: opportunity_create_params.Fields,
        relationships: opportunity_create_params.Relationships,
        # 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,
    ) -> OpportunityCreateResponse:
        """Creates a new opportunity record.

        The `$name` and `$stage` fields and the
        `$account` relationship are required.

        After creation, Lightfield automatically generates an opportunity summary in the
        background. The `$opportunityStatus` field is read-only and cannot be set via
        the API. The `$task` and `$note` relationships are also read-only — manage them
        via the `$opportunity` relationship on the task, or the
        `$account`/`$opportunity` note relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

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

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

        Args:
          fields: Field values for the new opportunity. System fields use a `$` prefix (e.g.
              `$name`, `$stage`); custom attributes use their bare slug. Required: `$name`
              (string) and `$stage` (option ID or label). 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/opportunity/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 opportunity. System relationships use a `$`
              prefix (e.g. `$account`, `$owner`); custom relationships use their bare slug.
              `$account` is required. Each value is a single entity ID or an array of IDs.
              Call the
              <u>[definitions endpoint](/api/resources/opportunity/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/opportunities",
            body=maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                opportunity_create_params.OpportunityCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityCreateResponse,
        )

    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,
    ) -> OpportunityRetrieveResponse:
        """
        Retrieves a single opportunity by its ID.

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

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

        Args:
          id: Unique identifier of the opportunity 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/opportunities/{id}", id=id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityRetrieveResponse,
        )

    def update(
        self,
        id: str,
        *,
        fields: opportunity_update_params.Fields | Omit = omit,
        relationships: opportunity_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,
    ) -> OpportunityUpdateResponse:
        """Updates an existing opportunity by ID.

        Only included fields and relationships
        are modified.

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

        Supports idempotency via the `Idempotency-Key` header.

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

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

        Args:
          id: Unique identifier of the opportunity 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`, `$stage`); 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/opportunity/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`, `$champion`). 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/opportunities/{id}", id=id),
            body=maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                opportunity_update_params.OpportunityUpdateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityUpdateResponse,
        )

    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,
    ) -> OpportunityListResponse:
        """Returns a paginated list of opportunities.

        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/):** `opportunities: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/opportunities",
            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,
                    },
                    opportunity_list_params.OpportunityListParams,
                ),
            ),
            cast_to=OpportunityListResponse,
        )

    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,
    ) -> OpportunityDefinitionsResponse:
        """
        Returns the schema for all field and relationship definitions available on
        opportunities, including both system-defined and custom fields. Useful for
        understanding the shape of opportunity 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/):** `opportunities:read`

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


class AsyncOpportunityResource(AsyncAPIResource):
    """Opportunities represent potential deals or sales in Lightfield.

    Each opportunity belongs to an account and can have tasks and notes associated with it.
    """

    @cached_property
    def with_raw_response(self) -> AsyncOpportunityResourceWithRawResponse:
        """
        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 AsyncOpportunityResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> AsyncOpportunityResourceWithStreamingResponse:
        """
        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 AsyncOpportunityResourceWithStreamingResponse(self)

    async def create(
        self,
        *,
        fields: opportunity_create_params.Fields,
        relationships: opportunity_create_params.Relationships,
        # 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,
    ) -> OpportunityCreateResponse:
        """Creates a new opportunity record.

        The `$name` and `$stage` fields and the
        `$account` relationship are required.

        After creation, Lightfield automatically generates an opportunity summary in the
        background. The `$opportunityStatus` field is read-only and cannot be set via
        the API. The `$task` and `$note` relationships are also read-only — manage them
        via the `$opportunity` relationship on the task, or the
        `$account`/`$opportunity` note relationships instead.

        Supports idempotency via the `Idempotency-Key` header.

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

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

        Args:
          fields: Field values for the new opportunity. System fields use a `$` prefix (e.g.
              `$name`, `$stage`); custom attributes use their bare slug. Required: `$name`
              (string) and `$stage` (option ID or label). 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/opportunity/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 opportunity. System relationships use a `$`
              prefix (e.g. `$account`, `$owner`); custom relationships use their bare slug.
              `$account` is required. Each value is a single entity ID or an array of IDs.
              Call the
              <u>[definitions endpoint](/api/resources/opportunity/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/opportunities",
            body=await async_maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                opportunity_create_params.OpportunityCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityCreateResponse,
        )

    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,
    ) -> OpportunityRetrieveResponse:
        """
        Retrieves a single opportunity by its ID.

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

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

        Args:
          id: Unique identifier of the opportunity 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/opportunities/{id}", id=id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityRetrieveResponse,
        )

    async def update(
        self,
        id: str,
        *,
        fields: opportunity_update_params.Fields | Omit = omit,
        relationships: opportunity_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,
    ) -> OpportunityUpdateResponse:
        """Updates an existing opportunity by ID.

        Only included fields and relationships
        are modified.

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

        Supports idempotency via the `Idempotency-Key` header.

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

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

        Args:
          id: Unique identifier of the opportunity 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`, `$stage`); 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/opportunity/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`, `$champion`). 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/opportunities/{id}", id=id),
            body=await async_maybe_transform(
                {
                    "fields": fields,
                    "relationships": relationships,
                },
                opportunity_update_params.OpportunityUpdateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=OpportunityUpdateResponse,
        )

    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,
    ) -> OpportunityListResponse:
        """Returns a paginated list of opportunities.

        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/):** `opportunities: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/opportunities",
            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,
                    },
                    opportunity_list_params.OpportunityListParams,
                ),
            ),
            cast_to=OpportunityListResponse,
        )

    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,
    ) -> OpportunityDefinitionsResponse:
        """
        Returns the schema for all field and relationship definitions available on
        opportunities, including both system-defined and custom fields. Useful for
        understanding the shape of opportunity 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/):** `opportunities:read`

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


class OpportunityResourceWithRawResponse:
    def __init__(self, opportunity: OpportunityResource) -> None:
        self._opportunity = opportunity

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


class AsyncOpportunityResourceWithRawResponse:
    def __init__(self, opportunity: AsyncOpportunityResource) -> None:
        self._opportunity = opportunity

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


class OpportunityResourceWithStreamingResponse:
    def __init__(self, opportunity: OpportunityResource) -> None:
        self._opportunity = opportunity

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


class AsyncOpportunityResourceWithStreamingResponse:
    def __init__(self, opportunity: AsyncOpportunityResource) -> None:
        self._opportunity = opportunity

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