# 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.worker_termination_container import WorkerTerminationContainer
from ..models.worker_termination_body_container import WorkerTerminationBodyContainer
from ..models.worker_bank_accounts_info_container import WorkerBankAccountsInfoContainer
from ..models.utils.cast_models import cast_models
from ..models.gp_payslips_list_container import GpPayslipsListContainer
from ..models.gp_payslip_download_url_container import GpPayslipDownloadUrlContainer
from ..models.gp_payroll_event_report_container import GpPayrollEventReportContainer
from ..models.gp_employee_pto_to_update_container import GpEmployeePtoToUpdateContainer
from ..models.gp_employee_information_updated_container import (
    GpEmployeeInformationUpdatedContainer,
)
from ..models.gp_employee_information_to_update_container import (
    GpEmployeeInformationToUpdateContainer,
)
from ..models.gp_employee_compensation_updated_container import (
    GpEmployeeCompensationUpdatedContainer,
)
from ..models.gp_employee_compensation_to_update_container import (
    GpEmployeeCompensationToUpdateContainer,
)
from ..models.gp_employee_address_updated_container import (
    GpEmployeeAddressUpdatedContainer,
)
from ..models.gp_employee_address_to_update_container import (
    GpEmployeeAddressToUpdateContainer,
)
from ..models.gp_contract_to_create_container import GpContractToCreateContainer
from ..models.gp_contract_created_container import GpContractCreatedContainer
from ..models.global_payroll_g2_n_report_container import (
    GlobalPayrollG2NReportContainer,
)
from ..models.generic_result_updated import GenericResultUpdated
from ..models.bank_account_updated_container import BankAccountUpdatedContainer
from ..models.bank_account_guide_container import BankAccountGuideContainer
from ..models.add_worker_bank_account_container import AddWorkerBankAccountContainer


