# 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.entry import Entry
from ..types.payabli_api_response import PayabliApiResponse
from .raw_client import AsyncRawGhostCardClient, RawGhostCardClient
from .types.card_status import CardStatus
from .types.create_ghost_card_response import CreateGhostCardResponse

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


class GhostCardClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawGhostCardClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        RawGhostCardClient
        """
        return self._raw_client

    def create_ghost_card(
        self,
        entry: Entry,
        *,
        vendor_id: int,
        expense_limit: float,
        expiration_date: typing.Optional[str] = OMIT,
        amount: typing.Optional[float] = OMIT,
        max_number_of_uses: typing.Optional[int] = OMIT,
        exact_amount: typing.Optional[bool] = OMIT,
        expense_limit_period: typing.Optional[str] = OMIT,
        billing_cycle: typing.Optional[str] = OMIT,
        billing_cycle_day: typing.Optional[str] = OMIT,
        daily_transaction_count: typing.Optional[int] = OMIT,
        daily_amount_limit: typing.Optional[float] = OMIT,
        transaction_amount_limit: typing.Optional[int] = OMIT,
        mcc: typing.Optional[str] = OMIT,
        tcc: typing.Optional[str] = OMIT,
        misc_1: typing.Optional[str] = OMIT,
        misc_2: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateGhostCardResponse:
        """
        Creates a ghost card, a multi-use virtual debit card issued to a vendor for recurring or discretionary spend.

        Unlike single-use virtual cards issued as part of a payout transaction, ghost cards aren't tied to a specific payout. They're issued directly to a vendor and can be reused up to a configurable number of times within the card's spending limits.

        Parameters
        ----------
        entry : Entry

        vendor_id : int
            ID of the vendor who receives the card. The vendor must belong to the paypoint and have an active status.

        expense_limit : float
            Spending limit for the card. Must be greater than `0` and can't exceed the paypoint's configured payout credit limit.

        expiration_date : typing.Optional[str]
            Requested expiration date for the card. If not provided, defaults to 30 days from creation.

        amount : typing.Optional[float]
            Initial load amount for the card. Defaults to `0`.

        max_number_of_uses : typing.Optional[int]
            Maximum number of times the card can be used. If `0` or negative, defaults to `9999`. Ignored and set to `1` when `exactAmount` is `true`.

        exact_amount : typing.Optional[bool]
            When `true`, restricts the card to a single use. `maxNumberOfUses` is automatically set to `1` regardless of any other value provided.

        expense_limit_period : typing.Optional[str]
            Time period over which `expenseLimit` applies (for example, `monthly` or `weekly`). No server-side enforcement.

        billing_cycle : typing.Optional[str]
            Billing cycle identifier.

        billing_cycle_day : typing.Optional[str]
            Day within the billing cycle.

        daily_transaction_count : typing.Optional[int]
            Maximum number of transactions allowed per day. Defaults to `0` (unlimited).

        daily_amount_limit : typing.Optional[float]
            Maximum total spend allowed per day. Defaults to `0` (unlimited).

        transaction_amount_limit : typing.Optional[int]
            Maximum spend allowed per single transaction. Defaults to `0` (unlimited).

        mcc : typing.Optional[str]
            Merchant Category Code to restrict where the card can be used. Must be a valid MCC if provided.

        tcc : typing.Optional[str]
            Transaction Category Code to restrict where the card can be used. Must be a valid TCC if provided.

        misc_1 : typing.Optional[str]
            Custom metadata field. Stored on the card record.

        misc_2 : typing.Optional[str]
            Custom metadata field. Stored on the card record.

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

        Returns
        -------
        CreateGhostCardResponse
            Success response with ghost card details.

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.ghost_card.create_ghost_card(
            entry="8cfec2e0fa",
            vendor_id=42,
            expense_limit=500.0,
            max_number_of_uses=3,
            exact_amount=False,
            expense_limit_period="monthly",
            billing_cycle="monthly",
            billing_cycle_day="1",
            daily_transaction_count=5,
            daily_amount_limit=200.0,
            transaction_amount_limit=100,
            mcc="5411",
            tcc="R",
            misc_1="PO-98765",
            misc_2="Dept-Finance",
        )
        """
        _response = self._raw_client.create_ghost_card(
            entry,
            vendor_id=vendor_id,
            expense_limit=expense_limit,
            expiration_date=expiration_date,
            amount=amount,
            max_number_of_uses=max_number_of_uses,
            exact_amount=exact_amount,
            expense_limit_period=expense_limit_period,
            billing_cycle=billing_cycle,
            billing_cycle_day=billing_cycle_day,
            daily_transaction_count=daily_transaction_count,
            daily_amount_limit=daily_amount_limit,
            transaction_amount_limit=transaction_amount_limit,
            mcc=mcc,
            tcc=tcc,
            misc_1=misc_1,
            misc_2=misc_2,
            request_options=request_options,
        )
        return _response.data

    def update_card(
        self,
        entry: Entry,
        *,
        card_token: str,
        status: typing.Optional[CardStatus] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse:
        """
        Updates the status of a virtual card (including ghost cards) under a paypoint.

        Parameters
        ----------
        entry : Entry

        card_token : str
            Token that uniquely identifies the card. This is the `ReferenceId` returned when the card was created.

        status : typing.Optional[CardStatus]
            The new status to set on the card.

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

        Returns
        -------
        PayabliApiResponse
            Success response.

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

        client = payabli(
            api_key="YOUR_API_KEY",
        )
        client.ghost_card.update_card(
            entry="8cfec2e0fa",
            card_token="gc_abc123def456",
            status="Cancelled",
        )
        """
        _response = self._raw_client.update_card(
            entry, card_token=card_token, status=status, request_options=request_options
        )
        return _response.data


class AsyncGhostCardClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawGhostCardClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        AsyncRawGhostCardClient
        """
        return self._raw_client

    async def create_ghost_card(
        self,
        entry: Entry,
        *,
        vendor_id: int,
        expense_limit: float,
        expiration_date: typing.Optional[str] = OMIT,
        amount: typing.Optional[float] = OMIT,
        max_number_of_uses: typing.Optional[int] = OMIT,
        exact_amount: typing.Optional[bool] = OMIT,
        expense_limit_period: typing.Optional[str] = OMIT,
        billing_cycle: typing.Optional[str] = OMIT,
        billing_cycle_day: typing.Optional[str] = OMIT,
        daily_transaction_count: typing.Optional[int] = OMIT,
        daily_amount_limit: typing.Optional[float] = OMIT,
        transaction_amount_limit: typing.Optional[int] = OMIT,
        mcc: typing.Optional[str] = OMIT,
        tcc: typing.Optional[str] = OMIT,
        misc_1: typing.Optional[str] = OMIT,
        misc_2: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateGhostCardResponse:
        """
        Creates a ghost card, a multi-use virtual debit card issued to a vendor for recurring or discretionary spend.

        Unlike single-use virtual cards issued as part of a payout transaction, ghost cards aren't tied to a specific payout. They're issued directly to a vendor and can be reused up to a configurable number of times within the card's spending limits.

        Parameters
        ----------
        entry : Entry

        vendor_id : int
            ID of the vendor who receives the card. The vendor must belong to the paypoint and have an active status.

        expense_limit : float
            Spending limit for the card. Must be greater than `0` and can't exceed the paypoint's configured payout credit limit.

        expiration_date : typing.Optional[str]
            Requested expiration date for the card. If not provided, defaults to 30 days from creation.

        amount : typing.Optional[float]
            Initial load amount for the card. Defaults to `0`.

        max_number_of_uses : typing.Optional[int]
            Maximum number of times the card can be used. If `0` or negative, defaults to `9999`. Ignored and set to `1` when `exactAmount` is `true`.

        exact_amount : typing.Optional[bool]
            When `true`, restricts the card to a single use. `maxNumberOfUses` is automatically set to `1` regardless of any other value provided.

        expense_limit_period : typing.Optional[str]
            Time period over which `expenseLimit` applies (for example, `monthly` or `weekly`). No server-side enforcement.

        billing_cycle : typing.Optional[str]
            Billing cycle identifier.

        billing_cycle_day : typing.Optional[str]
            Day within the billing cycle.

        daily_transaction_count : typing.Optional[int]
            Maximum number of transactions allowed per day. Defaults to `0` (unlimited).

        daily_amount_limit : typing.Optional[float]
            Maximum total spend allowed per day. Defaults to `0` (unlimited).

        transaction_amount_limit : typing.Optional[int]
            Maximum spend allowed per single transaction. Defaults to `0` (unlimited).

        mcc : typing.Optional[str]
            Merchant Category Code to restrict where the card can be used. Must be a valid MCC if provided.

        tcc : typing.Optional[str]
            Transaction Category Code to restrict where the card can be used. Must be a valid TCC if provided.

        misc_1 : typing.Optional[str]
            Custom metadata field. Stored on the card record.

        misc_2 : typing.Optional[str]
            Custom metadata field. Stored on the card record.

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

        Returns
        -------
        CreateGhostCardResponse
            Success response with ghost card details.

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.ghost_card.create_ghost_card(
                entry="8cfec2e0fa",
                vendor_id=42,
                expense_limit=500.0,
                max_number_of_uses=3,
                exact_amount=False,
                expense_limit_period="monthly",
                billing_cycle="monthly",
                billing_cycle_day="1",
                daily_transaction_count=5,
                daily_amount_limit=200.0,
                transaction_amount_limit=100,
                mcc="5411",
                tcc="R",
                misc_1="PO-98765",
                misc_2="Dept-Finance",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.create_ghost_card(
            entry,
            vendor_id=vendor_id,
            expense_limit=expense_limit,
            expiration_date=expiration_date,
            amount=amount,
            max_number_of_uses=max_number_of_uses,
            exact_amount=exact_amount,
            expense_limit_period=expense_limit_period,
            billing_cycle=billing_cycle,
            billing_cycle_day=billing_cycle_day,
            daily_transaction_count=daily_transaction_count,
            daily_amount_limit=daily_amount_limit,
            transaction_amount_limit=transaction_amount_limit,
            mcc=mcc,
            tcc=tcc,
            misc_1=misc_1,
            misc_2=misc_2,
            request_options=request_options,
        )
        return _response.data

    async def update_card(
        self,
        entry: Entry,
        *,
        card_token: str,
        status: typing.Optional[CardStatus] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayabliApiResponse:
        """
        Updates the status of a virtual card (including ghost cards) under a paypoint.

        Parameters
        ----------
        entry : Entry

        card_token : str
            Token that uniquely identifies the card. This is the `ReferenceId` returned when the card was created.

        status : typing.Optional[CardStatus]
            The new status to set on the card.

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

        Returns
        -------
        PayabliApiResponse
            Success response.

        Examples
        --------
        import asyncio

        from payabli import Asyncpayabli

        client = Asyncpayabli(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.ghost_card.update_card(
                entry="8cfec2e0fa",
                card_token="gc_abc123def456",
                status="Cancelled",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update_card(
            entry, card_token=card_token, status=status, request_options=request_options
        )
        return _response.data
