"""Payouts resource."""

from typing import Any, AsyncIterator, Dict, Iterator, Optional

from ..client import AsyncHttpClient, HttpClient
from ..pagination import PaginatedResponse, async_paginate, paginate
from ..types import CalculatePayoutFeesResponseDataDto, PayoutV2Dto

BASE_PATH = "/api/v1/payouts"


class PayoutsResource:
    """Synchronous payouts resource.

    Wraps endpoints under ``/api/v1/payouts``.
    """

    def __init__(self, client: HttpClient) -> None:
        self._client = client

    def create(
        self,
        *,
        method: str,
        currency: str,
        amount: str,
        recipient_id: str,
        narration: Optional[str] = None,
        reference: Optional[str] = None,
    ) -> PayoutV2Dto:
        """Create a new payout.

        Args:
            method: Payout method ("fiat" or "crypto").
            currency: Currency to receive (e.g. "NGN", "USDT").
            amount: Amount to payout (e.g. "5000.00").
            recipient_id: Recipient ID (bank account ID for fiat,
                crypto address ID for crypto).
            narration: Optional description for the payout.
            reference: Optional idempotency reference.

        Returns:
            The created payout object.
        """
        body: Dict[str, Any] = {
            "method": method,
            "currency": currency,
            "amount": amount,
            "recipientId": recipient_id,
        }
        if narration is not None:
            body["narration"] = narration
        if reference is not None:
            body["reference"] = reference

        return self._client.request("POST", BASE_PATH, json_body=body)

    def list(
        self,
        *,
        page: int = 1,
        size: int = 10,
        search: Optional[str] = None,
        status: Optional[str] = None,
        session_reference: Optional[str] = None,
    ) -> PaginatedResponse:
        """List payouts with pagination.

        Returns:
            A PaginatedResponse containing PayoutV2Dto items.
        """
        params: Dict[str, Any] = {
            "page": page,
            "size": size,
            "search": search,
            "status": status,
            "sessionReference": session_reference,
        }
        return self._client.request_paginated("GET", BASE_PATH, params=params)

    def list_auto_paginate(self, **kwargs: Any) -> Iterator[PayoutV2Dto]:
        """Iterate over all payouts across all pages."""
        return paginate(self.list, params=kwargs)

    def get(self, payout_id: str) -> PayoutV2Dto:
        """Get a payout by ID.

        Args:
            payout_id: The payout UUID.

        Returns:
            The payout object.
        """
        return self._client.request("GET", f"{BASE_PATH}/{payout_id}")

    def estimate_fees(self, *, currency: Optional[str] = None) -> CalculatePayoutFeesResponseDataDto:
        """Estimate payout fees.

        Args:
            currency: Currency for which to estimate fees. Optional.

        Returns:
            Fee breakdown for fiat and crypto payout methods.
        """
        params: Dict[str, Any] = {
            "currency": currency,
        }
        return self._client.request("GET", f"{BASE_PATH}/fees", params=params)


class AsyncPayoutsResource:
    """Asynchronous payouts resource."""

    def __init__(self, client: AsyncHttpClient) -> None:
        self._client = client

    async def create(
        self,
        *,
        method: str,
        currency: str,
        amount: str,
        recipient_id: str,
        narration: Optional[str] = None,
        reference: Optional[str] = None,
    ) -> PayoutV2Dto:
        """Create a new payout (async)."""
        body: Dict[str, Any] = {
            "method": method,
            "currency": currency,
            "amount": amount,
            "recipientId": recipient_id,
        }
        if narration is not None:
            body["narration"] = narration
        if reference is not None:
            body["reference"] = reference

        return await self._client.request("POST", BASE_PATH, json_body=body)

    async def list(
        self,
        *,
        page: int = 1,
        size: int = 10,
        search: Optional[str] = None,
        status: Optional[str] = None,
        session_reference: Optional[str] = None,
    ) -> PaginatedResponse:
        """List payouts with pagination (async)."""
        params: Dict[str, Any] = {
            "page": page,
            "size": size,
            "search": search,
            "status": status,
            "sessionReference": session_reference,
        }
        return await self._client.request_paginated("GET", BASE_PATH, params=params)

    def list_auto_paginate(self, **kwargs: Any) -> AsyncIterator[PayoutV2Dto]:
        """Iterate over all payouts across all pages (async)."""
        return async_paginate(self.list, params=kwargs)

    async def get(self, payout_id: str) -> PayoutV2Dto:
        """Get a payout by ID (async)."""
        return await self._client.request("GET", f"{BASE_PATH}/{payout_id}")

    async def estimate_fees(self, *, currency: Optional[str] = None) -> CalculatePayoutFeesResponseDataDto:
        """Estimate payout fees (async)."""
        params: Dict[str, Any] = {
            "currency": currency,
        }
        return await self._client.request("GET", f"{BASE_PATH}/fees", params=params)
