# !!!
# 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

from stytch.b2b.models.idp_oauth import AuthorizeResponse, AuthorizeStartResponse
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient


class OAuth:
    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

    def authorize_start(
        self,
        client_id: str,
        redirect_uri: str,
        response_type: str,
        scopes: List[str],
        organization_id: Optional[str] = None,
        member_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        prompt: Optional[str] = None,
    ) -> AuthorizeStartResponse:
        """Initiates a request for authorization of a Connected App to access a Member's account.

        Call this endpoint using the query parameters from an OAuth Authorization request.
        This endpoint validates various fields (`scope`, `client_id`, `redirect_uri`, `prompt`, etc...) are correct and returns
        relevant information for rendering an OAuth Consent Screen.

        This endpoint returns:
        - A public representation of the Connected App requesting authorization
        - Whether _explicit_ consent must be granted before proceeding with the authorization
        - A list of scopes the Member has the ability to grant the Connected App

        Use this response to prompt the Member for consent (if necessary) before calling the [Submit OAuth Authorization](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize) endpoint.

        Exactly one of the following must be provided to identify the Member granting authorization:
        - `organization_id` + `member_id`
        - `session_token`
        - `session_jwt`

        If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
        One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.

        Fields:
          - client_id: The ID of the Connected App client.
          - redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow.  This field is required when using the `authorization_code` grant.
          - response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`.
          - scopes: An array of scopes requested by the client.
          - organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
          - member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
          - session_token: A secret token for a given Stytch Session.
          - session_jwt: The JSON Web Token (JWT) for a given Stytch Session.
          - prompt: Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
            "redirect_uri": redirect_uri,
            "response_type": response_type,
            "scopes": scopes,
        }
        if organization_id is not None:
            data["organization_id"] = organization_id
        if member_id is not None:
            data["member_id"] = member_id
        if session_token is not None:
            data["session_token"] = session_token
        if session_jwt is not None:
            data["session_jwt"] = session_jwt
        if prompt is not None:
            data["prompt"] = prompt

        url = self.api_base.url_for("/v1/b2b/idp/oauth/authorize/start", data)
        res = self.sync_client.post(url, data, headers)
        return AuthorizeStartResponse.from_json(res.response.status_code, res.json)

    async def authorize_start_async(
        self,
        client_id: str,
        redirect_uri: str,
        response_type: str,
        scopes: List[str],
        organization_id: Optional[str] = None,
        member_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        prompt: Optional[str] = None,
    ) -> AuthorizeStartResponse:
        """Initiates a request for authorization of a Connected App to access a Member's account.

        Call this endpoint using the query parameters from an OAuth Authorization request.
        This endpoint validates various fields (`scope`, `client_id`, `redirect_uri`, `prompt`, etc...) are correct and returns
        relevant information for rendering an OAuth Consent Screen.

        This endpoint returns:
        - A public representation of the Connected App requesting authorization
        - Whether _explicit_ consent must be granted before proceeding with the authorization
        - A list of scopes the Member has the ability to grant the Connected App

        Use this response to prompt the Member for consent (if necessary) before calling the [Submit OAuth Authorization](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize) endpoint.

        Exactly one of the following must be provided to identify the Member granting authorization:
        - `organization_id` + `member_id`
        - `session_token`
        - `session_jwt`

        If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
        One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.

        Fields:
          - client_id: The ID of the Connected App client.
          - redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow.  This field is required when using the `authorization_code` grant.
          - response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`.
          - scopes: An array of scopes requested by the client.
          - organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
          - member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
          - session_token: A secret token for a given Stytch Session.
          - session_jwt: The JSON Web Token (JWT) for a given Stytch Session.
          - prompt: Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "client_id": client_id,
            "redirect_uri": redirect_uri,
            "response_type": response_type,
            "scopes": scopes,
        }
        if organization_id is not None:
            data["organization_id"] = organization_id
        if member_id is not None:
            data["member_id"] = member_id
        if session_token is not None:
            data["session_token"] = session_token
        if session_jwt is not None:
            data["session_jwt"] = session_jwt
        if prompt is not None:
            data["prompt"] = prompt

        url = self.api_base.url_for("/v1/b2b/idp/oauth/authorize/start", data)
        res = await self.async_client.post(url, data, headers)
        return AuthorizeStartResponse.from_json(res.response.status, res.json)

    def authorize(
        self,
        consent_granted: bool,
        scopes: List[str],
        client_id: str,
        redirect_uri: str,
        response_type: str,
        organization_id: Optional[str] = None,
        member_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        prompt: Optional[str] = None,
        state: Optional[str] = None,
        nonce: Optional[str] = None,
        code_challenge: Optional[str] = None,
        resources: Optional[List[str]] = None,
    ) -> AuthorizeResponse:
        """Completes a request for authorization of a Connected App to access a Member's account.

        Call this endpoint using the query parameters from an OAuth Authorization request, after previously validating those parameters using the
        [Preflight Check](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize-start) API.
        Note that this endpoint takes in a few additional parameters the preflight check does not- `state`, `nonce`, and `code_challenge`.

        If the authorization was successful, the `redirect_uri` will contain a valid `authorization_code` embedded as a query parameter.
        If the authorization was unsuccessful, the `redirect_uri` will contain an OAuth2.1 `error_code`.
        In both cases, redirect the Member to the location for the response to be consumed by the Connected App.

        Exactly one of the following must be provided to identify the Member granting authorization:
        - `organization_id` + `member_id`
        - `session_token`
        - `session_jwt`

        If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
        One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.

        Fields:
          - consent_granted: Indicates whether the user granted the requested scopes.
          - scopes: An array of scopes requested by the client.
          - client_id: The ID of the Connected App client.
          - redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow.  This field is required when using the `authorization_code` grant.
          - response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`.
          - organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
          - member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
          - session_token: A secret token for a given Stytch Session.
          - session_jwt: The JSON Web Token (JWT) for a given Stytch Session.
          - prompt: Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
          - state: An opaque value used to maintain state between the request and callback.
          - nonce: A string used to associate a client session with an ID token to mitigate replay attacks.
          - code_challenge: A base64url encoded challenge derived from the code verifier for PKCE flows.
          - resources: (no documentation yet)
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "consent_granted": consent_granted,
            "scopes": scopes,
            "client_id": client_id,
            "redirect_uri": redirect_uri,
            "response_type": response_type,
        }
        if organization_id is not None:
            data["organization_id"] = organization_id
        if member_id is not None:
            data["member_id"] = member_id
        if session_token is not None:
            data["session_token"] = session_token
        if session_jwt is not None:
            data["session_jwt"] = session_jwt
        if prompt is not None:
            data["prompt"] = prompt
        if state is not None:
            data["state"] = state
        if nonce is not None:
            data["nonce"] = nonce
        if code_challenge is not None:
            data["code_challenge"] = code_challenge
        if resources is not None:
            data["resources"] = resources

        url = self.api_base.url_for("/v1/b2b/idp/oauth/authorize", data)
        res = self.sync_client.post(url, data, headers)
        return AuthorizeResponse.from_json(res.response.status_code, res.json)

    async def authorize_async(
        self,
        consent_granted: bool,
        scopes: List[str],
        client_id: str,
        redirect_uri: str,
        response_type: str,
        organization_id: Optional[str] = None,
        member_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        prompt: Optional[str] = None,
        state: Optional[str] = None,
        nonce: Optional[str] = None,
        code_challenge: Optional[str] = None,
        resources: Optional[List[str]] = None,
    ) -> AuthorizeResponse:
        """Completes a request for authorization of a Connected App to access a Member's account.

        Call this endpoint using the query parameters from an OAuth Authorization request, after previously validating those parameters using the
        [Preflight Check](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize-start) API.
        Note that this endpoint takes in a few additional parameters the preflight check does not- `state`, `nonce`, and `code_challenge`.

        If the authorization was successful, the `redirect_uri` will contain a valid `authorization_code` embedded as a query parameter.
        If the authorization was unsuccessful, the `redirect_uri` will contain an OAuth2.1 `error_code`.
        In both cases, redirect the Member to the location for the response to be consumed by the Connected App.

        Exactly one of the following must be provided to identify the Member granting authorization:
        - `organization_id` + `member_id`
        - `session_token`
        - `session_jwt`

        If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
        One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.

        Fields:
          - consent_granted: Indicates whether the user granted the requested scopes.
          - scopes: An array of scopes requested by the client.
          - client_id: The ID of the Connected App client.
          - redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow.  This field is required when using the `authorization_code` grant.
          - response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`.
          - organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
          - member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
          - session_token: A secret token for a given Stytch Session.
          - session_jwt: The JSON Web Token (JWT) for a given Stytch Session.
          - prompt: Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
          - state: An opaque value used to maintain state between the request and callback.
          - nonce: A string used to associate a client session with an ID token to mitigate replay attacks.
          - code_challenge: A base64url encoded challenge derived from the code verifier for PKCE flows.
          - resources: (no documentation yet)
        """  # noqa
        headers: Dict[str, str] = {}
        data: Dict[str, Any] = {
            "consent_granted": consent_granted,
            "scopes": scopes,
            "client_id": client_id,
            "redirect_uri": redirect_uri,
            "response_type": response_type,
        }
        if organization_id is not None:
            data["organization_id"] = organization_id
        if member_id is not None:
            data["member_id"] = member_id
        if session_token is not None:
            data["session_token"] = session_token
        if session_jwt is not None:
            data["session_jwt"] = session_jwt
        if prompt is not None:
            data["prompt"] = prompt
        if state is not None:
            data["state"] = state
        if nonce is not None:
            data["nonce"] = nonce
        if code_challenge is not None:
            data["code_challenge"] = code_challenge
        if resources is not None:
            data["resources"] = resources

        url = self.api_base.url_for("/v1/b2b/idp/oauth/authorize", data)
        res = await self.async_client.post(url, data, headers)
        return AuthorizeResponse.from_json(res.response.status, res.json)
