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

from __future__ import annotations
from dataclasses import dataclass, field
from documenso_sdk.models import DocumensoError
from documenso_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from documenso_sdk.utils import FieldMetadata, QueryParamMetadata
from enum import Enum
import httpx
import pydantic
from pydantic import model_serializer
from typing import Dict, List, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


class QueryParamSource(str, Enum):
    r"""Filter documents by how it was created."""

    DOCUMENT = "DOCUMENT"
    TEMPLATE = "TEMPLATE"
    TEMPLATE_DIRECT_LINK = "TEMPLATE_DIRECT_LINK"


class QueryParamStatus(str, Enum):
    r"""Filter documents by the current status"""

    DRAFT = "DRAFT"
    PENDING = "PENDING"
    COMPLETED = "COMPLETED"
    REJECTED = "REJECTED"


class OrderByColumn(str, Enum):
    CREATED_AT = "createdAt"


class OrderByDirection(str, Enum):
    ASC = "asc"
    DESC = "desc"


class DocumentFindRequestTypedDict(TypedDict):
    query: NotRequired[str]
    r"""The search query."""
    page: NotRequired[float]
    r"""The pagination page number, starts at 1."""
    per_page: NotRequired[float]
    r"""The number of items per page."""
    template_id: NotRequired[float]
    r"""Filter documents by the template ID used to create it."""
    source: NotRequired[QueryParamSource]
    r"""Filter documents by how it was created."""
    status: NotRequired[QueryParamStatus]
    r"""Filter documents by the current status"""
    folder_id: NotRequired[str]
    r"""Filter documents by folder ID"""
    order_by_column: NotRequired[OrderByColumn]
    order_by_direction: NotRequired[OrderByDirection]


