from __future__ import annotations

import httpx

from .models import (
    Balance,
    CustomerBalanceResponse,
    CustomerInvoiceDetail,
    CustomerInvoiceResponse,
    CustomerWithdrawalCreateRequest,
    CustomerWithdrawalResponse,
    InvoiceCreateRequest,
    InvoiceDetail,
    InvoiceResponse,
    PaginatedCustomerInvoiceDetailList,
    PaginatedCustomerTransactionResponseList,
    PaginatedCustomerWithdrawalResponseList,
    PaginatedInvoiceDetailList,
    PaginatedPaymentLinkList,
    PaginatedTransactionList,
    PaymentLink,
    PaymentLinkCreateRequest,
    PaymentLinkPayInputRequest,
    PaymentLinkPublic,
    Withdrawal,
    WithdrawalCreateRequest,
)


class SyncPaymentsPaymentsAPI:
    """Synchronous API endpoints for Payments."""

    def __init__(self, client: httpx.Client):
        """Initialize sync sub-client with shared httpx client."""
        self._client = client

    def balance_retrieve(self) -> Balance:
        url = "/api/payments/balance/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Balance.model_validate(response.json())


    def customer_balance_retrieve(self) -> CustomerBalanceResponse:
        """
        GET /customer/balance/ — customer balance (always 200).
        """
        url = "/api/payments/customer/balance/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CustomerBalanceResponse.model_validate(response.json())


    def customer_invoices_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedCustomerInvoiceDetailList]:
        """
        GET /customer/invoices/ — payment history.
        """
        url = "/api/payments/customer/invoices/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedCustomerInvoiceDetailList.model_validate(response.json())


    def customer_invoices_retrieve(self, id: str) -> CustomerInvoiceDetail:
        """
        GET /customer/invoices/{id}/ — invoice detail.
        """
        url = f"/api/payments/customer/invoices/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CustomerInvoiceDetail.model_validate(response.json())


    def customer_profile_retrieve(self) -> None:
        """
        GET /customer/profile/ — customer profile (always 200).
        """
        url = "/api/payments/customer/profile/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


    def customer_transactions_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedCustomerTransactionResponseList]:
        """
        GET /customer/transactions/ — transaction history.
        """
        url = "/api/payments/customer/transactions/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedCustomerTransactionResponseList.model_validate(response.json())


    def customer_withdrawals_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedCustomerWithdrawalResponseList]:
        """
        GET /customer/withdrawals/ — withdrawals list.
        """
        url = "/api/payments/customer/withdrawals/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedCustomerWithdrawalResponseList.model_validate(response.json())


    def customer_withdrawals_create_create(
        self,
        data: CustomerWithdrawalCreateRequest,
    ) -> CustomerWithdrawalResponse:
        """
        POST /customer/withdrawals/create/ — create withdrawal.
        """
        url = "/api/payments/customer/withdrawals/create/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CustomerWithdrawalResponse.model_validate(response.json())


    def invoices_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedInvoiceDetailList]:
        url = "/api/payments/invoices/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedInvoiceDetailList.model_validate(response.json())


    def invoices_retrieve(self, id: str) -> InvoiceDetail:
        url = f"/api/payments/invoices/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return InvoiceDetail.model_validate(response.json())


    def invoices_cancel_create(self, id: str) -> InvoiceDetail:
        url = f"/api/payments/invoices/{id}/cancel/"
        response = self._client.post(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return InvoiceDetail.model_validate(response.json())


    def invoices_status_retrieve(self, id: str) -> InvoiceResponse:
        url = f"/api/payments/invoices/{id}/status/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return InvoiceResponse.model_validate(response.json())


    def invoices_create_create(self, data: InvoiceCreateRequest) -> InvoiceResponse:
        url = "/api/payments/invoices/create/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return InvoiceResponse.model_validate(response.json())


    def links_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedPaymentLinkList]:
        url = "/api/payments/links/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedPaymentLinkList.model_validate(response.json())


    def links_create_create(self, data: PaymentLinkCreateRequest) -> PaymentLink:
        url = "/api/payments/links/create/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaymentLink.model_validate(response.json())


    def public_links_retrieve(self, id: str) -> PaymentLinkPublic:
        """
        GET /links/{id}/ — public.
        """
        url = f"/api/payments/public/links/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaymentLinkPublic.model_validate(response.json())


    def public_links_pay_create(
        self,
        id: str,
        data: PaymentLinkPayInputRequest,
    ) -> CustomerInvoiceResponse:
        """
        POST /links/{id}/pay/ — public.
        """
        url = f"/api/payments/public/links/{id}/pay/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CustomerInvoiceResponse.model_validate(response.json())


    def transactions_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedTransactionList]:
        url = "/api/payments/transactions/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedTransactionList.model_validate(response.json())


    def withdrawals_create(self, data: WithdrawalCreateRequest) -> Withdrawal:
        url = "/api/payments/withdrawals/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Withdrawal.model_validate(response.json())


    def withdrawals_retrieve(self, id: str) -> Withdrawal:
        url = f"/api/payments/withdrawals/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Withdrawal.model_validate(response.json())


    def withdrawals_cancel_create(self, id: str) -> Withdrawal:
        url = f"/api/payments/withdrawals/{id}/cancel/"
        response = self._client.post(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Withdrawal.model_validate(response.json())


