# This file was generated by liblab | https://liblab.com/

from .utils.validator import Validator
from .utils.base_service import BaseService
from ..net.transport.serializer import Serializer
from ..models.utils.cast_models import cast_models
from ..models.payment_list_container import PaymentListContainer
from ..models.payment_break_down_container import PaymentBreakDownContainer
from ..models.invoice_list_container import InvoiceListContainer
from ..models.invoice_download_link_container import InvoiceDownloadLinkContainer
from ..models.get_payment_list_entities import GetPaymentListEntities
from ..models.get_payment_list_currencies import GetPaymentListCurrencies
from ..models.get_invoice_list_entities import GetInvoiceListEntities
from ..models.deel_invoice_list_container import DeelInvoiceListContainer


class AccountingService(BaseService):

    @cast_models
    def get_invoice_list(
        self,
        issued_from_date: str = None,
        issued_to_date: str = None,
        entities: GetInvoiceListEntities = None,
        limit: float = None,
        offset: float = None,
    ) -> InvoiceListContainer:
        """Retrieve a list of paid invoices for your workforce.

        :param issued_from_date: to get records created after given issue date, defaults to None
        :type issued_from_date: str, optional
        :param issued_to_date: to get records created before given issued date, defaults to None
        :type issued_to_date: str, optional
        :param entities: Filter by legal entity type; company, or individual, defaults to None
        :type entities: GetInvoiceListEntities, optional
        :param limit: Return a page of results with given number of records; NOTE technically ALL query parameters are strings or array of strings, defaults to None
        :type limit: float, optional
        :param offset: Return a page of results after given index of row; NOTE technically ALL query parameters are strings or array of strings', defaults to None
        :type offset: float, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: InvoiceListContainer
        """

        Validator(str).is_optional().validate(issued_from_date)
        Validator(str).is_optional().validate(issued_to_date)
        Validator(GetInvoiceListEntities).is_optional().validate(entities)
        Validator(float).is_optional().min(1).max(99).validate(limit)
        Validator(float).is_optional().min(0).max(999999999).validate(offset)

        serialized_request = (
            Serializer(f"{self.base_url}/invoices", self.get_default_headers())
            .add_query("issued_from_date", issued_from_date)
            .add_query("issued_to_date", issued_to_date)
            .add_query("entities", entities)
            .add_query("limit", limit)
            .add_query("offset", offset)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return InvoiceListContainer._unmap(response)

    @cast_models
    def get_deel_invoice_list(
        self, contract_id: str, limit: float = None, offset: float = None
    ) -> DeelInvoiceListContainer:
        """Retrieve a list of invoices related to Deel fees.

        :param contract_id: Deel contract id.
        :type contract_id: str
        :param limit: Return a page of results with given number of records; NOTE technically ALL query parameters are strings or array of strings, defaults to None
        :type limit: float, optional
        :param offset: Return a page of results after given index of row; NOTE technically ALL query parameters are strings or array of strings', defaults to None
        :type offset: float, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: DeelInvoiceListContainer
        """

        Validator(str).validate(contract_id)
        Validator(float).is_optional().min(1).max(99).validate(limit)
        Validator(float).is_optional().min(0).max(999999999).validate(offset)

        serialized_request = (
            Serializer(f"{self.base_url}/invoices/deel", self.get_default_headers())
            .add_query("limit", limit)
            .add_query("offset", offset)
            .add_query("contract_id", contract_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return DeelInvoiceListContainer._unmap(response)

    @cast_models
    def get_billing_invoice_download_link(
        self, invoice_id: str
    ) -> InvoiceDownloadLinkContainer:
        """Get link to download the invoice PDF.

        :param invoice_id: ID of an existing invoice
        :type invoice_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: InvoiceDownloadLinkContainer
        """

        Validator(str).validate(invoice_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/invoices/{{invoice_id}}/download",
                self.get_default_headers(),
            )
            .add_path("invoice_id", invoice_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return InvoiceDownloadLinkContainer._unmap(response)

    @cast_models
    def get_payment_list(
        self,
        date_from: str = None,
        date_to: str = None,
        currencies: GetPaymentListCurrencies = None,
        entities: GetPaymentListEntities = None,
    ) -> PaymentListContainer:
        """Retrieve a list of payments made to Deel.

        :param date_from: Filtered results will include records created on or after the provided date., defaults to None
        :type date_from: str, optional
        :param date_to: Filtered results will include records created before the provided date., defaults to None
        :type date_to: str, optional
        :param currencies: Currency codes of contracts to filter., defaults to None
        :type currencies: GetPaymentListCurrencies, optional
        :param entities: Filter by legal entity type; company, or individual, defaults to None
        :type entities: GetPaymentListEntities, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: PaymentListContainer
        """

        Validator(str).is_optional().pattern("^\d{4}-\d{2}-\d{2}$").validate(date_from)
        Validator(str).is_optional().pattern("^\d{4}-\d{2}-\d{2}$").validate(date_to)
        Validator(GetPaymentListCurrencies).is_optional().validate(currencies)
        Validator(GetPaymentListEntities).is_optional().validate(entities)

        serialized_request = (
            Serializer(f"{self.base_url}/payments", self.get_default_headers())
            .add_query("date_from", date_from, nullable=True)
            .add_query("date_to", date_to, nullable=True)
            .add_query("currencies", currencies)
            .add_query("entities", entities)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return PaymentListContainer._unmap(response)

    @cast_models
    def get_payments_break_down_by_id(
        self, payment_id: str
    ) -> PaymentBreakDownContainer:
        """Get a full breakdown of a payment made to Deel. Breakdown will include individual invoices and Deel fee as line items.

        :param payment_id: payment_id
        :type payment_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: PaymentBreakDownContainer
        """

        Validator(str).validate(payment_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/payments/{{payment_id}}/breakdown",
                self.get_default_headers(),
            )
            .add_path("payment_id", payment_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return PaymentBreakDownContainer._unmap(response)