class DocumentFindRequest(BaseModel):
    query: Annotated[
        Optional[str],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""The search query."""

    page: Annotated[
        Optional[float],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""The pagination page number, starts at 1."""

    per_page: Annotated[
        Optional[float],
        pydantic.Field(alias="perPage"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""The number of items per page."""

    template_id: Annotated[
        Optional[float],
        pydantic.Field(alias="templateId"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter documents by the template ID used to create it."""

    source: Annotated[
        Optional[QueryParamSource],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter documents by how it was created."""

    status: Annotated[
        Optional[QueryParamStatus],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter documents by the current status"""

    folder_id: Annotated[
        Optional[str],
        pydantic.Field(alias="folderId"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter documents by folder ID"""

    order_by_column: Annotated[
        Optional[OrderByColumn],
        pydantic.Field(alias="orderByColumn"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None

    order_by_direction: Annotated[
        Optional[OrderByDirection],
        pydantic.Field(alias="orderByDirection"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = OrderByDirection.DESC


class DocumentFindInternalServerErrorIssueTypedDict(TypedDict):
    message: str


class DocumentFindInternalServerErrorIssue(BaseModel):
    message: str


class DocumentFindInternalServerErrorData(BaseModel):
    message: str

    code: str

    issues: Optional[List[DocumentFindInternalServerErrorIssue]] = None


@dataclass(unsafe_hash=True)
class DocumentFindInternalServerError(DocumensoError):
    r"""Internal server error"""

    data: DocumentFindInternalServerErrorData = field(hash=False)

    def __init__(
        self,
        data: DocumentFindInternalServerErrorData,
        raw_response: httpx.Response,
        body: Optional[str] = None,
    ):
        fallback = body or raw_response.text
        message = str(data.message) or fallback
        super().__init__(message, raw_response, body)
        object.__setattr__(self, "data", data)


class DocumentFindNotFoundIssueTypedDict(TypedDict):
    message: str


class DocumentFindNotFoundIssue(BaseModel):
    message: str


class DocumentFindNotFoundErrorData(BaseModel):
    message: str

    code: str

    issues: Optional[List[DocumentFindNotFoundIssue]] = None


@dataclass(unsafe_hash=True)
class DocumentFindNotFoundError(DocumensoError):
    r"""Not found"""

    data: DocumentFindNotFoundErrorData = field(hash=False)

    def __init__(
        self,
        data: DocumentFindNotFoundErrorData,
        raw_response: httpx.Response,
        body: Optional[str] = None,
    ):
        fallback = body or raw_response.text
        message = str(data.message) or fallback
        super().__init__(message, raw_response, body)
        object.__setattr__(self, "data", data)


class DocumentFindForbiddenIssueTypedDict(TypedDict):
    message: str


class DocumentFindForbiddenIssue(BaseModel):
    message: str


class DocumentFindForbiddenErrorData(BaseModel):
    message: str

    code: str

    issues: Optional[List[DocumentFindForbiddenIssue]] = None


@dataclass(unsafe_hash=True)
class DocumentFindForbiddenError(DocumensoError):
    r"""Insufficient access"""

    data: DocumentFindForbiddenErrorData = field(hash=False)

    def __init__(
        self,
        data: DocumentFindForbiddenErrorData,
        raw_response: httpx.Response,
        body: Optional[str] = None,
    ):
        fallback = body or raw_response.text
        message = str(data.message) or fallback
        super().__init__(message, raw_response, body)
        object.__setattr__(self, "data", data)


class DocumentFindUnauthorizedIssueTypedDict(TypedDict):
    message: str


class DocumentFindUnauthorizedIssue(BaseModel):
    message: str


class DocumentFindUnauthorizedErrorData(BaseModel):
    message: str

    code: str

    issues: Optional[List[DocumentFindUnauthorizedIssue]] = None


@dataclass(unsafe_hash=True)
class DocumentFindUnauthorizedError(DocumensoError):
    r"""Authorization not provided"""

    data: DocumentFindUnauthorizedErrorData = field(hash=False)

    def __init__(
        self,
        data: DocumentFindUnauthorizedErrorData,
        raw_response: httpx.Response,
        body: Optional[str] = None,
    ):
        fallback = body or raw_response.text
        message = str(data.message) or fallback
        super().__init__(message, raw_response, body)
        object.__setattr__(self, "data", data)


class DocumentFindBadRequestIssueTypedDict(TypedDict):
    message: str


class DocumentFindBadRequestIssue(BaseModel):
    message: str


class DocumentFindBadRequestErrorData(BaseModel):
    message: str

    code: str

    issues: Optional[List[DocumentFindBadRequestIssue]] = None


@dataclass(unsafe_hash=True)
class DocumentFindBadRequestError(DocumensoError):
    r"""Invalid input data"""

    data: DocumentFindBadRequestErrorData = field(hash=False)

    def __init__(
        self,
        data: DocumentFindBadRequestErrorData,
        raw_response: httpx.Response,
        body: Optional[str] = None,
    ):
        fallback = body or raw_response.text
        message = str(data.message) or fallback
        super().__init__(message, raw_response, body)
        object.__setattr__(self, "data", data)


class DocumentFindVisibility(str, Enum):
    EVERYONE = "EVERYONE"
    MANAGER_AND_ABOVE = "MANAGER_AND_ABOVE"
    ADMIN = "ADMIN"


class DataStatus(str, Enum):
    DRAFT = "DRAFT"
    PENDING = "PENDING"
    COMPLETED = "COMPLETED"
    REJECTED = "REJECTED"


class DataSource(str, Enum):
    DOCUMENT = "DOCUMENT"
    TEMPLATE = "TEMPLATE"
    TEMPLATE_DIRECT_LINK = "TEMPLATE_DIRECT_LINK"


class DocumentFindGlobalAccessAuth(str, Enum):
    ACCOUNT = "ACCOUNT"
    TWO_FACTOR_AUTH = "TWO_FACTOR_AUTH"


class DocumentFindGlobalActionAuth(str, Enum):
    ACCOUNT = "ACCOUNT"
    PASSKEY = "PASSKEY"
    TWO_FACTOR_AUTH = "TWO_FACTOR_AUTH"
    PASSWORD = "PASSWORD"


class DocumentFindAuthOptionsTypedDict(TypedDict):
    global_access_auth: List[DocumentFindGlobalAccessAuth]
    global_action_auth: List[DocumentFindGlobalActionAuth]


class DocumentFindAuthOptions(BaseModel):
    global_access_auth: Annotated[
        List[DocumentFindGlobalAccessAuth], pydantic.Field(alias="globalAccessAuth")
    ]

    global_action_auth: Annotated[
        List[DocumentFindGlobalActionAuth], pydantic.Field(alias="globalActionAuth")
    ]


DocumentFindFormValuesTypedDict = TypeAliasType(
    "DocumentFindFormValuesTypedDict", Union[str, bool, float]
)


DocumentFindFormValues = TypeAliasType(
    "DocumentFindFormValues", Union[str, bool, float]
)


class DocumentFindUserTypedDict(TypedDict):
    id: float
    name: Nullable[str]
    email: str


class DocumentFindUser(BaseModel):
    id: float

    name: Nullable[str]

    email: str

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = []
        nullable_fields = ["name"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class DocumentFindRole(str, Enum):
    CC = "CC"
    SIGNER = "SIGNER"
    VIEWER = "VIEWER"
    APPROVER = "APPROVER"
    ASSISTANT = "ASSISTANT"


class DocumentFindReadStatus(str, Enum):
    NOT_OPENED = "NOT_OPENED"
    OPENED = "OPENED"


class DocumentFindSigningStatus(str, Enum):
    NOT_SIGNED = "NOT_SIGNED"
    SIGNED = "SIGNED"
    REJECTED = "REJECTED"


class DocumentFindSendStatus(str, Enum):
    NOT_SENT = "NOT_SENT"
    SENT = "SENT"


class DocumentFindAccessAuth(str, Enum):
    ACCOUNT = "ACCOUNT"
    TWO_FACTOR_AUTH = "TWO_FACTOR_AUTH"


class DocumentFindActionAuth(str, Enum):
    ACCOUNT = "ACCOUNT"
    PASSKEY = "PASSKEY"
    TWO_FACTOR_AUTH = "TWO_FACTOR_AUTH"
    PASSWORD = "PASSWORD"
    EXPLICIT_NONE = "EXPLICIT_NONE"


class DocumentFindRecipientAuthOptionsTypedDict(TypedDict):
    access_auth: List[DocumentFindAccessAuth]
    action_auth: List[DocumentFindActionAuth]


class DocumentFindRecipientAuthOptions(BaseModel):
    access_auth: Annotated[
        List[DocumentFindAccessAuth], pydantic.Field(alias="accessAuth")
    ]

    action_auth: Annotated[
        List[DocumentFindActionAuth], pydantic.Field(alias="actionAuth")
    ]


class DocumentFindRecipientTypedDict(TypedDict):
    envelope_id: str
    role: DocumentFindRole
    read_status: DocumentFindReadStatus
    signing_status: DocumentFindSigningStatus
    send_status: DocumentFindSendStatus
    id: float
    email: str
    name: str
    token: str
    document_deleted_at: Nullable[str]
    expired: Nullable[str]
    signed_at: Nullable[str]
    auth_options: Nullable[DocumentFindRecipientAuthOptionsTypedDict]
    signing_order: Nullable[float]
    rejection_reason: Nullable[str]
    document_id: NotRequired[Nullable[float]]
    template_id: NotRequired[Nullable[float]]


class DocumentFindRecipient(BaseModel):
    envelope_id: Annotated[str, pydantic.Field(alias="envelopeId")]

    role: DocumentFindRole

    read_status: Annotated[DocumentFindReadStatus, pydantic.Field(alias="readStatus")]

    signing_status: Annotated[
        DocumentFindSigningStatus, pydantic.Field(alias="signingStatus")
    ]

    send_status: Annotated[DocumentFindSendStatus, pydantic.Field(alias="sendStatus")]

    id: float

    email: str

    name: str

    token: str

    document_deleted_at: Annotated[
        Nullable[str], pydantic.Field(alias="documentDeletedAt")
    ]

    expired: Nullable[str]

    signed_at: Annotated[Nullable[str], pydantic.Field(alias="signedAt")]

    auth_options: Annotated[
        Nullable[DocumentFindRecipientAuthOptions], pydantic.Field(alias="authOptions")
    ]

    signing_order: Annotated[Nullable[float], pydantic.Field(alias="signingOrder")]

    rejection_reason: Annotated[Nullable[str], pydantic.Field(alias="rejectionReason")]

    document_id: Annotated[
        OptionalNullable[float], pydantic.Field(alias="documentId")
    ] = UNSET

    template_id: Annotated[
        OptionalNullable[float], pydantic.Field(alias="templateId")
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["documentId", "templateId"]
        nullable_fields = [
            "documentDeletedAt",
            "expired",
            "signedAt",
            "authOptions",
            "signingOrder",
            "rejectionReason",
            "documentId",
            "templateId",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class DocumentFindTeamTypedDict(TypedDict):
    id: float
    url: str


class DocumentFindTeam(BaseModel):
    id: float

    url: str


class DocumentFindDataTypedDict(TypedDict):
    visibility: DocumentFindVisibility
    status: DataStatus
    source: DataSource
    id: float
    external_id: Nullable[str]
    user_id: float
    auth_options: Nullable[DocumentFindAuthOptionsTypedDict]
    form_values: Nullable[Dict[str, DocumentFindFormValuesTypedDict]]
    title: str
    created_at: str
    updated_at: str
    completed_at: Nullable[str]
    deleted_at: Nullable[str]
    team_id: float
    folder_id: Nullable[str]
    use_legacy_field_insertion: bool
    envelope_id: str
    internal_version: float
    user: DocumentFindUserTypedDict
    recipients: List[DocumentFindRecipientTypedDict]
    team: Nullable[DocumentFindTeamTypedDict]
    document_data_id: NotRequired[str]
    template_id: NotRequired[Nullable[float]]


class DocumentFindData(BaseModel):
    visibility: DocumentFindVisibility

    status: DataStatus

    source: DataSource

    id: float

    external_id: Annotated[Nullable[str], pydantic.Field(alias="externalId")]

    user_id: Annotated[float, pydantic.Field(alias="userId")]

    auth_options: Annotated[
        Nullable[DocumentFindAuthOptions], pydantic.Field(alias="authOptions")
    ]

    form_values: Annotated[
        Nullable[Dict[str, DocumentFindFormValues]], pydantic.Field(alias="formValues")
    ]

    title: str

    created_at: Annotated[str, pydantic.Field(alias="createdAt")]

    updated_at: Annotated[str, pydantic.Field(alias="updatedAt")]

    completed_at: Annotated[Nullable[str], pydantic.Field(alias="completedAt")]

    deleted_at: Annotated[Nullable[str], pydantic.Field(alias="deletedAt")]

    team_id: Annotated[float, pydantic.Field(alias="teamId")]

    folder_id: Annotated[Nullable[str], pydantic.Field(alias="folderId")]

    use_legacy_field_insertion: Annotated[
        bool, pydantic.Field(alias="useLegacyFieldInsertion")
    ]

    envelope_id: Annotated[str, pydantic.Field(alias="envelopeId")]

    internal_version: Annotated[float, pydantic.Field(alias="internalVersion")]

    user: DocumentFindUser

    recipients: List[DocumentFindRecipient]

    team: Nullable[DocumentFindTeam]

    document_data_id: Annotated[
        Optional[str], pydantic.Field(alias="documentDataId")
    ] = ""

    template_id: Annotated[
        OptionalNullable[float], pydantic.Field(alias="templateId")
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["documentDataId", "templateId"]
        nullable_fields = [
            "externalId",
            "authOptions",
            "formValues",
            "completedAt",
            "deletedAt",
            "folderId",
            "templateId",
            "team",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class DocumentFindResponseTypedDict(TypedDict):
    r"""Successful response"""

    data: List[DocumentFindDataTypedDict]
    count: float
    current_page: float
    per_page: float
    total_pages: float


class DocumentFindResponse(BaseModel):
    r"""Successful response"""

    data: List[DocumentFindData]

    count: float

    current_page: Annotated[float, pydantic.Field(alias="currentPage")]

    per_page: Annotated[float, pydantic.Field(alias="perPage")]

    total_pages: Annotated[float, pydantic.Field(alias="totalPages")]
