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

from __future__ import annotations

from typing import Dict
from typing_extensions import Literal

import httpx

from .files import (
    FilesResource,
    AsyncFilesResource,
    FilesResourceWithRawResponse,
    AsyncFilesResourceWithRawResponse,
    FilesResourceWithStreamingResponse,
    AsyncFilesResourceWithStreamingResponse,
)
from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, 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.dataframer import transform_job_create_params
from ....types.dataframer.transform_job_list_response import TransformJobListResponse
from ....types.dataframer.transform_job_create_response import TransformJobCreateResponse
from ....types.dataframer.transform_job_retrieve_response import TransformJobRetrieveResponse

__all__ = ["TransformJobsResource", "AsyncTransformJobsResource"]


class TransformJobsResource(SyncAPIResource):
    @cached_property
    def files(self) -> FilesResource:
        return FilesResource(self._client)

    @cached_property
    def with_raw_response(self) -> TransformJobsResourceWithRawResponse:
        """
        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/aimonlabs/dataframer-python-sdk#accessing-raw-response-data-eg-headers
        """
        return TransformJobsResourceWithRawResponse(self)

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

        For more information, see https://www.github.com/aimonlabs/dataframer-python-sdk#with_streaming_response
        """
        return TransformJobsResourceWithStreamingResponse(self)

    def create(
        self,
        *,
        dataset_id: str,
        detection_method: Literal["gliner", "llm", "heuristics", "gliner+heuristics", "llm+heuristics", "all"],
        name: str,
        pii_types: SequenceNotStr[str],
        evaluation_model: str | Omit = omit,
        mask_config: Dict[str, str] | Omit = omit,
        model_name: str | Omit = omit,
        threshold: float | 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,
    ) -> TransformJobCreateResponse:
        """
        Create a new PII/PHI transform job.

        **Async operation**: Returns immediately with a job ID and `PENDING` status.
        Poll `GET /api/dataframer/transform-jobs/{job_id}/` until status is `SUCCEEDED`
        or `FAILED`.

        Args:
          dataset_id: UUID of the seed dataset to transform.

          detection_method: Entity detection method. Use `llm` or compound methods when you need LLM-based
              detection; supply `model_name` in that case.

          name: Human-readable name for this transform job.

          pii_types: List of PII/PHI entity types to detect and mask (e.g. ["PERSON", "EMAIL",
              "PHONE_NUMBER"]).

          evaluation_model: AI model for automatic PII redaction quality evaluation after the job completes.
              Defaults to `anthropic/claude-sonnet-4-6`.

          mask_config: Optional per-entity-type masking strategy, e.g.
              `{"PERSON": "REPLACE", "EMAIL": "REDACT"}`. Defaults to redact all.

          model_name: LLM model name. Required when `detection_method` includes `llm`.

          threshold: Confidence threshold for entity detection (0.0–1.0). Lower values detect more
              entities; higher values reduce false positives.

          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(
            "/api/dataframer/transform-jobs/",
            body=maybe_transform(
                {
                    "dataset_id": dataset_id,
                    "detection_method": detection_method,
                    "name": name,
                    "pii_types": pii_types,
                    "evaluation_model": evaluation_model,
                    "mask_config": mask_config,
                    "model_name": model_name,
                    "threshold": threshold,
                },
                transform_job_create_params.TransformJobCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobCreateResponse,
        )

    def retrieve(
        self,
        job_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,
    ) -> TransformJobRetrieveResponse:
        """Retrieve a transform job by ID.

        Use this endpoint to poll for completion while
        status is `PENDING` or `RUNNING`.

        Args:
          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 job_id:
            raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
        return self._get(
            path_template("/api/dataframer/transform-jobs/{job_id}/", job_id=job_id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobRetrieveResponse,
        )

    def list(
        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,
    ) -> TransformJobListResponse:
        """
        List all PII/PHI transform jobs for the authenticated company, newest first.
        Running and pending jobs have their status refreshed automatically.
        """
        return self._get(
            "/api/dataframer/transform-jobs/",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobListResponse,
        )

    def delete(
        self,
        job_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,
    ) -> None:
        """Soft-delete a transform job (hidden from list view).

        The job data is retained
        internally.

        Args:
          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 job_id:
            raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
        extra_headers = {"Accept": "*/*", **(extra_headers or {})}
        return self._delete(
            path_template("/api/dataframer/transform-jobs/{job_id}/", job_id=job_id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=NoneType,
        )


class AsyncTransformJobsResource(AsyncAPIResource):
    @cached_property
    def files(self) -> AsyncFilesResource:
        return AsyncFilesResource(self._client)

    @cached_property
    def with_raw_response(self) -> AsyncTransformJobsResourceWithRawResponse:
        """
        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/aimonlabs/dataframer-python-sdk#accessing-raw-response-data-eg-headers
        """
        return AsyncTransformJobsResourceWithRawResponse(self)

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

        For more information, see https://www.github.com/aimonlabs/dataframer-python-sdk#with_streaming_response
        """
        return AsyncTransformJobsResourceWithStreamingResponse(self)

    async def create(
        self,
        *,
        dataset_id: str,
        detection_method: Literal["gliner", "llm", "heuristics", "gliner+heuristics", "llm+heuristics", "all"],
        name: str,
        pii_types: SequenceNotStr[str],
        evaluation_model: str | Omit = omit,
        mask_config: Dict[str, str] | Omit = omit,
        model_name: str | Omit = omit,
        threshold: float | 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,
    ) -> TransformJobCreateResponse:
        """
        Create a new PII/PHI transform job.

        **Async operation**: Returns immediately with a job ID and `PENDING` status.
        Poll `GET /api/dataframer/transform-jobs/{job_id}/` until status is `SUCCEEDED`
        or `FAILED`.

        Args:
          dataset_id: UUID of the seed dataset to transform.

          detection_method: Entity detection method. Use `llm` or compound methods when you need LLM-based
              detection; supply `model_name` in that case.

          name: Human-readable name for this transform job.

          pii_types: List of PII/PHI entity types to detect and mask (e.g. ["PERSON", "EMAIL",
              "PHONE_NUMBER"]).

          evaluation_model: AI model for automatic PII redaction quality evaluation after the job completes.
              Defaults to `anthropic/claude-sonnet-4-6`.

          mask_config: Optional per-entity-type masking strategy, e.g.
              `{"PERSON": "REPLACE", "EMAIL": "REDACT"}`. Defaults to redact all.

          model_name: LLM model name. Required when `detection_method` includes `llm`.

          threshold: Confidence threshold for entity detection (0.0–1.0). Lower values detect more
              entities; higher values reduce false positives.

          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(
            "/api/dataframer/transform-jobs/",
            body=await async_maybe_transform(
                {
                    "dataset_id": dataset_id,
                    "detection_method": detection_method,
                    "name": name,
                    "pii_types": pii_types,
                    "evaluation_model": evaluation_model,
                    "mask_config": mask_config,
                    "model_name": model_name,
                    "threshold": threshold,
                },
                transform_job_create_params.TransformJobCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobCreateResponse,
        )

    async def retrieve(
        self,
        job_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,
    ) -> TransformJobRetrieveResponse:
        """Retrieve a transform job by ID.

        Use this endpoint to poll for completion while
        status is `PENDING` or `RUNNING`.

        Args:
          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 job_id:
            raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
        return await self._get(
            path_template("/api/dataframer/transform-jobs/{job_id}/", job_id=job_id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobRetrieveResponse,
        )

    async def list(
        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,
    ) -> TransformJobListResponse:
        """
        List all PII/PHI transform jobs for the authenticated company, newest first.
        Running and pending jobs have their status refreshed automatically.
        """
        return await self._get(
            "/api/dataframer/transform-jobs/",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=TransformJobListResponse,
        )

    async def delete(
        self,
        job_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,
    ) -> None:
        """Soft-delete a transform job (hidden from list view).

        The job data is retained
        internally.

        Args:
          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 job_id:
            raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
        extra_headers = {"Accept": "*/*", **(extra_headers or {})}
        return await self._delete(
            path_template("/api/dataframer/transform-jobs/{job_id}/", job_id=job_id),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=NoneType,
        )


class TransformJobsResourceWithRawResponse:
    def __init__(self, transform_jobs: TransformJobsResource) -> None:
        self._transform_jobs = transform_jobs

        self.create = to_raw_response_wrapper(
            transform_jobs.create,
        )
        self.retrieve = to_raw_response_wrapper(
            transform_jobs.retrieve,
        )
        self.list = to_raw_response_wrapper(
            transform_jobs.list,
        )
        self.delete = to_raw_response_wrapper(
            transform_jobs.delete,
        )

    @cached_property
    def files(self) -> FilesResourceWithRawResponse:
        return FilesResourceWithRawResponse(self._transform_jobs.files)


class AsyncTransformJobsResourceWithRawResponse:
    def __init__(self, transform_jobs: AsyncTransformJobsResource) -> None:
        self._transform_jobs = transform_jobs

        self.create = async_to_raw_response_wrapper(
            transform_jobs.create,
        )
        self.retrieve = async_to_raw_response_wrapper(
            transform_jobs.retrieve,
        )
        self.list = async_to_raw_response_wrapper(
            transform_jobs.list,
        )
        self.delete = async_to_raw_response_wrapper(
            transform_jobs.delete,
        )

    @cached_property
    def files(self) -> AsyncFilesResourceWithRawResponse:
        return AsyncFilesResourceWithRawResponse(self._transform_jobs.files)


class TransformJobsResourceWithStreamingResponse:
    def __init__(self, transform_jobs: TransformJobsResource) -> None:
        self._transform_jobs = transform_jobs

        self.create = to_streamed_response_wrapper(
            transform_jobs.create,
        )
        self.retrieve = to_streamed_response_wrapper(
            transform_jobs.retrieve,
        )
        self.list = to_streamed_response_wrapper(
            transform_jobs.list,
        )
        self.delete = to_streamed_response_wrapper(
            transform_jobs.delete,
        )

    @cached_property
    def files(self) -> FilesResourceWithStreamingResponse:
        return FilesResourceWithStreamingResponse(self._transform_jobs.files)


class AsyncTransformJobsResourceWithStreamingResponse:
    def __init__(self, transform_jobs: AsyncTransformJobsResource) -> None:
        self._transform_jobs = transform_jobs

        self.create = async_to_streamed_response_wrapper(
            transform_jobs.create,
        )
        self.retrieve = async_to_streamed_response_wrapper(
            transform_jobs.retrieve,
        )
        self.list = async_to_streamed_response_wrapper(
            transform_jobs.list,
        )
        self.delete = async_to_streamed_response_wrapper(
            transform_jobs.delete,
        )

    @cached_property
    def files(self) -> AsyncFilesResourceWithStreamingResponse:
        return AsyncFilesResourceWithStreamingResponse(self._transform_jobs.files)
