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

from __future__ import annotations

import httpx
import os
import mimetypes

from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from ...._utils import (
    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.workers.link import Link
from ....types.workers.resources import file_create_params
from ....types.workers.resources.file_list_response import FileListResponse

__all__ = ["FileResource", "AsyncFileResource"]


class FileResource(SyncAPIResource):
    @cached_property
    def with_raw_response(self) -> FileResourceWithRawResponse:
        """
        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/BrainbaseHQ/brainbase-labs-python-sdk#accessing-raw-response-data-eg-headers
        """
        return FileResourceWithRawResponse(self)

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

        For more information, see https://www.github.com/BrainbaseHQ/brainbase-labs-python-sdk#with_streaming_response
        """
        return FileResourceWithStreamingResponse(self)

    def create(
        self,
        worker_id: str,
        *,
        local_file_path: str,
        name: 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,
    ) -> Link:
        """
        Create a new file resource by uploading a local file.

        This method performs the following steps:
          1. Reads the specified local file and determines its file name, MIME type, and size.
          2. Retrieves a signed upload URL from the upload service.
          3. Uploads the file to S3 using the signed URL.
          4. Makes the final API request with the file metadata.

        Args:
          local_file_path: The path to the local file to be uploaded.
          name: The name of the file resource.
          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 worker_id:
            raise ValueError(f"Expected a non-empty value for `worker_id` but received {worker_id!r}")

        if not os.path.exists(local_file_path):
            raise ValueError(f"File does not exist: {local_file_path}")

        # Extract file details from the local file.
        file_name = os.path.basename(local_file_path)
        size = str(os.path.getsize(local_file_path))
        mime_type, _ = mimetypes.guess_type(local_file_path)
        if mime_type is None:
            mime_type = "application/octet-stream"

        # Step 1: Get the signed upload URL using self._get.
        # Use a relative URL so that self._get uses your client's base URL.
        upload_endpoint = f"/api/upload/{worker_id}/resource-upload-url"
        params = {"fileName": file_name, "contentType": mime_type}
        upload_headers = {"x-api-key": "sk_8a2307bd1a63e3025ad348b7237b6335cd62951d499183133e2362d4e4a7"}
        # The _get method will prepend the base URL; cast_to=dict ensures the JSON response is returned as a dictionary.
        upload_response = self._get(
            upload_endpoint,
            options=make_request_options(extra_headers=upload_headers, extra_query=params, timeout=timeout),
            cast_to=dict,
        )
        signed_upload_url = upload_response["uploadUrl"]

        # Step 2: Upload the file to S3 using the signed URL.
        with open(local_file_path, "rb") as f:
            file_content = f.read()
        put_headers = {"Content-Type": mime_type}
        put_response = httpx.put(signed_upload_url, data=file_content, headers=put_headers)
        put_response.raise_for_status()

        # Extract the S3 file path (without query parameters) to be stored.
        s3_file_path = signed_upload_url.split("?")[0]

        # Step 3: Create the file resource record with the file metadata.
        payload = {
            "file_name": file_name,
            "mime_type": mime_type,
            "name": name,
            "s3_file_path": s3_file_path,
            "size": size,
        }
        return self._post(
            f"/api/workers/{worker_id}/resources/file",
            body=maybe_transform(payload, file_create_params.FileCreateParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=Link,
        )

    def list(
        self,
        worker_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,
    ) -> FileListResponse:
        """
        Get all file resources for a worker

        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 worker_id:
            raise ValueError(f"Expected a non-empty value for `worker_id` but received {worker_id!r}")
        return self._get(
            f"/api/workers/{worker_id}/resources/file",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=FileListResponse,
        )


class AsyncFileResource(AsyncAPIResource):
    @cached_property
    def with_raw_response(self) -> AsyncFileResourceWithRawResponse:
        """
        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/BrainbaseHQ/brainbase-labs-python-sdk#accessing-raw-response-data-eg-headers
        """
        return AsyncFileResourceWithRawResponse(self)

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

        For more information, see https://www.github.com/BrainbaseHQ/brainbase-labs-python-sdk#with_streaming_response
        """
        return AsyncFileResourceWithStreamingResponse(self)

    async def create(
        self,
        worker_id: str,
        *,
        local_file_path: str,
        name: 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,
    ) -> Link:
        """
        Create a new file resource by uploading a local file.

        This method performs the following steps:
          1. Reads the specified local file and determines its file name, MIME type, and size.
          2. Retrieves a signed upload URL from the upload service.
          3. Uploads the file to S3 using the signed URL.
          4. Makes the final API request with the file metadata.

        Args:
          local_file_path: The path to the local file to be uploaded.
          name: The name of the file resource.
          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 worker_id:
            raise ValueError(f"Expected a non-empty value for `worker_id` but received {worker_id!r}")

        if not os.path.exists(local_file_path):
            raise ValueError(f"File does not exist: {local_file_path}")

        # Extract file details from the local file.
        file_name = os.path.basename(local_file_path)
        size = str(os.path.getsize(local_file_path))
        mime_type, _ = mimetypes.guess_type(local_file_path)
        if mime_type is None:
            mime_type = "application/octet-stream"

        # Step 1: Get the signed upload URL using self._get.
        # Use a relative URL so that self._get uses your client's base URL.
        upload_endpoint = f"/api/upload/{worker_id}/resource-upload-url"
        params = {"fileName": file_name, "contentType": mime_type}
        upload_headers = {"x-api-key": "sk_8a2307bd1a63e3025ad348b7237b6335cd62951d499183133e2362d4e4a7"}
        # The _get method will prepend the base URL; cast_to=dict ensures the JSON response is returned as a dictionary.
        upload_response = await self._get(
            upload_endpoint,
            options=make_request_options(extra_headers=upload_headers, extra_query=params, timeout=timeout),
            cast_to=dict,
        )
        signed_upload_url = upload_response["uploadUrl"]

        # Step 2: Upload the file to S3 using the signed URL.
        with open(local_file_path, "rb") as f:
            file_content = f.read()
        put_headers = {"Content-Type": mime_type}
        put_response = httpx.put(signed_upload_url, data=file_content, headers=put_headers)
        put_response.raise_for_status()

        # Extract the S3 file path (without query parameters) to be stored.
        s3_file_path = signed_upload_url.split("?")[0]

        # Step 3: Create the file resource record with the file metadata.
        payload = {
            "file_name": file_name,
            "mime_type": mime_type,
            "name": name,
            "s3_file_path": s3_file_path,
            "size": size,
        }
        return await self._post(
            f"/api/workers/{worker_id}/resources/file",
            body=await async_maybe_transform(payload, file_create_params.FileCreateParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=Link,
        )

    async def list(
        self,
        worker_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,
    ) -> FileListResponse:
        """
        Get all file resources for a worker

        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 worker_id:
            raise ValueError(f"Expected a non-empty value for `worker_id` but received {worker_id!r}")
        return await self._get(
            f"/api/workers/{worker_id}/resources/file",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=FileListResponse,
        )


class FileResourceWithRawResponse:
    def __init__(self, file: FileResource) -> None:
        self._file = file

        self.create = to_raw_response_wrapper(
            file.create,
        )
        self.list = to_raw_response_wrapper(
            file.list,
        )


class AsyncFileResourceWithRawResponse:
    def __init__(self, file: AsyncFileResource) -> None:
        self._file = file

        self.create = async_to_raw_response_wrapper(
            file.create,
        )
        self.list = async_to_raw_response_wrapper(
            file.list,
        )


class FileResourceWithStreamingResponse:
    def __init__(self, file: FileResource) -> None:
        self._file = file

        self.create = to_streamed_response_wrapper(
            file.create,
        )
        self.list = to_streamed_response_wrapper(
            file.list,
        )


class AsyncFileResourceWithStreamingResponse:
    def __init__(self, file: AsyncFileResource) -> None:
        self._file = file

        self.create = async_to_streamed_response_wrapper(
            file.create,
        )
        self.list = async_to_streamed_response_wrapper(
            file.list,
        )