import logging
import uuid

from staff.lib import waffle

from staff.lib.log import log_context

from staff.budget_position.workflow_service import use_cases, entities


logger = logging.getLogger(__name__)


class CreateWorkflowFromFemida:
    def __init__(
        self,
        repository: entities.WorkflowRepositoryInterface,
        staff_service: entities.StaffService,
        confirm_workflow: use_cases.ConfirmWorkflows,
        grade_calculator: entities.GradeCalculator,
        schemes_calculator: entities.SchemesCalculator,
        workflow_factory: entities.AbstractFemidaWorkflowFactory,
        oebs_service: entities.OEBSService,
    ):
        self._repository = repository
        self._staff_service = staff_service
        self._confirm_workflow = confirm_workflow
        self._grade_calculator = grade_calculator
        self._schemes_calculator = schemes_calculator
        self._oebs_service = oebs_service
        self._workflow_factory = workflow_factory

    def create(self, data: entities.FemidaData) -> uuid.UUID:
        logger.info('Creating workflow')
        self._add_grade(data)

        workflow = self._workflow_factory.create(data)
        workflow.vacancy_id = data.vacancy_id
        with log_context(workflow_id=str(workflow.id), expected_exceptions=[entities.OEBSError]):
            logger.info('Created workflow %s with id %s', workflow.code, workflow.id)
            self._set_schemes(data, workflow)
            self._repository.save(workflow)
            catalyst = self._staff_service.hr_analyst_responsible_for_department(data.department_id)
            self._confirm_workflow.confirm(workflow.id, catalyst and catalyst.id)
            return workflow.id

    def _set_schemes(self, data: entities.FemidaData, workflow: entities.AbstractWorkflow) -> None:
        if not waffle.switch_is_active('enable_table_flow_for_registry'):
            return

        schemes_set = self._schemes_calculator.scheme_set(
            department_id=data.department_id,
            occupation_id=data.occupation_id,
            grade_level=data.grade_level,
            is_internship=data.is_internship,
        )

        if not schemes_set:
            logger.info('For workflow %s schemes not found', workflow.id)
            return

        last_change = workflow.changes[-1]
        for change in workflow.changes:
            change.review_scheme_id = last_change.review_scheme_id or schemes_set.review_scheme_id
            change.bonus_scheme_id = last_change.bonus_scheme_id or schemes_set.bonus_scheme_id
            change.reward_scheme_id = last_change.reward_scheme_id or schemes_set.reward_scheme_id

    def _add_grade(self, data: entities.FemidaData):
        if data.has_grade:
            return

        if not data.has_occupation:
            return

        if data.grade_level:
            data.grade_id = self._oebs_service.get_grade_id(occupation=data.occupation_id, level=data.grade_level)
            return

        if not waffle.switch_is_active('enable_table_flow_for_registry'):
            return

        if data.professional_level:
            grade_id, grade_level = self._grade_calculator.grade_by_prof_level(
                occupation_id=data.occupation_id,
                prof_level=data.professional_level,
            )
            data.grade_id = grade_id
            data.grade_level = grade_level
