# !!!
# WARNING: This file is autogenerated
# Only modify code within MANUAL() sections
# or your changes may be overwritten later!
# !!!

from __future__ import annotations

from typing import Any, Dict, List, Optional, Union

from stytch.consumer.api.connected_apps_clients_secrets import Secrets
from stytch.consumer.models.connected_apps_clients import (
    CreateRequestClientType,
    CreateResponse,
    DeleteResponse,
    GetResponse,
    SearchResponse,
    UpdateResponse,
)
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient


class Clients:
    def __init__(
        self, api_base: ApiBase, sync_client: SyncClient, async_client: AsyncClient
    ) -> None:
        self.api_base = api_base
        self.sync_client = sync_client
        self.async_client = async_client
        self.secrets = Secrets(
            api_base=self.api_base,
            sync_client=self.sync_client,
            async_client=self.async_client,
        )

    def get(
        self,
        client_id: str,
    ) -> GetResponse:
        """Retrieve details of a specific Connected App by `client_id`.

        Fields:
          - client_id: The ID of the Connected App client.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = self.sync_client.get(url, data, headers)
        return GetResponse.from_json(res.response.status_code, res.json)

    async def get_async(
        self,
        client_id: str,
    ) -> GetResponse:
        """Retrieve details of a specific Connected App by `client_id`.

        Fields:
          - client_id: The ID of the Connected App client.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = await self.async_client.get(url, data, headers)
        return GetResponse.from_json(res.response.status, res.json)

    def update(
        self,
        client_id: str,
        client_name: Optional[str] = None,
        client_description: Optional[str] = None,
        redirect_urls: Optional[List[str]] = None,
        full_access_allowed: Optional[bool] = None,
        access_token_expiry_minutes: Optional[int] = None,
        access_token_custom_audience: Optional[str] = None,
        access_token_template_content: Optional[str] = None,
        post_logout_redirect_urls: Optional[List[str]] = None,
        logo_url: Optional[str] = None,
        bypass_consent_for_offline_access: Optional[bool] = None,
    ) -> UpdateResponse:
        """Updates mutable fields of a Connected App. Cannot update Client Type, Client ID, or Secrets.

        Fields:
          - client_id: The ID of the client.
          - client_name: A human-readable name for the client.
          - client_description: A human-readable description for the client.
          - redirect_urls: Array of redirect URI values for use in OAuth Authorization flows.
          - full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
          - access_token_expiry_minutes: The number of minutes before the access token expires. The default is 60 minutes.
          - access_token_custom_audience: The custom audience for the access token.
          - access_token_template_content: The content of the access token custom claims template. The template must be a valid JSON object.
          - post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows.
          - logo_url: The logo URL of the Connected App, if any.
          - bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need to request explicit user consent for the `offline_access` scope.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }
        if client_name is not None:
            data["client_name"] = client_name
        if client_description is not None:
            data["client_description"] = client_description
        if redirect_urls is not None:
            data["redirect_urls"] = redirect_urls
        if full_access_allowed is not None:
            data["full_access_allowed"] = full_access_allowed
        if access_token_expiry_minutes is not None:
            data["access_token_expiry_minutes"] = access_token_expiry_minutes
        if access_token_custom_audience is not None:
            data["access_token_custom_audience"] = access_token_custom_audience
        if access_token_template_content is not None:
            data["access_token_template_content"] = access_token_template_content
        if post_logout_redirect_urls is not None:
            data["post_logout_redirect_urls"] = post_logout_redirect_urls
        if logo_url is not None:
            data["logo_url"] = logo_url
        if bypass_consent_for_offline_access is not None:
            data["bypass_consent_for_offline_access"] = (
                bypass_consent_for_offline_access
            )

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = self.sync_client.put(url, data, headers)
        return UpdateResponse.from_json(res.response.status_code, res.json)

    async def update_async(
        self,
        client_id: str,
        client_name: Optional[str] = None,
        client_description: Optional[str] = None,
        redirect_urls: Optional[List[str]] = None,
        full_access_allowed: Optional[bool] = None,
        access_token_expiry_minutes: Optional[int] = None,
        access_token_custom_audience: Optional[str] = None,
        access_token_template_content: Optional[str] = None,
        post_logout_redirect_urls: Optional[List[str]] = None,
        logo_url: Optional[str] = None,
        bypass_consent_for_offline_access: Optional[bool] = None,
    ) -> UpdateResponse:
        """Updates mutable fields of a Connected App. Cannot update Client Type, Client ID, or Secrets.

        Fields:
          - client_id: The ID of the client.
          - client_name: A human-readable name for the client.
          - client_description: A human-readable description for the client.
          - redirect_urls: Array of redirect URI values for use in OAuth Authorization flows.
          - full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
          - access_token_expiry_minutes: The number of minutes before the access token expires. The default is 60 minutes.
          - access_token_custom_audience: The custom audience for the access token.
          - access_token_template_content: The content of the access token custom claims template. The template must be a valid JSON object.
          - post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows.
          - logo_url: The logo URL of the Connected App, if any.
          - bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need to request explicit user consent for the `offline_access` scope.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }
        if client_name is not None:
            data["client_name"] = client_name
        if client_description is not None:
            data["client_description"] = client_description
        if redirect_urls is not None:
            data["redirect_urls"] = redirect_urls
        if full_access_allowed is not None:
            data["full_access_allowed"] = full_access_allowed
        if access_token_expiry_minutes is not None:
            data["access_token_expiry_minutes"] = access_token_expiry_minutes
        if access_token_custom_audience is not None:
            data["access_token_custom_audience"] = access_token_custom_audience
        if access_token_template_content is not None:
            data["access_token_template_content"] = access_token_template_content
        if post_logout_redirect_urls is not None:
            data["post_logout_redirect_urls"] = post_logout_redirect_urls
        if logo_url is not None:
            data["logo_url"] = logo_url
        if bypass_consent_for_offline_access is not None:
            data["bypass_consent_for_offline_access"] = (
                bypass_consent_for_offline_access
            )

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = await self.async_client.put(url, data, headers)
        return UpdateResponse.from_json(res.response.status, res.json)

    def delete(
        self,
        client_id: str,
    ) -> DeleteResponse:
        """Deletes a Connected App.

        Fields:
          - client_id: The ID of the client.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = self.sync_client.delete(url, headers)
        return DeleteResponse.from_json(res.response.status_code, res.json)

    async def delete_async(
        self,
        client_id: str,
    ) -> DeleteResponse:
        """Deletes a Connected App.

        Fields:
          - client_id: The ID of the client.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
        }

        url = self.api_base.url_for("/v1/connected_apps/clients/{client_id}", data)
        res = await self.async_client.delete(url, headers)
        return DeleteResponse.from_json(res.response.status, res.json)

    def search(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> SearchResponse:
        """Search for Connected Apps. Supports cursor-based pagination. Specific filters coming soon.

        Fields:
          - cursor: The `cursor` field allows you to paginate through your results. Each result array is limited to 1000 results. If your query returns more than 1000 results, you will need to paginate the responses using the `cursor`. If you receive a response that includes a non-null `next_cursor` in the `results_metadata` object, repeat the search call with the `next_cursor` value set to the `cursor` field to retrieve the next page of results. Continue to make search calls until the `next_cursor` in the response is null.
          - limit: The number of search results to return per page. The default limit is 100. A maximum of 1000 results can be returned by a single search request. If the total size of your result set is greater than one page size, you must paginate the response. See the `cursor` field.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {}
        if cursor is not None:
            data["cursor"] = cursor
        if limit is not None:
            data["limit"] = limit

        url = self.api_base.url_for("/v1/connected_apps/clients/search", data)
        res = self.sync_client.post(url, data, headers)
        return SearchResponse.from_json(res.response.status_code, res.json)

    async def search_async(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> SearchResponse:
        """Search for Connected Apps. Supports cursor-based pagination. Specific filters coming soon.

        Fields:
          - cursor: The `cursor` field allows you to paginate through your results. Each result array is limited to 1000 results. If your query returns more than 1000 results, you will need to paginate the responses using the `cursor`. If you receive a response that includes a non-null `next_cursor` in the `results_metadata` object, repeat the search call with the `next_cursor` value set to the `cursor` field to retrieve the next page of results. Continue to make search calls until the `next_cursor` in the response is null.
          - limit: The number of search results to return per page. The default limit is 100. A maximum of 1000 results can be returned by a single search request. If the total size of your result set is greater than one page size, you must paginate the response. See the `cursor` field.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {}
        if cursor is not None:
            data["cursor"] = cursor
        if limit is not None:
            data["limit"] = limit

        url = self.api_base.url_for("/v1/connected_apps/clients/search", data)
        res = await self.async_client.post(url, data, headers)
        return SearchResponse.from_json(res.response.status, res.json)

    def create(
        self,
        client_type: Union[CreateRequestClientType, str],
        redirect_urls: List[str],
        full_access_allowed: bool,
        post_logout_redirect_urls: List[str],
        client_name: Optional[str] = None,
        client_description: Optional[str] = None,
        access_token_expiry_minutes: Optional[int] = None,
        access_token_custom_audience: Optional[str] = None,
        access_token_template_content: Optional[str] = None,
        logo_url: Optional[str] = None,
        bypass_consent_for_offline_access: Optional[bool] = None,
    ) -> CreateResponse:
        """Creates a new Connected App. If the Connected App `client_type` is `first_party` or `third_party` a `client_secret` is returned.

        **Important:** This is the only time you will be able to view the generated `client_secret` in the API response. Stytch stores a hash of the `client_secret` and cannot recover the value if lost. Be sure to persist the `client_secret` in a secure location. If the `client_secret` is lost, you will need to trigger a secret rotation flow to receive another one.

        Fields:
          - client_type: The type of Connected App. Supported values are `first_party`, `first_party_public`, `third_party`, and `third_party_public`.
          - redirect_urls: Array of redirect URI values for use in OAuth Authorization flows.
          - full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
          - post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows.
          - client_name: A human-readable name for the client.
          - client_description: A human-readable description for the client.
          - access_token_expiry_minutes: The number of minutes before the access token expires. The default is 60 minutes.
          - access_token_custom_audience: The custom audience for the access token.
          - access_token_template_content: The content of the access token custom claims template. The template must be a valid JSON object.
          - logo_url: The logo URL of the Connected App, if any.
          - bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need to request explicit user consent for the `offline_access` scope.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_type": client_type,
            "redirect_urls": redirect_urls,
            "full_access_allowed": full_access_allowed,
            "post_logout_redirect_urls": post_logout_redirect_urls,
        }
        if client_name is not None:
            data["client_name"] = client_name
        if client_description is not None:
            data["client_description"] = client_description
        if access_token_expiry_minutes is not None:
            data["access_token_expiry_minutes"] = access_token_expiry_minutes
        if access_token_custom_audience is not None:
            data["access_token_custom_audience"] = access_token_custom_audience
        if access_token_template_content is not None:
            data["access_token_template_content"] = access_token_template_content
        if logo_url is not None:
            data["logo_url"] = logo_url
        if bypass_consent_for_offline_access is not None:
            data["bypass_consent_for_offline_access"] = (
                bypass_consent_for_offline_access
            )

        url = self.api_base.url_for("/v1/connected_apps/clients", data)
        res = self.sync_client.post(url, data, headers)
        return CreateResponse.from_json(res.response.status_code, res.json)

    async def create_async(
        self,
        client_type: CreateRequestClientType,
        redirect_urls: List[str],
        full_access_allowed: bool,
        post_logout_redirect_urls: List[str],
        client_name: Optional[str] = None,
        client_description: Optional[str] = None,
        access_token_expiry_minutes: Optional[int] = None,
        access_token_custom_audience: Optional[str] = None,
        access_token_template_content: Optional[str] = None,
        logo_url: Optional[str] = None,
        bypass_consent_for_offline_access: Optional[bool] = None,
    ) -> CreateResponse:
        """Creates a new Connected App. If the Connected App `client_type` is `first_party` or `third_party` a `client_secret` is returned.

        **Important:** This is the only time you will be able to view the generated `client_secret` in the API response. Stytch stores a hash of the `client_secret` and cannot recover the value if lost. Be sure to persist the `client_secret` in a secure location. If the `client_secret` is lost, you will need to trigger a secret rotation flow to receive another one.

        Fields:
          - client_type: The type of Connected App. Supported values are `first_party`, `first_party_public`, `third_party`, and `third_party_public`.
          - redirect_urls: Array of redirect URI values for use in OAuth Authorization flows.
          - full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
          - post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows.
          - client_name: A human-readable name for the client.
          - client_description: A human-readable description for the client.
          - access_token_expiry_minutes: The number of minutes before the access token expires. The default is 60 minutes.
          - access_token_custom_audience: The custom audience for the access token.
          - access_token_template_content: The content of the access token custom claims template. The template must be a valid JSON object.
          - logo_url: The logo URL of the Connected App, if any.
          - bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need to request explicit user consent for the `offline_access` scope.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_type": client_type,
            "redirect_urls": redirect_urls,
            "full_access_allowed": full_access_allowed,
            "post_logout_redirect_urls": post_logout_redirect_urls,
        }
        if client_name is not None:
            data["client_name"] = client_name
        if client_description is not None:
            data["client_description"] = client_description
        if access_token_expiry_minutes is not None:
            data["access_token_expiry_minutes"] = access_token_expiry_minutes
        if access_token_custom_audience is not None:
            data["access_token_custom_audience"] = access_token_custom_audience
        if access_token_template_content is not None:
            data["access_token_template_content"] = access_token_template_content
        if logo_url is not None:
            data["logo_url"] = logo_url
        if bypass_consent_for_offline_access is not None:
            data["bypass_consent_for_offline_access"] = (
                bypass_consent_for_offline_access
            )

        url = self.api_base.url_for("/v1/connected_apps/clients", data)
        res = await self.async_client.post(url, data, headers)
        return CreateResponse.from_json(res.response.status, res.json)
