"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
from .sdkconfiguration import SDKConfiguration
from .utils.logger import Logger, get_default_logger
from .utils.retries import RetryConfig
import httpx
import importlib
from que_media import errors, models, utils
from que_media._hooks import HookContext, SDKHooks
from que_media.types import OptionalNullable, UNSET
from que_media.utils import get_security_from_env
from que_media.utils.unmarshal_json_response import unmarshal_json_response
import sys
from typing import (
    Any,
    Callable,
    Dict,
    List,
    Mapping,
    Optional,
    TYPE_CHECKING,
    Union,
    cast,
)
import weakref

if TYPE_CHECKING:
    from que_media.asset_management import AssetManagement
    from que_media.utility import Utility


class Que(BaseSDK):
    r"""Que API: Welcome to the Que Public HTTP API for C2PA (Content Authenticity Initiative) provenance management.

    Our platform provides robust tools for working with digital asset provenance through C2PA manifests, enabling you to sign and verify digital assets to ensure their authenticity, origin, and processing history.

    **Key Features:**
    *   **Memory-Efficient Streaming**: Assets are processed using streaming techniques to minimize memory usage, supporting large files efficiently
    *   **Verify**: Inspect and validate C2PA manifests embedded in assets with multiple detail levels
    *   **Sign**: Embed comprehensive C2PA manifests into your assets with server-side cryptographic signatures
    *   **Trust Management**: Retrieve and validate against current trust lists containing trusted certificate authorities and manufacturers
    *   **Secure Uploads**: Direct-to-S3 uploads via presigned URLs for large assets

    **Authentication:**
    All endpoints (except for `/healthz`) are secured and require an API key to be passed in the `x-api-key` header.

    **Processing Architecture:**
    Assets are streamed from S3 or URLs to temporary storage during processing to ensure O(chunk_size) memory usage instead of O(file_size), enabling efficient handling of large files on containerized platforms.

    Usage of this API is tracked via Firehose for billing and monitoring purposes.

    https://docs.addque.org - Find more detailed documentation and tutorials here.
    """

    utility: "Utility"
    r"""Service-level endpoints for health checks and configuration."""
    asset_management: "AssetManagement"
    r"""Helper endpoints for handling asset uploads."""
    _sub_sdk_map = {
        "utility": ("que_media.utility", "Utility"),
        "asset_management": ("que_media.asset_management", "AssetManagement"),
    }

    def __init__(
        self,
        api_key_auth: Optional[
            Union[Optional[str], Callable[[], Optional[str]]]
        ] = None,
        environment: Optional[str] = None,
        server_idx: Optional[int] = None,
        server_url: Optional[str] = None,
        url_params: Optional[Dict[str, str]] = None,
        client: Optional[HttpClient] = None,
        async_client: Optional[AsyncHttpClient] = None,
        retry_config: OptionalNullable[RetryConfig] = UNSET,
        timeout_ms: Optional[int] = None,
        debug_logger: Optional[Logger] = None,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param api_key_auth: The api_key_auth required for authentication
        :param environment: Allows setting the environment variable for url substitution
        :param server_idx: The index of the server to use for all methods
        :param server_url: The server URL to use for all methods
        :param url_params: Parameters to optionally template the server URL with
        :param client: The HTTP client to use for all synchronous methods
        :param async_client: The Async HTTP client to use for all asynchronous methods
        :param retry_config: The retry configuration to use for all supported methods
        :param timeout_ms: Optional request timeout applied to each operation in milliseconds
        """
        client_supplied = True
        if client is None:
            client = httpx.Client()
            client_supplied = False

        assert issubclass(
            type(client), HttpClient
        ), "The provided client must implement the HttpClient protocol."

        async_client_supplied = True
        if async_client is None:
            async_client = httpx.AsyncClient()
            async_client_supplied = False

        if debug_logger is None:
            debug_logger = get_default_logger()

        assert issubclass(
            type(async_client), AsyncHttpClient
        ), "The provided async_client must implement the AsyncHttpClient protocol."

        security: Any = None
        if callable(api_key_auth):
            # pylint: disable=unnecessary-lambda-assignment
            security = lambda: models.Security(api_key_auth=api_key_auth())
        else:
            security = models.Security(api_key_auth=api_key_auth)

        if server_url is not None:
            if url_params is not None:
                server_url = utils.template_url(server_url, url_params)
        server_defaults: List[Dict[str, str]] = [
            {
                "environment": environment or "dev-api",
            },
        ]

        BaseSDK.__init__(
            self,
            SDKConfiguration(
                client=client,
                client_supplied=client_supplied,
                async_client=async_client,
                async_client_supplied=async_client_supplied,
                security=security,
                server_url=server_url,
                server_idx=server_idx,
                server_defaults=server_defaults,
                retry_config=retry_config,
                timeout_ms=timeout_ms,
                debug_logger=debug_logger,
            ),
            parent_ref=self,
        )

        hooks = SDKHooks()

        # pylint: disable=protected-access
        self.sdk_configuration.__dict__["_hooks"] = hooks

        self.sdk_configuration = hooks.sdk_init(self.sdk_configuration)

        weakref.finalize(
            self,
            close_clients,
            cast(ClientOwner, self.sdk_configuration),
            self.sdk_configuration.client,
            self.sdk_configuration.client_supplied,
            self.sdk_configuration.async_client,
            self.sdk_configuration.async_client_supplied,
        )

    def dynamic_import(self, modname, retries=3):
        for attempt in range(retries):
            try:
                return importlib.import_module(modname)
            except KeyError:
                # Clear any half-initialized module and retry
                sys.modules.pop(modname, None)
                if attempt == retries - 1:
                    break
        raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")

    def __getattr__(self, name: str):
        if name in self._sub_sdk_map:
            module_path, class_name = self._sub_sdk_map[name]
            try:
                module = self.dynamic_import(module_path)
                klass = getattr(module, class_name)
                instance = klass(self.sdk_configuration, parent_ref=self)
                setattr(self, name, instance)
                return instance
            except ImportError as e:
                raise AttributeError(
                    f"Failed to import module {module_path} for attribute {name}: {e}"
                ) from e
            except AttributeError as e:
                raise AttributeError(
                    f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
                ) from e

        raise AttributeError(
            f"'{type(self).__name__}' object has no attribute '{name}'"
        )

    def __dir__(self):
        default_attrs = list(super().__dir__())
        lazy_attrs = list(self._sub_sdk_map.keys())
        return sorted(list(set(default_attrs + lazy_attrs)))

    def __enter__(self):
        return self

    async def __aenter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.client is not None
            and not self.sdk_configuration.client_supplied
        ):
            self.sdk_configuration.client.close()
        self.sdk_configuration.client = None

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.async_client is not None
            and not self.sdk_configuration.async_client_supplied
        ):
            await self.sdk_configuration.async_client.aclose()
        self.sdk_configuration.async_client = None

    def verify_asset(
        self,
        *,
        asset: Union[models.AssetRefDto, models.AssetRefDtoTypedDict],
        mode: Optional[str] = "summary",
        allow_remote_manifests: Optional[bool] = False,
        allow_insecure_remote_http: Optional[bool] = False,
        include_certificates: Optional[bool] = False,
        cawg: Optional[
            Union[models.CawgVerifyDto, models.CawgVerifyDtoTypedDict]
        ] = None,
        limits: Optional[Union[models.LimitsDto, models.LimitsDtoTypedDict]] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.VerifyAssetResponse:
        r"""Verify the C2PA manifest of an asset

        Analyzes a digital asset to find, validate, and report on any embedded C2PA manifests. This allows you to confirm the asset's provenance, authenticity, and processing history.

        The asset is processed using memory-efficient streaming to temporary storage during verification. Returns detailed validation results including trust status, signer information, and any validation failures.


        :param asset: A reference to a digital asset, either stored in S3 or accessible via URL. Files are streamed efficiently to temporary storage during processing to minimize memory usage.
        :param mode: The level of detail to return in the verification report. * `summary`: A high-level pass/fail result with basic trust status. Fastest option for simple validation. * `info`: Basic information about the manifest, claims, and signing entities. * `detailed`: Comprehensive details of all assertions, claims, signatures, and validation steps. * `tree`: Hierarchical view of the manifest's ingredient relationships and provenance chain.
        :param allow_remote_manifests: Whether to allow fetching and validating remote manifests referenced in the asset's C2PA data.
        :param allow_insecure_remote_http: Whether to allow HTTP (non-HTTPS) URLs when fetching remote manifest resources. Disabled by default for security.
        :param include_certificates: Whether to include full certificate chains and cryptographic details in the verification report.
        :param cawg: Options controlling CAWG identity validation behavior during verification.
        :param limits: Optional limits for processing operations to prevent resource exhaustion. These limits apply to the streaming and processing phases of asset handling.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.VerifyRequest(
            asset=utils.get_pydantic_model(asset, models.AssetRefDto),
            mode=mode,
            allow_remote_manifests=allow_remote_manifests,
            allow_insecure_remote_http=allow_insecure_remote_http,
            include_certificates=include_certificates,
            cawg=utils.get_pydantic_model(cawg, Optional[models.CawgVerifyDto]),
            limits=utils.get_pydantic_model(limits, Optional[models.LimitsDto]),
        )

        req = self._build_request(
            method="POST",
            path="/v1/verify",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request, False, False, "json", models.VerifyRequest
            ),
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="verifyAsset",
                oauth2_scopes=[],
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "422", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.VerifyAssetResponse(
                result=unmarshal_json_response(models.VerifyResponse, http_res),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "422"], "application/problem+json"
        ):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "429", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)

        raise errors.QueDefaultError("Unexpected response received", http_res)

    async def verify_asset_async(
        self,
        *,
        asset: Union[models.AssetRefDto, models.AssetRefDtoTypedDict],
        mode: Optional[str] = "summary",
        allow_remote_manifests: Optional[bool] = False,
        allow_insecure_remote_http: Optional[bool] = False,
        include_certificates: Optional[bool] = False,
        cawg: Optional[
            Union[models.CawgVerifyDto, models.CawgVerifyDtoTypedDict]
        ] = None,
        limits: Optional[Union[models.LimitsDto, models.LimitsDtoTypedDict]] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.VerifyAssetResponse:
        r"""Verify the C2PA manifest of an asset

        Analyzes a digital asset to find, validate, and report on any embedded C2PA manifests. This allows you to confirm the asset's provenance, authenticity, and processing history.

        The asset is processed using memory-efficient streaming to temporary storage during verification. Returns detailed validation results including trust status, signer information, and any validation failures.


        :param asset: A reference to a digital asset, either stored in S3 or accessible via URL. Files are streamed efficiently to temporary storage during processing to minimize memory usage.
        :param mode: The level of detail to return in the verification report. * `summary`: A high-level pass/fail result with basic trust status. Fastest option for simple validation. * `info`: Basic information about the manifest, claims, and signing entities. * `detailed`: Comprehensive details of all assertions, claims, signatures, and validation steps. * `tree`: Hierarchical view of the manifest's ingredient relationships and provenance chain.
        :param allow_remote_manifests: Whether to allow fetching and validating remote manifests referenced in the asset's C2PA data.
        :param allow_insecure_remote_http: Whether to allow HTTP (non-HTTPS) URLs when fetching remote manifest resources. Disabled by default for security.
        :param include_certificates: Whether to include full certificate chains and cryptographic details in the verification report.
        :param cawg: Options controlling CAWG identity validation behavior during verification.
        :param limits: Optional limits for processing operations to prevent resource exhaustion. These limits apply to the streaming and processing phases of asset handling.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.VerifyRequest(
            asset=utils.get_pydantic_model(asset, models.AssetRefDto),
            mode=mode,
            allow_remote_manifests=allow_remote_manifests,
            allow_insecure_remote_http=allow_insecure_remote_http,
            include_certificates=include_certificates,
            cawg=utils.get_pydantic_model(cawg, Optional[models.CawgVerifyDto]),
            limits=utils.get_pydantic_model(limits, Optional[models.LimitsDto]),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1/verify",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request, False, False, "json", models.VerifyRequest
            ),
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="verifyAsset",
                oauth2_scopes=[],
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "422", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.VerifyAssetResponse(
                result=unmarshal_json_response(models.VerifyResponse, http_res),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "422"], "application/problem+json"
        ):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "429", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)

        raise errors.QueDefaultError("Unexpected response received", http_res)

    def sign_asset(
        self,
        *,
        asset: Union[models.AssetRefDto, models.AssetRefDtoTypedDict],
        mode: models.Mode,
        manifest_json: Optional[str] = None,
        cawg: Optional[
            Union[models.CawgIdentityDto, models.CawgIdentityDtoTypedDict]
        ] = None,
        allow_insecure_remote_http: Optional[bool] = False,
        limits: Optional[Union[models.LimitsDto, models.LimitsDtoTypedDict]] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.SignAssetResponse:
        r"""Sign an asset with a C2PA manifest

        Embeds a C2PA manifest into a digital asset and signs it using a server-side cryptographic key. The asset is processed using memory-efficient streaming to temporary storage before signing.

        This operation cryptographically links the asset to its provenance information, creating an immutable record of the asset's origin, authorship, and any processing history.


        :param asset: A reference to a digital asset, either stored in S3 or accessible via URL. Files are streamed efficiently to temporary storage during processing to minimize memory usage.
        :param mode: The signing mode to use. * `server_measure`: The server streams the asset, calculates its hash, and embeds the manifest. Requires `manifest_json`. This is the primary signing mode. * `client_hash`: The client provides the asset hash directly for offline signing. (Not yet implemented).
        :param manifest_json: JSON string containing the manifest to embed in the asset as a C2PA claim. This defines the provenance information and assertions about the asset. Required when `mode` is `server_measure`.
        :param cawg: Configuration to add a CAWG identity assertion during signing. Presence of this object enables CAWG.
        :param allow_insecure_remote_http: Whether to allow HTTP (non-HTTPS) URLs for remote manifest resources. Disabled by default for security.
        :param limits: Optional limits for processing operations to prevent resource exhaustion. These limits apply to the streaming and processing phases of asset handling.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.SignRequest(
            asset=utils.get_pydantic_model(asset, models.AssetRefDto),
            mode=mode,
            manifest_json=manifest_json,
            cawg=utils.get_pydantic_model(cawg, Optional[models.CawgIdentityDto]),
            allow_insecure_remote_http=allow_insecure_remote_http,
            limits=utils.get_pydantic_model(limits, Optional[models.LimitsDto]),
        )

        req = self._build_request(
            method="POST",
            path="/v1/sign",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request, False, False, "json", models.SignRequest
            ),
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="signAsset",
                oauth2_scopes=[],
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "422", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.SignAssetResponse(
                result=unmarshal_json_response(models.SignResponse, http_res),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "422"], "application/problem+json"
        ):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "429", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)

        raise errors.QueDefaultError("Unexpected response received", http_res)

    async def sign_asset_async(
        self,
        *,
        asset: Union[models.AssetRefDto, models.AssetRefDtoTypedDict],
        mode: models.Mode,
        manifest_json: Optional[str] = None,
        cawg: Optional[
            Union[models.CawgIdentityDto, models.CawgIdentityDtoTypedDict]
        ] = None,
        allow_insecure_remote_http: Optional[bool] = False,
        limits: Optional[Union[models.LimitsDto, models.LimitsDtoTypedDict]] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.SignAssetResponse:
        r"""Sign an asset with a C2PA manifest

        Embeds a C2PA manifest into a digital asset and signs it using a server-side cryptographic key. The asset is processed using memory-efficient streaming to temporary storage before signing.

        This operation cryptographically links the asset to its provenance information, creating an immutable record of the asset's origin, authorship, and any processing history.


        :param asset: A reference to a digital asset, either stored in S3 or accessible via URL. Files are streamed efficiently to temporary storage during processing to minimize memory usage.
        :param mode: The signing mode to use. * `server_measure`: The server streams the asset, calculates its hash, and embeds the manifest. Requires `manifest_json`. This is the primary signing mode. * `client_hash`: The client provides the asset hash directly for offline signing. (Not yet implemented).
        :param manifest_json: JSON string containing the manifest to embed in the asset as a C2PA claim. This defines the provenance information and assertions about the asset. Required when `mode` is `server_measure`.
        :param cawg: Configuration to add a CAWG identity assertion during signing. Presence of this object enables CAWG.
        :param allow_insecure_remote_http: Whether to allow HTTP (non-HTTPS) URLs for remote manifest resources. Disabled by default for security.
        :param limits: Optional limits for processing operations to prevent resource exhaustion. These limits apply to the streaming and processing phases of asset handling.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.SignRequest(
            asset=utils.get_pydantic_model(asset, models.AssetRefDto),
            mode=mode,
            manifest_json=manifest_json,
            cawg=utils.get_pydantic_model(cawg, Optional[models.CawgIdentityDto]),
            allow_insecure_remote_http=allow_insecure_remote_http,
            limits=utils.get_pydantic_model(limits, Optional[models.LimitsDto]),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1/sign",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request, False, False, "json", models.SignRequest
            ),
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="signAsset",
                oauth2_scopes=[],
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "422", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.SignAssetResponse(
                result=unmarshal_json_response(models.SignResponse, http_res),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "422"], "application/problem+json"
        ):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "429", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/problem+json"):
            response_data = unmarshal_json_response(
                errors.ProblemResponseErrorData, http_res
            )
            raise errors.ProblemResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.QueDefaultError("API error occurred", http_res, http_res_text)

        raise errors.QueDefaultError("Unexpected response received", http_res)
