# !!!
# 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.b2b.models.sso import (
    ConnectionImplicitRoleAssignment,
    GroupImplicitRoleAssignment,
    SAMLConnectionImplicitRoleAssignment,
    SAMLGroupImplicitRoleAssignment,
)
from stytch.b2b.models.sso_external import (
    CreateConnectionRequestOptions,
    CreateConnectionResponse,
    UpdateConnectionRequestOptions,
    UpdateConnectionResponse,
)
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient


class External:
    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 create_connection(
        self,
        organization_id: str,
        external_organization_id: str,
        external_connection_id: str,
        display_name: Optional[str] = None,
        connection_implicit_role_assignments: Optional[
            List[Union[SAMLConnectionImplicitRoleAssignment, Dict[str, Any]]]
        ] = None,
        group_implicit_role_assignments: Optional[
            List[Union[SAMLGroupImplicitRoleAssignment, Dict[str, Any]]]
        ] = None,
        method_options: Optional[CreateConnectionRequestOptions] = None,
    ) -> CreateConnectionResponse:
        """Create a new External SSO Connection.

        Fields:
          - 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.
          - external_organization_id: Globally unique UUID that identifies a different Organization within your Project.
          - external_connection_id: Globally unique UUID that identifies a specific SSO connection configured for a different Organization in your Project.
          - display_name: A human-readable display name for the connection.
          - connection_implicit_role_assignments: (no documentation yet)
          - group_implicit_role_assignments: (no documentation yet)
        """  # noqa
        headers: Dict[str, str] = {}
        if method_options is not None:
            headers = method_options.add_headers(headers)
        data: Dict[str, Any] = {
            "organization_id": organization_id,
            "external_organization_id": external_organization_id,
            "external_connection_id": external_connection_id,
        }
        if display_name is not None:
            data["display_name"] = display_name
        if connection_implicit_role_assignments is not None:
            data["connection_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in connection_implicit_role_assignments
            ]
        if group_implicit_role_assignments is not None:
            data["group_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in group_implicit_role_assignments
            ]

        url = self.api_base.url_for("/v1/b2b/sso/external/{organization_id}", data)
        res = self.sync_client.post(url, data, headers)
        return CreateConnectionResponse.from_json(res.response.status_code, res.json)

    async def create_connection_async(
        self,
        organization_id: str,
        external_organization_id: str,
        external_connection_id: str,
        display_name: Optional[str] = None,
        connection_implicit_role_assignments: Optional[
            List[SAMLConnectionImplicitRoleAssignment]
        ] = None,
        group_implicit_role_assignments: Optional[
            List[SAMLGroupImplicitRoleAssignment]
        ] = None,
        method_options: Optional[CreateConnectionRequestOptions] = None,
    ) -> CreateConnectionResponse:
        """Create a new External SSO Connection.

        Fields:
          - 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.
          - external_organization_id: Globally unique UUID that identifies a different Organization within your Project.
          - external_connection_id: Globally unique UUID that identifies a specific SSO connection configured for a different Organization in your Project.
          - display_name: A human-readable display name for the connection.
          - connection_implicit_role_assignments: (no documentation yet)
          - group_implicit_role_assignments: (no documentation yet)
        """  # noqa
        headers: Dict[str, str] = {}
        if method_options is not None:
            headers = method_options.add_headers(headers)
        data: Dict[str, Any] = {
            "organization_id": organization_id,
            "external_organization_id": external_organization_id,
            "external_connection_id": external_connection_id,
        }
        if display_name is not None:
            data["display_name"] = display_name
        if connection_implicit_role_assignments is not None:
            data["connection_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in connection_implicit_role_assignments
            ]
        if group_implicit_role_assignments is not None:
            data["group_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in group_implicit_role_assignments
            ]

        url = self.api_base.url_for("/v1/b2b/sso/external/{organization_id}", data)
        res = await self.async_client.post(url, data, headers)
        return CreateConnectionResponse.from_json(res.response.status, res.json)

    def update_connection(
        self,
        organization_id: str,
        connection_id: str,
        display_name: Optional[str] = None,
        external_connection_implicit_role_assignments: Optional[
            List[Union[ConnectionImplicitRoleAssignment, Dict[str, Any]]]
        ] = None,
        external_group_implicit_role_assignments: Optional[
            List[Union[GroupImplicitRoleAssignment, Dict[str, Any]]]
        ] = None,
        method_options: Optional[UpdateConnectionRequestOptions] = None,
    ) -> UpdateConnectionResponse:
        """Updates an existing External SSO connection.

        Fields:
          - 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.
          - connection_id: Globally unique UUID that identifies a specific External SSO Connection.
          - display_name: A human-readable display name for the connection.
          - external_connection_implicit_role_assignments: All Members who log in with this External connection will implicitly receive the specified Roles. See the [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment. Implicit role assignments are not supported for External connections if the underlying SSO connection is an OIDC connection.
          - external_group_implicit_role_assignments: Defines the names of the groups
         that grant specific role assignments. For each group-Role pair, if a Member logs in with this external connection and
         belongs to the specified group, they will be granted the associated Role. See the
         [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment. Before adding any group implicit role assignments to an external connection, you must add a "groups" key to the underlying SAML connection's
                 `attribute_mapping`. Make sure that the SAML connection IdP is configured to correctly send the group information. Implicit role assignments are not supported
                 for External connections if the underlying SSO connection is an OIDC connection.
        """  # noqa
        headers: Dict[str, str] = {}
        if method_options is not None:
            headers = method_options.add_headers(headers)
        data: Dict[str, Any] = {
            "organization_id": organization_id,
            "connection_id": connection_id,
        }
        if display_name is not None:
            data["display_name"] = display_name
        if external_connection_implicit_role_assignments is not None:
            data["external_connection_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in external_connection_implicit_role_assignments
            ]
        if external_group_implicit_role_assignments is not None:
            data["external_group_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in external_group_implicit_role_assignments
            ]

        url = self.api_base.url_for(
            "/v1/b2b/sso/external/{organization_id}/connections/{connection_id}", data
        )
        res = self.sync_client.put(url, data, headers)
        return UpdateConnectionResponse.from_json(res.response.status_code, res.json)

    async def update_connection_async(
        self,
        organization_id: str,
        connection_id: str,
        display_name: Optional[str] = None,
        external_connection_implicit_role_assignments: Optional[
            List[ConnectionImplicitRoleAssignment]
        ] = None,
        external_group_implicit_role_assignments: Optional[
            List[GroupImplicitRoleAssignment]
        ] = None,
        method_options: Optional[UpdateConnectionRequestOptions] = None,
    ) -> UpdateConnectionResponse:
        """Updates an existing External SSO connection.

        Fields:
          - 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.
          - connection_id: Globally unique UUID that identifies a specific External SSO Connection.
          - display_name: A human-readable display name for the connection.
          - external_connection_implicit_role_assignments: All Members who log in with this External connection will implicitly receive the specified Roles. See the [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment. Implicit role assignments are not supported for External connections if the underlying SSO connection is an OIDC connection.
          - external_group_implicit_role_assignments: Defines the names of the groups
         that grant specific role assignments. For each group-Role pair, if a Member logs in with this external connection and
         belongs to the specified group, they will be granted the associated Role. See the
         [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment. Before adding any group implicit role assignments to an external connection, you must add a "groups" key to the underlying SAML connection's
                 `attribute_mapping`. Make sure that the SAML connection IdP is configured to correctly send the group information. Implicit role assignments are not supported
                 for External connections if the underlying SSO connection is an OIDC connection.
        """  # noqa
        headers: Dict[str, str] = {}
        if method_options is not None:
            headers = method_options.add_headers(headers)
        data: Dict[str, Any] = {
            "organization_id": organization_id,
            "connection_id": connection_id,
        }
        if display_name is not None:
            data["display_name"] = display_name
        if external_connection_implicit_role_assignments is not None:
            data["external_connection_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in external_connection_implicit_role_assignments
            ]
        if external_group_implicit_role_assignments is not None:
            data["external_group_implicit_role_assignments"] = [
                item if isinstance(item, dict) else item.dict()
                for item in external_group_implicit_role_assignments
            ]

        url = self.api_base.url_for(
            "/v1/b2b/sso/external/{organization_id}/connections/{connection_id}", data
        )
        res = await self.async_client.put(url, data, headers)
        return UpdateConnectionResponse.from_json(res.response.status, res.json)
