# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from stripe._createable_api_resource import CreateableAPIResource
from stripe._expandable_field import ExpandableField
from stripe._list_object import ListObject
from stripe._stripe_object import StripeObject
from typing import ClassVar, List, Optional, cast
from typing_extensions import Literal, Unpack, TYPE_CHECKING

if TYPE_CHECKING:
    from stripe._account import Account as AccountResource
    from stripe._customer import Customer
    from stripe.financial_connections._account import (
        Account as FinancialConnectionsAccountResource,
    )
    from stripe.params.financial_connections._session_create_params import (
        SessionCreateParams,
    )
    from stripe.params.financial_connections._session_retrieve_params import (
        SessionRetrieveParams,
    )


class Session(CreateableAPIResource["Session"]):
    """
    A Financial Connections Session is the secure way to programmatically launch the client-side Stripe.js modal that lets your users link their accounts.
    """

    OBJECT_NAME: ClassVar[Literal["financial_connections.session"]] = (
        "financial_connections.session"
    )

    class AccountHolder(StripeObject):
        account: Optional[ExpandableField["AccountResource"]]
        """
        The ID of the Stripe account that this account belongs to. Only available when `account_holder.type` is `account`.
        """
        customer: Optional[ExpandableField["Customer"]]
        """
        The ID for an Account representing a customer that this account belongs to. Only available when `account_holder.type` is `customer`.
        """
        customer_account: Optional[str]
        type: Literal["account", "customer"]
        """
        Type of account holder that this account belongs to.
        """

    class Filters(StripeObject):
        account_subcategories: Optional[
            List[
                Literal[
                    "checking",
                    "credit_card",
                    "line_of_credit",
                    "mortgage",
                    "savings",
                ]
            ]
        ]
        """
        Restricts the Session to subcategories of accounts that can be linked. Valid subcategories are: `checking`, `savings`, `mortgage`, `line_of_credit`, `credit_card`.
        """
        countries: Optional[List[str]]
        """
        List of countries from which to filter accounts.
        """
        institution: Optional[str]
        """
        Stripe ID of the institution with which the customer should be directed to log in.
        """

    class Hosted(StripeObject):
        delivery_method: Optional[Literal["email", "url"]]
        """
        How the user enters the hosted flow. You can only use the values `email` and `url` if you provide `relink_options`.
        """
        return_url: Optional[str]
        """
        The URL to redirect your customer back to after they link their accounts or cancel this Session. This parameter is required if `ui_mode` is `hosted`.
        """

    class Limits(StripeObject):
        accounts: int
        """
        The number of accounts that can be linked in this Session.
        """

    class ManualEntry(StripeObject):
        pass

    class RelinkOptions(StripeObject):
        account: Optional[str]
        """
        Requires the end user to repair this specific account during the authentication flow instead of connecting a different one.
        """
        authorization: str
        """
        The authorization to relink in the Session.
        """

    class RelinkResult(StripeObject):
        account: Optional[str]
        """
        The account relinked in the Session. Only present if `relink_options[account]` is set and relink is successful.
        """
        authorization: Optional[str]
        """
        The authorization relinked in the Session. Only present if relink is successful.
        """
        failure_reason: Optional[
            Literal["no_account", "no_authorization", "other"]
        ]
        """
        Reason for why relink failed. One of `no_authorization`, `no_account`, or `other`.
        """

    class StatusDetails(StripeObject):
        class Cancelled(StripeObject):
            reason: Literal["custom_manual_entry", "other"]
            """
            The reason for the Session being cancelled.
            """

        cancelled: Optional[Cancelled]
        _inner_class_types = {"cancelled": Cancelled}

    account_holder: Optional[AccountHolder]
    """
    The account holder for whom accounts are collected in this session.
    """
    accounts: ListObject["FinancialConnectionsAccountResource"]
    """
    The accounts that were collected as part of this Session.
    """
    client_secret: Optional[str]
    """
    A value that will be passed to the client to launch the authentication flow.
    """
    filters: Optional[Filters]
    hosted: Optional[Hosted]
    """
    Settings for the Hosted UI mode.
    """
    id: str
    """
    Unique identifier for the object.
    """
    limits: Optional[Limits]
    livemode: bool
    """
    If the object exists in live mode, the value is `true`. If the object exists in test mode, the value is `false`.
    """
    manual_entry: Optional[ManualEntry]
    object: Literal["financial_connections.session"]
    """
    String representing the object's type. Objects of the same type share the same value.
    """
    permissions: List[
        Literal["balances", "ownership", "payment_method", "transactions"]
    ]
    """
    Permissions requested for accounts collected during this session.
    """
    prefetch: Optional[
        List[
            Literal[
                "balances", "inferred_balances", "ownership", "transactions"
            ]
        ]
    ]
    """
    Data features requested to be retrieved upon account creation.
    """
    relink_options: Optional[RelinkOptions]
    relink_result: Optional[RelinkResult]
    return_url: Optional[str]
    """
    For webview integrations only. Upon completing OAuth login in the native browser, the user will be redirected to this URL to return to your app.
    """
    status: Optional[Literal["cancelled", "failed", "pending", "succeeded"]]
    """
    The current state of the session.
    """
    status_details: Optional[StatusDetails]
    ui_mode: Optional[Literal["hosted", "modal"]]
    """
    The UI mode for this session.
    """
    url: Optional[str]
    """
    The hosted URL for this Session. Redirect customers to this URL to take them to the hosted authentication flow. This value is only present when the Session is active and the `ui_mode` is `hosted`.
    """

    @classmethod
    def create(cls, **params: Unpack["SessionCreateParams"]) -> "Session":
        """
        To launch the Financial Connections authorization flow, create a Session. The session's client_secret can be used to launch the flow using Stripe.js.
        """
        return cast(
            "Session",
            cls._static_request(
                "post",
                cls.class_url(),
                params=params,
            ),
        )

    @classmethod
    async def create_async(
        cls, **params: Unpack["SessionCreateParams"]
    ) -> "Session":
        """
        To launch the Financial Connections authorization flow, create a Session. The session's client_secret can be used to launch the flow using Stripe.js.
        """
        return cast(
            "Session",
            await cls._static_request_async(
                "post",
                cls.class_url(),
                params=params,
            ),
        )

    @classmethod
    def retrieve(
        cls, id: str, **params: Unpack["SessionRetrieveParams"]
    ) -> "Session":
        """
        Retrieves the details of a Financial Connections Session
        """
        instance = cls(id, **params)
        instance.refresh()
        return instance

    @classmethod
    async def retrieve_async(
        cls, id: str, **params: Unpack["SessionRetrieveParams"]
    ) -> "Session":
        """
        Retrieves the details of a Financial Connections Session
        """
        instance = cls(id, **params)
        await instance.refresh_async()
        return instance

    _inner_class_types = {
        "account_holder": AccountHolder,
        "filters": Filters,
        "hosted": Hosted,
        "limits": Limits,
        "manual_entry": ManualEntry,
        "relink_options": RelinkOptions,
        "relink_result": RelinkResult,
        "status_details": StatusDetails,
    }
