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

from typing import Any, Dict, List, Optional

import pydantic

from stytch.b2b.models.organizations import (
    CreateResponse,
    DeleteMemberResponse,
    DeleteResponse,
    GetResponse,
    SearchMembersResponse,
    SearchResponse,
    UpdateResponse,
)
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient
from stytch.core.models import SearchQuery


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

    @property
    def sub_url(self) -> str:
        return "organizations"

    def create(
        self,
        organization_name: str,
        organization_slug: str,
        trusted_metadata: Optional[Dict[str, Any]] = None,
        email_jit_provisioning: Optional[str] = None,
        email_invites: Optional[str] = None,
        email_allowed_domains: Optional[List[str]] = None,
        sso_jit_provisioning: Optional[str] = None,
    ) -> CreateResponse:
        """Creates a new Organization. It requires a name and a unique slug.

        See the Organization authentication settings resource to learn more about fields like email_jit_provisioning, email_allowed_domains, sso_jit_provisioning, etc., and their behaviors.

        Parameters:

        - `organization_name`: The name of the Organization.

        - `organization_slug`: The unique URL slug of the Organization.

        - `organzation_logo_url`: The image URL of the Organization’s logo.

        - `trusted_metadata`: An arbitrary JSON object for storing application-specific data.

        - `email_jit_provisioning`: The setting that controls the JIT provisioning of new Members when authenticating via email. The accepted values are:

          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be provisioned upon authentication.
          - NOT_ALLOWED – disable JIT provisioning.

        - `email_invites`: The setting that controls how a new Member can be invited to an organization by email. The accepted values are:

          - ALL_ALLOWED – any new Member can be invited to join
          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be invited
          - NOT_ALLOWED – disable invites

        - `email_allowed_domains`: An array of email domains that allow invitations or JIT provisioning for new Members. This list is enforced when either email_invites or email_jit_provisioning is set to RESTRICTED.

        - `sso_jit_provisioning`: The setting that controls the JIT provisioning of Members when authenticating via SSO. The accepted values are:
          - ALL_ALLOWED – any new Member can be provisioned upon authentication
          - RESTRICTED – only new Members with SSO logins that comply with sso_jit_provisioning_allowed_connections can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_name": organization_name,
            "organization_slug": organization_slug,
        }

        if trusted_metadata is not None:
            payload["trusted_metadata"] = trusted_metadata
        if email_jit_provisioning is not None:
            payload["email_jit_provisioning"] = email_jit_provisioning
        if email_invites is not None:
            payload["email_invites"] = email_invites
        if email_allowed_domains is not None:
            payload["email_allowed_domains"] = email_allowed_domains
        if sso_jit_provisioning is not None:
            payload["sso_jit_provisioning"] = sso_jit_provisioning

        url = self.api_base.route_with_sub_url(self.sub_url, None)

        res = self.sync_client.post(url, json=payload)
        return CreateResponse.from_json(res.response.status_code, res.json)

    async def create_async(
        self,
        organization_name: str,
        organization_slug: str,
        trusted_metadata: Optional[Dict[str, Any]] = None,
        email_jit_provisioning: Optional[str] = None,
        email_invites: Optional[str] = None,
        email_allowed_domains: Optional[List[str]] = None,
        sso_jit_provisioning: Optional[str] = None,
    ) -> CreateResponse:
        """Creates a new Organization. It requires a name and a unique slug.

        See the Organization authentication settings resource to learn more about fields like email_jit_provisioning, email_allowed_domains, sso_jit_provisioning, etc., and their behaviors.

        Parameters:

        - `organization_name`: The name of the Organization.

        - `organization_slug`: The unique URL slug of the Organization.

        - `organzation_logo_url`: The image URL of the Organization’s logo.

        - `trusted_metadata`: An arbitrary JSON object for storing application-specific data.

        - `email_jit_provisioning`: The setting that controls the JIT provisioning of new Members when authenticating via email. The accepted values are:

          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be provisioned upon authentication.
          - NOT_ALLOWED – disable JIT provisioning.

        - `email_invites`: The setting that controls how a new Member can be invited to an organization by email. The accepted values are:

          - ALL_ALLOWED – any new Member can be invited to join
          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be invited
          - NOT_ALLOWED – disable invites

        - `email_allowed_domains`: An array of email domains that allow invitations or JIT provisioning for new Members. This list is enforced when either email_invites or email_jit_provisioning is set to RESTRICTED.

        - `sso_jit_provisioning`: The setting that controls the JIT provisioning of Members when authenticating via SSO. The accepted values are:
          - ALL_ALLOWED – any new Member can be provisioned upon authentication
          - RESTRICTED – only new Members with SSO logins that comply with sso_jit_provisioning_allowed_connections can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_name": organization_name,
            "organization_slug": organization_slug,
        }

        if trusted_metadata is not None:
            payload["trusted_metadata"] = trusted_metadata
        if email_jit_provisioning is not None:
            payload["email_jit_provisioning"] = email_jit_provisioning
        if email_invites is not None:
            payload["email_invites"] = email_invites
        if email_allowed_domains is not None:
            payload["email_allowed_domains"] = email_allowed_domains
        if sso_jit_provisioning is not None:
            payload["sso_jit_provisioning"] = sso_jit_provisioning

        url = self.api_base.route_with_sub_url(self.sub_url, None)

        res = await self.async_client.post(url, json=payload)
        return CreateResponse.from_json(res.response.status, res.json)

    def get(
        self,
        organization_id: str,
    ) -> GetResponse:
        """Returns an Organization specified by organization_id.

        Parameters:

        - `organization_id`: Globally unique UUID that identifies a specific Organization in the Stytch API. The organization_id is critical to perform operations on an Organization in the Stytch API, so be sure to preserve this value.
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_id": organization_id,
        }

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = self.sync_client.get(url, params=payload)
        return GetResponse.from_json(res.response.status_code, res.json)

    async def get_async(
        self,
        organization_id: str,
    ) -> GetResponse:
        """Returns an Organization specified by organization_id.

        Parameters:

        - `organization_id`: Globally unique UUID that identifies a specific Organization in the Stytch API. The organization_id is critical to perform operations on an Organization in the Stytch API, so be sure to preserve this value.
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_id": organization_id,
        }

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = await self.async_client.get(url, params=payload)
        return GetResponse.from_json(res.response.status, res.json)

    def update(
        self,
        organization_id: str,
        organization_name: Optional[str] = None,
        organization_slug: Optional[str] = None,
        organization_logo_url: Optional[str] = None,
        trusted_metadata: Optional[Dict[str, Any]] = None,
        sso_default_connection_id: Optional[str] = None,
        sso_jit_provisioning_allowed_connections: Optional[List[str]] = None,
        sso_jit_provisioning: Optional[str] = None,
        email_allowed_domains: Optional[List[str]] = None,
        email_jit_provisioning: Optional[str] = None,
        email_invites: Optional[str] = None,
    ) -> UpdateResponse:
        """Updates an Organization specified by organization_id.

        See the Organization authentication settings resource to learn more about fields like email_jit_provisioning, email_allowed_domains, sso_jit_provisioning, etc., and their behaviors.

        Parameters:

        - `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.

        - `organization_name`: The name of the Organization.

        - `organization_slug`: The unique URL slug of the Organization.

        - `organization_logo_url`: The image URL of the Organization’s logo.

        - `trusted_metadata`: An arbitrary JSON object for storing application-specific data.

        - `sso_default_connection_id`: The default connection used for SSO when there are multiple active connections.

        - `sso_jit_provisioning_allowed_connections`: An array of connections used for SSO when sso_jit_provisiniong is set to RESTRICTED.

        - `sso_jit_provisioning`: The setting that controls the JIT provisioning of Members when authenticating via SSO. The accepted values are:

          - ALL_ALLOWED – any new Member can be provisioned upon authentication
          - RESTRICTED – only new Members with SSO logins that comply with sso_jit_provisioning_allowed_connections can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning

        - `email_allowed_domains`: An array of email domains that allow invitations or JIT provisioning for new Members. This list is enforced when either email_invites or email_jit_provisioning is set to RESTRICTED. To remove or add domains, you must pass in the full array with all its values.

        - `email_jit_provisioning`: The setting that controls the JIT provisioning of new Members when authenticating via email. The accepted values are:

          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning

        - `email_invites`: The setting that controls how a new Member can be invited to an Organization by email. The three accepted values are:
          - ALL_ALLOWED – any new Member can be invited to join
          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be invited
          - NOT_ALLOWED – disable invites
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_id": organization_id,
        }

        if organization_name is not None:
            payload["organization_name"] = organization_name
        if organization_slug is not None:
            payload["organization_slug"] = organization_slug
        if organization_logo_url is not None:
            payload["organization_logo_url"] = organization_logo_url
        if trusted_metadata is not None:
            payload["trusted_metadata"] = trusted_metadata
        if sso_default_connection_id is not None:
            payload["sso_default_connection_id"] = sso_default_connection_id
        if sso_jit_provisioning_allowed_connections is not None:
            payload[
                "sso_jit_provisioning_allowed_connections"
            ] = sso_jit_provisioning_allowed_connections
        if sso_jit_provisioning is not None:
            payload["sso_jit_provisioning"] = sso_jit_provisioning
        if email_allowed_domains is not None:
            payload["email_allowed_domains"] = email_allowed_domains
        if email_jit_provisioning is not None:
            payload["email_jit_provisioning"] = email_jit_provisioning
        if email_invites is not None:
            payload["email_invites"] = email_invites

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = self.sync_client.put(url, json=payload)
        return UpdateResponse.from_json(res.response.status_code, res.json)

    async def update_async(
        self,
        organization_id: str,
        organization_name: Optional[str] = None,
        organization_slug: Optional[str] = None,
        organization_logo_url: Optional[str] = None,
        trusted_metadata: Optional[Dict[str, Any]] = None,
        sso_default_connection_id: Optional[str] = None,
        sso_jit_provisioning_allowed_connections: Optional[List[str]] = None,
        sso_jit_provisioning: Optional[str] = None,
        email_allowed_domains: Optional[List[str]] = None,
        email_jit_provisioning: Optional[str] = None,
        email_invites: Optional[str] = None,
    ) -> UpdateResponse:
        """Updates an Organization specified by organization_id.

        See the Organization authentication settings resource to learn more about fields like email_jit_provisioning, email_allowed_domains, sso_jit_provisioning, etc., and their behaviors.

        Parameters:

        - `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.

        - `organization_name`: The name of the Organization.

        - `organization_slug`: The unique URL slug of the Organization.

        - `organization_logo_url`: The image URL of the Organization’s logo.

        - `trusted_metadata`: An arbitrary JSON object for storing application-specific data.

        - `sso_default_connection_id`: The default connection used for SSO when there are multiple active connections.

        - `sso_jit_provisioning_allowed_connections`: An array of connections used for SSO when sso_jit_provisiniong is set to RESTRICTED.

        - `sso_jit_provisioning`: The setting that controls the JIT provisioning of Members when authenticating via SSO. The accepted values are:

          - ALL_ALLOWED – any new Member can be provisioned upon authentication
          - RESTRICTED – only new Members with SSO logins that comply with sso_jit_provisioning_allowed_connections can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning

        - `email_allowed_domains`: An array of email domains that allow invitations or JIT provisioning for new Members. This list is enforced when either email_invites or email_jit_provisioning is set to RESTRICTED. To remove or add domains, you must pass in the full array with all its values.

        - `email_jit_provisioning`: The setting that controls the JIT provisioning of new Members when authenticating via email. The accepted values are:

          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be provisioned upon authentication
          - NOT_ALLOWED – disable JIT provisioning

        - `email_invites`: The setting that controls how a new Member can be invited to an Organization by email. The three accepted values are:
          - ALL_ALLOWED – any new Member can be invited to join
          - RESTRICTED – only new Members with verified emails that comply with email_allowed_domains can be invited
          - NOT_ALLOWED – disable invites
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_id": organization_id,
        }

        if organization_name is not None:
            payload["organization_name"] = organization_name
        if organization_slug is not None:
            payload["organization_slug"] = organization_slug
        if organization_logo_url is not None:
            payload["organization_logo_url"] = organization_logo_url
        if trusted_metadata is not None:
            payload["trusted_metadata"] = trusted_metadata
        if sso_default_connection_id is not None:
            payload["sso_default_connection_id"] = sso_default_connection_id
        if sso_jit_provisioning_allowed_connections is not None:
            payload[
                "sso_jit_provisioning_allowed_connections"
            ] = sso_jit_provisioning_allowed_connections
        if sso_jit_provisioning is not None:
            payload["sso_jit_provisioning"] = sso_jit_provisioning
        if email_allowed_domains is not None:
            payload["email_allowed_domains"] = email_allowed_domains
        if email_jit_provisioning is not None:
            payload["email_jit_provisioning"] = email_jit_provisioning
        if email_invites is not None:
            payload["email_invites"] = email_invites

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = await self.async_client.put(url, json=payload)
        return UpdateResponse.from_json(res.response.status, res.json)

    def delete(
        self,
        organization_id: str,
    ) -> DeleteResponse:
        """Deletes an Organization, its Members, its Sessions, and other resources under it.

        Parameters:

        - `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.
        """  # noqa

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = self.sync_client.delete(url)
        return DeleteResponse.from_json(res.response.status_code, res.json)

    async def delete_async(
        self,
        organization_id: str,
    ) -> DeleteResponse:
        """Deletes an Organization, its Members, its Sessions, and other resources under it.

        Parameters:

        - `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.
        """  # noqa

        url = self.api_base.route_with_sub_url(self.sub_url, organization_id)

        res = await self.async_client.delete(url)
        return DeleteResponse.from_json(res.response.status, res.json)

    def delete_member(
        self,
        organization_id: str,
        member_id: str,
    ) -> DeleteMemberResponse:
        """Deletes a Member from an Organization.

        Parameters:

        - `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.

        - `member_id`: Globally unique UUID that identifies a specific Member in the Stytch API. The member_id is critical to perform operations on a Member, so be sure to preserve this value.
        """  # noqa

        url = self.api_base.route_with_sub_url(
            self.sub_url, f"{organization_id}/member/{member_id}"
        )

        res = self.sync_client.delete(url)
        return DeleteMemberResponse.from_json(res.response.status_code, res.json)

    async def delete_member_async(
        self,
        organization_id: str,
        member_id: str,
    ) -> DeleteMemberResponse:
        """Deletes a Member from an Organization.

        Parameters:

        - `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.

        - `member_id`: Globally unique UUID that identifies a specific Member in the Stytch API. The member_id is critical to perform operations on a Member, so be sure to preserve this value.
        """  # noqa

        url = self.api_base.route_with_sub_url(
            self.sub_url, f"{organization_id}/member/{member_id}"
        )

        res = await self.async_client.delete(url)
        return DeleteMemberResponse.from_json(res.response.status, res.json)

    def search(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
        query: Optional[SearchQuery] = None,
    ) -> SearchResponse:
        """Search for Organizations. If you send a request with no body params, no filtering will be applied and the endpoint will return all Organizations.

        All fuzzy search filters require a minimum of at least 3 characters

        Parameters:

        - `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, you should repeat the call, being sure to include all of the original fields, but pass in the next_cursor in the cursor field. Continue to make calls until the next_cursor in the response is null.

        - `limit`: The number of Organizations to return per page, the default is 100. A maximum of 1000 Organizations can be returned by a single request. If the total size of your result is greater than one page size, you must paginate the response. See the cursor field above.

        - `query`: The optional query object contains the operator, e.g. AND or OR, and the operands that will filter your Organizations. Only an operator is required, if you include no operands, no filtering will be applied. Similarly if you include no query object, no filtering is applied and we'll return all of your Organizations with no filtering applied.
        """  # noqa

        payload: Dict[str, Any] = {}

        if cursor is not None:
            payload["cursor"] = cursor
        if limit is not None:
            payload["limit"] = limit
        if query is not None:
            payload["query"] = query

        url = self.api_base.route_with_sub_url(self.sub_url, "search")

        res = self.sync_client.post(url, json=payload)
        return SearchResponse.from_json(res.response.status_code, res.json)

    async def search_async(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
        query: Optional[SearchQuery] = None,
    ) -> SearchResponse:
        """Search for Organizations. If you send a request with no body params, no filtering will be applied and the endpoint will return all Organizations.

        All fuzzy search filters require a minimum of at least 3 characters

        Parameters:

        - `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, you should repeat the call, being sure to include all of the original fields, but pass in the next_cursor in the cursor field. Continue to make calls until the next_cursor in the response is null.

        - `limit`: The number of Organizations to return per page, the default is 100. A maximum of 1000 Organizations can be returned by a single request. If the total size of your result is greater than one page size, you must paginate the response. See the cursor field above.

        - `query`: The optional query object contains the operator, e.g. AND or OR, and the operands that will filter your Organizations. Only an operator is required, if you include no operands, no filtering will be applied. Similarly if you include no query object, no filtering is applied and we'll return all of your Organizations with no filtering applied.
        """  # noqa

        payload: Dict[str, Any] = {}

        if cursor is not None:
            payload["cursor"] = cursor
        if limit is not None:
            payload["limit"] = limit
        if query is not None:
            payload["query"] = query

        url = self.api_base.route_with_sub_url(self.sub_url, "search")

        res = await self.async_client.post(url, json=payload)
        return SearchResponse.from_json(res.response.status, res.json)

    def search_members(
        self,
        organization_ids: List[str],
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
        query: Optional[SearchQuery] = None,
    ) -> SearchMembersResponse:
        """Search for members within an Organization. It requires an organization_id. Submitting an empty query returns all Members of an Organization.

        Parameters:

        - `organization_ids`: List of globally unique UUIDs that identify specific Organizations. The organization_id is critical to perform operations on an Organization, so be sure to preserve this value.

        - `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, you should repeat the call, being sure to include all of the original fields, but pass in the next_cursor in the cursor field. Continue to make calls until the next_cursor in the response is null.

        - `limit`: The number of Organizations to return per page, the default is 100. A maximum of 1000 Members can be returned by a single request. If the total size of your result is greater than one page size, you must paginate the response. See the cursor field above.

        - `query`: The optional query object contains the operator, e.g. AND or OR, and the operands that will filter your Members. Only an operator is required, if you include no operands, no filtering will be applied. Similarly if you include no query object, no filtering is applied and we'll return all of your Members with no filtering applied.
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_ids": organization_ids,
        }

        if cursor is not None:
            payload["cursor"] = cursor
        if limit is not None:
            payload["limit"] = limit
        if query is not None:
            payload["query"] = (
                query.dict() if isinstance(query, pydantic.BaseModel) else query
            )

        url = self.api_base.route_with_sub_url(self.sub_url, "members/search")

        res = self.sync_client.post(url, json=payload)
        return SearchMembersResponse.from_json(res.response.status_code, res.json)

    async def search_members_async(
        self,
        organization_ids: List[str],
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
        query: Optional[SearchQuery] = None,
    ) -> SearchMembersResponse:
        """Search for members within an Organization. It requires an organization_id. Submitting an empty query returns all Members of an Organization.

        Parameters:

        - `organization_ids`: List of globally unique UUIDs that identify specific Organizations. The organization_id is critical to perform operations on an Organization, so be sure to preserve this value.

        - `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, you should repeat the call, being sure to include all of the original fields, but pass in the next_cursor in the cursor field. Continue to make calls until the next_cursor in the response is null.

        - `limit`: The number of Organizations to return per page, the default is 100. A maximum of 1000 Members can be returned by a single request. If the total size of your result is greater than one page size, you must paginate the response. See the cursor field above.

        - `query`: The optional query object contains the operator, e.g. AND or OR, and the operands that will filter your Members. Only an operator is required, if you include no operands, no filtering will be applied. Similarly if you include no query object, no filtering is applied and we'll return all of your Members with no filtering applied.
        """  # noqa

        payload: Dict[str, Any] = {
            "organization_ids": organization_ids,
        }

        if cursor is not None:
            payload["cursor"] = cursor
        if limit is not None:
            payload["limit"] = limit
        if query is not None:
            payload["query"] = (
                query.dict() if isinstance(query, pydantic.BaseModel) else query
            )

        url = self.api_base.route_with_sub_url(self.sub_url, "members/search")

        res = await self.async_client.post(url, json=payload)
        return SearchMembersResponse.from_json(res.response.status, res.json)
