# 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.premium_to_add_container import PremiumToAddContainer
from ..models.premium_result_added_container import PremiumResultAddedContainer
from ..models.generic_result_deleted import GenericResultDeleted
from ..models.generic_result_created import GenericResultCreated
from ..models.contract_to_terminate_container import ContractToTerminateContainer
from ..models.contract_to_create_container_payg_tasks import (
    ContractToCreateContainerPaygTasks,
)
from ..models.contract_to_create_container_payg_milestones import (
    ContractToCreateContainerPaygMilestones,
)
from ..models.contract_to_create_container_pay_as_you_go_time_based import (
    ContractToCreateContainerPayAsYouGoTimeBased,
)
from ..models.contract_to_create_container_ongoing_time_based import (
    ContractToCreateContainerOngoingTimeBased,
)
from ..models.contract_to_create_container import ContractToCreateContainer
from ..models.contract_to_amend_details_container import ContractToAmendDetailsContainer
from ..models.contract_termination_result_container import (
    ContractTerminationResultContainer,
)
from ..models.contract_container_payg_tasks import ContractContainerPaygTasks
from ..models.contract_container_payg_milestones import ContractContainerPaygMilestones
from ..models.contract_container_pay_as_you_go_time_based import (
    ContractContainerPayAsYouGoTimeBased,
)
from ..models.contract_container_ongoing_time_based import (
    ContractContainerOngoingTimeBased,
)
from ..models.contract_container import ContractContainer


class ContractorsService(BaseService):

    @cast_models
    def create_contract_time_based(
        self, request_body: ContractToCreateContainerPayAsYouGoTimeBased
    ) -> ContractContainerPayAsYouGoTimeBased:
        """Create a new contract (time-based).

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

        Validator(ContractToCreateContainerPayAsYouGoTimeBased).validate(request_body)

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

        response = self.send_request(serialized_request)

        return ContractContainerPayAsYouGoTimeBased._unmap(response)

    @cast_models
    def create_contract_task_based(
        self, request_body: ContractToCreateContainerPaygTasks
    ) -> ContractContainerPaygTasks:
        """Create a new Deel contract.

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

        Validator(ContractToCreateContainerPaygTasks).validate(request_body)

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

        response = self.send_request(serialized_request)

        return ContractContainerPaygTasks._unmap(response)

    @cast_models
    def create_contract_milestone_based(
        self, request_body: ContractToCreateContainerPaygMilestones
    ) -> ContractContainerPaygMilestones:
        """Create a new Deel contract.

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

        Validator(ContractToCreateContainerPaygMilestones).validate(request_body)

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

        response = self.send_request(serialized_request)

        return ContractContainerPaygMilestones._unmap(response)

    @cast_models
    def create_contract_fixed_rate(
        self, request_body: ContractToCreateContainerOngoingTimeBased
    ) -> ContractContainerOngoingTimeBased:
        """Create a new Deel contract.

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

        Validator(ContractToCreateContainerOngoingTimeBased).validate(request_body)

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

        response = self.send_request(serialized_request)

        return ContractContainerOngoingTimeBased._unmap(response)

    @cast_models
    def create_contract(
        self, request_body: ContractToCreateContainer
    ) -> ContractContainer:
        """Create a new Deel contract.

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

        Validator(ContractToCreateContainer).validate(request_body)

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

        response = self.send_request(serialized_request)

        return ContractContainer._unmap(response)

    @cast_models
    def get_contract_preview(self, contract_id: str, template_id: str = None) -> str:
        """Retrieve an IC and EOR contract agreement content in HTML. If no template is specified, the default or currently assigned template will be used. This endpoint does not support Global Payroll contract type.

        :param contract_id: Deel contract id.
        :type contract_id: str
        :param template_id: ID of an existing contract template., defaults to None
        :type template_id: str, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: str
        """

        Validator(str).validate(contract_id)
        Validator(str).is_optional().validate(template_id)

        serialized_request = (
            Serializer(
                f"{self.base_url}/contracts/{{contract_id}}/preview",
                self.get_default_headers(),
            )
            .add_path("contract_id", contract_id)
            .add_query("templateId", template_id)
            .serialize()
            .set_method("GET")
        )

        response = self.send_request(serialized_request)

        return response

    @cast_models
    def amend_contract_details(
        self, request_body: ContractToAmendDetailsContainer, contract_id: str
    ) -> GenericResultCreated:
        """Amend the details of a contract. Please note that if the contract is already signed or active, then the update will have to be approved and re-signed for to take effect.

        :param request_body: The request body.
        :type request_body: ContractToAmendDetailsContainer
        :param contract_id: Deel contract id.
        :type contract_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GenericResultCreated
        """

        Validator(ContractToAmendDetailsContainer).validate(request_body)
        Validator(str).validate(contract_id)

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

        response = self.send_request(serialized_request)

        return GenericResultCreated._unmap(response)

    @cast_models
    def terminate_contract(
        self, request_body: ContractToTerminateContainer, contract_id: str
    ) -> ContractTerminationResultContainer:
        """Terminate an active contract.

        :param request_body: The request body.
        :type request_body: ContractToTerminateContainer
        :param contract_id: Deel contract id.
        :type contract_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: ContractTerminationResultContainer
        """

        Validator(ContractToTerminateContainer).validate(request_body)
        Validator(str).validate(contract_id)

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

        response = self.send_request(serialized_request)

        return ContractTerminationResultContainer._unmap(response)

    @cast_models
    def add_premium(
        self, contract_id: str, request_body: PremiumToAddContainer = None
    ) -> PremiumResultAddedContainer:
        """Add additional protection against misclassification by upgrading to Deel Premium.

        :param request_body: The request body., defaults to None
        :type request_body: PremiumToAddContainer, optional
        :param contract_id: Deel contract id.
        :type contract_id: str
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: PremiumResultAddedContainer
        """

        Validator(PremiumToAddContainer).is_optional().validate(request_body)
        Validator(str).validate(contract_id)

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

        response = self.send_request(serialized_request)

        return PremiumResultAddedContainer._unmap(response)

    @cast_models
    def remove_premium_from_contract(
        self, contract_id: str, reason: str = None
    ) -> GenericResultDeleted:
        """Remove Deel Premium from an existing contract.

        :param contract_id: Deel contract id.
        :type contract_id: str
        :param reason: Reason for deleting an existing Deel Premium from a contract., defaults to None
        :type reason: str, optional
        ...
        :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
        ...
        :return: Successful operation.
        :rtype: GenericResultDeleted
        """

        Validator(str).validate(contract_id)
        Validator(str).is_optional().validate(reason)

        serialized_request = (
            Serializer(
                f"{self.base_url}/contracts/{{contract_id}}/premium",
                self.get_default_headers(),
            )
            .add_path("contract_id", contract_id)
            .add_query("reason", reason)
            .serialize()
            .set_method("DELETE")
        )

        response = self.send_request(serialized_request)

        return GenericResultDeleted._unmap(response)