class GlobalPayrollService(BaseService):

    @cast_models
    def create_gp_contract(
        self, request_body: GpContractToCreateContainer
    ) -> GpContractCreatedContainer:
        """Create a Global Payroll contract.

        :param request_body: The request body.
        :type request_body: GpContractToCreateContainer
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpContractCreatedContainer
        """

        Validator(GpContractToCreateContainer).validate(request_body)

        serialized_request = (
            Serializer(f"{self.base_url}/contracts/gp", self.get_default_headers())
            .serialize()
            .set_method("POST")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return GpContractCreatedContainer._unmap(response)

    @cast_models
    def get_worker_payslips(self, worker_id: str) -> GpPayslipsListContainer:
        """Get of payslips for an employee.

        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpPayslipsListContainer
        """

        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/payslips",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return GpPayslipsListContainer._unmap(response)

    @cast_models
    def update_gp_employee_address(
        self, request_body: GpEmployeeAddressToUpdateContainer, worker_id: str
    ) -> GpEmployeeAddressUpdatedContainer:
        """Update the address of a Global Payroll employee.

        :param request_body: The request body.
        :type request_body: GpEmployeeAddressToUpdateContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpEmployeeAddressUpdatedContainer
        """

        Validator(GpEmployeeAddressToUpdateContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/address",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("PATCH")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return GpEmployeeAddressUpdatedContainer._unmap(response)

    @cast_models
    def get_gp_bank_accounts(self, worker_id: str) -> WorkerBankAccountsInfoContainer:
        """Retrieve all bank accounts for an employee.

        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: WorkerBankAccountsInfoContainer
        """

        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/banks",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return WorkerBankAccountsInfoContainer._unmap(response)

    @cast_models
    def add_gp_bank_account(
        self, request_body: AddWorkerBankAccountContainer, worker_id: str
    ) -> BankAccountUpdatedContainer:
        """Add a new bank account for an employee.

        :param request_body: The request body.
        :type request_body: AddWorkerBankAccountContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: BankAccountUpdatedContainer
        """

        Validator(AddWorkerBankAccountContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/banks",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("POST")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return BankAccountUpdatedContainer._unmap(response)

    @cast_models
    def patch_gp_bank_account(
        self, request_body: AddWorkerBankAccountContainer, worker_id: str, bank_id: str
    ) -> BankAccountUpdatedContainer:
        """Modify bank account for an employee.

        :param request_body: The request body.
        :type request_body: AddWorkerBankAccountContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        :param bank_id: Bank Account id.
        :type bank_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: BankAccountUpdatedContainer
        """

        Validator(AddWorkerBankAccountContainer).validate(request_body)
        Validator(str).validate(worker_id)
        Validator(str).validate(bank_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/banks/{{bank_id}}",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .add_path("bank_id", bank_id)
            .serialize()
            .set_method("PATCH")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return BankAccountUpdatedContainer._unmap(response)

    @cast_models
    def get_gp_bank_guide(self, worker_id: str) -> BankAccountGuideContainer:
        """Retrieve the bank form guide for employee.

        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: BankAccountGuideContainer
        """

        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/banks/guide",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return BankAccountGuideContainer._unmap(response)

    @cast_models
    def update_gp_employee_compensation(
        self, request_body: GpEmployeeCompensationToUpdateContainer, worker_id: str
    ) -> GpEmployeeCompensationUpdatedContainer:
        """Update the compensation of a Global Payroll employee. Returns the full compensation history including the update.

        :param request_body: The request body.
        :type request_body: GpEmployeeCompensationToUpdateContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpEmployeeCompensationUpdatedContainer
        """

        Validator(GpEmployeeCompensationToUpdateContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/compensation",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("PATCH")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return GpEmployeeCompensationUpdatedContainer._unmap(response)

    @cast_models
    def update_gp_employee_pto(
        self, request_body: GpEmployeePtoToUpdateContainer, worker_id: str
    ) -> GenericResultUpdated:
        """Update the PTO policy of a Global Payroll employee.

        :param request_body: The request body.
        :type request_body: GpEmployeePtoToUpdateContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GenericResultUpdated
        """

        Validator(GpEmployeePtoToUpdateContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/pto-policy",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("PATCH")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return GenericResultUpdated._unmap(response)

    @cast_models
    def update_gp_employee_information(
        self, request_body: GpEmployeeInformationToUpdateContainer, worker_id: str
    ) -> GpEmployeeInformationUpdatedContainer:
        """Update Global Payroll employee information.

        :param request_body: The request body.
        :type request_body: GpEmployeeInformationToUpdateContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpEmployeeInformationUpdatedContainer
        """

        Validator(GpEmployeeInformationToUpdateContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/employee-information",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("PATCH")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return GpEmployeeInformationUpdatedContainer._unmap(response)

    @cast_models
    def get_download_url_for_gp_payslip(
        self, worker_id: str, payslip_id: str
    ) -> GpPayslipDownloadUrlContainer:
        """Get download url for GP payslip.

        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        :param payslip_id: Unique identifier for a payslip.
        :type payslip_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpPayslipDownloadUrlContainer
        """

        Validator(str).validate(worker_id)
        Validator(str).validate(payslip_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/payslips/{{payslip_id}}/download",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .add_path("payslip_id", payslip_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return GpPayslipDownloadUrlContainer._unmap(response)

    @cast_models
    def get_gp_legal_entities(
        self, legal_entity_id: str, start_date: str = None
    ) -> GpPayrollEventReportContainer:
        """Get list of global payroll events by legal entities.

        :param legal_entity_id: Id of an legal entity.
        :type legal_entity_id: str
        :param start_date: Start date of payroll report., defaults to None
        :type start_date: str, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GpPayrollEventReportContainer
        """

        Validator(str).validate(legal_entity_id)
        Validator(str).is_optional().pattern("^\d{4}-\d{2}-\d{2}$").validate(start_date)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/legal-entities/{{legal_entity_id}}/reports",
                self.get_default_headers(),
            )
            .add_path("legal_entity_id", legal_entity_id)
            .add_query("start_date", start_date, nullable=True)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return GpPayrollEventReportContainer._unmap(response)

    @cast_models
    def get_gross_to_net_gp_reports(
        self, gp_report_id: str
    ) -> GlobalPayrollG2NReportContainer:
        """Get list of global payroll reports detailing gross-to-net calculations.

        :param gp_report_id: Id of gp report.
        :type gp_report_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GlobalPayrollG2NReportContainer
        """

        Validator(str).validate(gp_report_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/reports/{{gp_report_id}}/gross_to_net",
                self.get_default_headers(),
            )
            .add_path("gp_report_id", gp_report_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return GlobalPayrollG2NReportContainer._unmap(response)

    @cast_models
    def download_gross_to_net_gp_report(self, gp_report_id: str) -> str:
        """Download global payroll reports detailing gross-to-net calculations.

        :param gp_report_id: Id of gp report.
        :type gp_report_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: str
        """

        Validator(str).validate(gp_report_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/reports/{{gp_report_id}}/gross_to_net/csv",
                self.get_default_headers(),
            )
            .add_path("gp_report_id", gp_report_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return response

    @cast_models
    def request_termination(
        self, request_body: WorkerTerminationBodyContainer, worker_id: str
    ) -> WorkerTerminationContainer:
        """Request a termination for a global payroll employee. A successful call starts the termination process and does not confirm termination.

        :param request_body: The request body.
        :type request_body: WorkerTerminationBodyContainer
        :param worker_id: Unique identifier for a worker.
        :type worker_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: WorkerTerminationContainer
        """

        Validator(WorkerTerminationBodyContainer).validate(request_body)
        Validator(str).validate(worker_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/gp/workers/{{worker_id}}/terminations",
                self.get_default_headers(),
            )
            .add_path("worker_id", worker_id)
            .serialize()
            .set_method("POST")
            .set_body(request_body)
        )

        response = self.send_request(serialized_request)

        return WorkerTerminationContainer._unmap(response)
