# This file was auto-generated by Fern from our API Definition.

import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.bill_data import BillData
from ..types.entrypointfield import Entrypointfield
from ..types.force_customer_creation import ForceCustomerCreation
from ..types.idempotency_key import IdempotencyKey
from ..types.payment_detail import PaymentDetail
from ..types.payor_data_request import PayorDataRequest
from ..types.schedule_detail import ScheduleDetail
from ..types.source import Source
from ..types.subdomain import Subdomain
from ..types.subscription_query_records import SubscriptionQueryRecords
from .raw_client import AsyncRawSubscriptionClient, RawSubscriptionClient
from .types.add_subscription_response import AddSubscriptionResponse
from .types.remove_subscription_response import RemoveSubscriptionResponse
from .types.request_schedule_payment_method import RequestSchedulePaymentMethod
from .types.set_pause import SetPause
from .types.update_subscription_response import UpdateSubscriptionResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class SubscriptionClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawSubscriptionClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawSubscriptionClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawSubscriptionClient
        """
        return self._raw_client

    def get_subscription(
        self, sub_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> SubscriptionQueryRecords:
        """
        Retrieves a single subscription's details.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SubscriptionQueryRecords
            Success

        Examples
        --------
        from payabli import payabli

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.subscription.get_subscription(
            sub_id=263,
        )
        """
        _response = self._raw_client.get_subscription(sub_id, request_options=request_options)
        return _response.data

    def new_subscription(
        self,
        *,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        payment_details: typing.Optional[PaymentDetail] = OMIT,
        payment_method: typing.Optional[RequestSchedulePaymentMethod] = OMIT,
        schedule_details: typing.Optional[ScheduleDetail] = OMIT,
        set_pause: typing.Optional[SetPause] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AddSubscriptionResponse:
        """
        Creates a subscription or scheduled payment to run at a specified time and frequency.

        Parameters
        ----------
        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the customer/payor.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the subscription.

        payment_details : typing.Optional[PaymentDetail]
            Object describing details of the payment. To skip the payment, set the `totalAmount` to 0. Payments will be paused until the amount is updated to a non-zero value. When `totalAmount` is set to 0, the `serviceFee` must also be set to 0.

        payment_method : typing.Optional[RequestSchedulePaymentMethod]
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        schedule_details : typing.Optional[ScheduleDetail]
            Object describing the schedule for subscription.

        set_pause : typing.Optional[SetPause]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AddSubscriptionResponse
            Success

        Examples
        --------
        from payabli import (
            PaymentDetail,
            PayMethodCredit,
            PayorDataRequest,
            ScheduleDetail,
            payabli,
        )

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.subscription.new_subscription(
            customer_data=PayorDataRequest(
                customer_id=4440,
            ),
            entry_point="f743aed24a",
            payment_details=PaymentDetail(
                service_fee=0.0,
                total_amount=100.0,
            ),
            payment_method=PayMethodCredit(
                cardcvv="123",
                cardexp="02/25",
                card_holder="John Cassian",
                cardnumber="4111111111111111",
                cardzip="37615",
                initiator="payor",
            ),
            schedule_details=ScheduleDetail(
                end_date="03-20-2025",
                frequency="weekly",
                plan_id=1,
                start_date="09-20-2024",
            ),
        )
        """
        _response = self._raw_client.new_subscription(
            force_customer_creation=force_customer_creation,
            idempotency_key=idempotency_key,
            customer_data=customer_data,
            entry_point=entry_point,
            invoice_data=invoice_data,
            payment_details=payment_details,
            payment_method=payment_method,
            schedule_details=schedule_details,
            set_pause=set_pause,
            source=source,
            subdomain=subdomain,
            request_options=request_options,
        )
        return _response.data

    def remove_subscription(
        self, sub_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> RemoveSubscriptionResponse:
        """
        Deletes a subscription, autopay, or recurring payment and prevents future charges.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        RemoveSubscriptionResponse
            Success

        Examples
        --------
        from payabli import payabli

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.subscription.remove_subscription(
            sub_id=396,
        )
        """
        _response = self._raw_client.remove_subscription(sub_id, request_options=request_options)
        return _response.data

    def update_subscription(
        self,
        sub_id: int,
        *,
        payment_details: typing.Optional[PaymentDetail] = OMIT,
        schedule_details: typing.Optional[ScheduleDetail] = OMIT,
        set_pause: typing.Optional[SetPause] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateSubscriptionResponse:
        """
        Updates a subscription's details.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        payment_details : typing.Optional[PaymentDetail]
            Object describing details of the payment. To skip the payment, set the `totalAmount` to 0. Payments will be paused until the amount is updated to a non-zero value. When `totalAmount` is set to 0, the `serviceFee` must also be set to 0.

        schedule_details : typing.Optional[ScheduleDetail]
            Object describing the schedule for subscription

        set_pause : typing.Optional[SetPause]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpdateSubscriptionResponse
            Success

        Examples
        --------
        from payabli import payabli

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.subscription.update_subscription(
            sub_id=231,
            set_pause=True,
        )
        """
        _response = self._raw_client.update_subscription(
            sub_id,
            payment_details=payment_details,
            schedule_details=schedule_details,
            set_pause=set_pause,
            request_options=request_options,
        )
        return _response.data


class AsyncSubscriptionClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawSubscriptionClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawSubscriptionClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawSubscriptionClient
        """
        return self._raw_client

    async def get_subscription(
        self, sub_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> SubscriptionQueryRecords:
        """
        Retrieves a single subscription's details.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SubscriptionQueryRecords
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.subscription.get_subscription(
                sub_id=263,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_subscription(sub_id, request_options=request_options)
        return _response.data

    async def new_subscription(
        self,
        *,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        payment_details: typing.Optional[PaymentDetail] = OMIT,
        payment_method: typing.Optional[RequestSchedulePaymentMethod] = OMIT,
        schedule_details: typing.Optional[ScheduleDetail] = OMIT,
        set_pause: typing.Optional[SetPause] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AddSubscriptionResponse:
        """
        Creates a subscription or scheduled payment to run at a specified time and frequency.

        Parameters
        ----------
        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the customer/payor.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the subscription.

        payment_details : typing.Optional[PaymentDetail]
            Object describing details of the payment. To skip the payment, set the `totalAmount` to 0. Payments will be paused until the amount is updated to a non-zero value. When `totalAmount` is set to 0, the `serviceFee` must also be set to 0.

        payment_method : typing.Optional[RequestSchedulePaymentMethod]
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        schedule_details : typing.Optional[ScheduleDetail]
            Object describing the schedule for subscription.

        set_pause : typing.Optional[SetPause]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AddSubscriptionResponse
            Success

        Examples
        --------
        import asyncio

        from payabli import (
            Asyncpayabli,
            PaymentDetail,
            PayMethodCredit,
            PayorDataRequest,
            ScheduleDetail,
        )

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.subscription.new_subscription(
                customer_data=PayorDataRequest(
                    customer_id=4440,
                ),
                entry_point="f743aed24a",
                payment_details=PaymentDetail(
                    service_fee=0.0,
                    total_amount=100.0,
                ),
                payment_method=PayMethodCredit(
                    cardcvv="123",
                    cardexp="02/25",
                    card_holder="John Cassian",
                    cardnumber="4111111111111111",
                    cardzip="37615",
                    initiator="payor",
                ),
                schedule_details=ScheduleDetail(
                    end_date="03-20-2025",
                    frequency="weekly",
                    plan_id=1,
                    start_date="09-20-2024",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.new_subscription(
            force_customer_creation=force_customer_creation,
            idempotency_key=idempotency_key,
            customer_data=customer_data,
            entry_point=entry_point,
            invoice_data=invoice_data,
            payment_details=payment_details,
            payment_method=payment_method,
            schedule_details=schedule_details,
            set_pause=set_pause,
            source=source,
            subdomain=subdomain,
            request_options=request_options,
        )
        return _response.data

    async def remove_subscription(
        self, sub_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> RemoveSubscriptionResponse:
        """
        Deletes a subscription, autopay, or recurring payment and prevents future charges.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        RemoveSubscriptionResponse
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.subscription.remove_subscription(
                sub_id=396,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.remove_subscription(sub_id, request_options=request_options)
        return _response.data

    async def update_subscription(
        self,
        sub_id: int,
        *,
        payment_details: typing.Optional[PaymentDetail] = OMIT,
        schedule_details: typing.Optional[ScheduleDetail] = OMIT,
        set_pause: typing.Optional[SetPause] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateSubscriptionResponse:
        """
        Updates a subscription's details.

        Parameters
        ----------
        sub_id : int
            The subscription ID.

        payment_details : typing.Optional[PaymentDetail]
            Object describing details of the payment. To skip the payment, set the `totalAmount` to 0. Payments will be paused until the amount is updated to a non-zero value. When `totalAmount` is set to 0, the `serviceFee` must also be set to 0.

        schedule_details : typing.Optional[ScheduleDetail]
            Object describing the schedule for subscription

        set_pause : typing.Optional[SetPause]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpdateSubscriptionResponse
            Success

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.subscription.update_subscription(
                sub_id=231,
                set_pause=True,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update_subscription(
            sub_id,
            payment_details=payment_details,
            schedule_details=schedule_details,
            set_pause=set_pause,
            request_options=request_options,
        )
        return _response.data
