from staff.budget_position.models import BudgetPosition, BudgetPositionAssignment, BudgetPositionAssignmentStatus


class AssignmentPartQueryBuilder:
    @property
    def _budget_position_table(self) -> str:
        return BudgetPosition._meta.db_table

    @property
    def _budget_position_assignment_table(self) -> str:
        return BudgetPositionAssignment._meta.db_table

    def _static_part(self) -> str:
        return f"""
        SELECT
            {self.assignment_alias}.id,
            {self.assignment_alias}.department_id,
            {self.assignment_alias}.value_stream_id,
            {self.assignment_alias}.geography_id,
            (CASE WHEN next_assignment.id IS NULL THEN budget_position.headcount ELSE 0 END)
                AS headcount,
            (CASE WHEN {self.assignment_alias}.status = '{BudgetPositionAssignmentStatus.OCCUPIED.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS working,
            (CASE WHEN {self.assignment_alias}.status = '{BudgetPositionAssignmentStatus.OFFER.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS offer,
            (CASE WHEN {self.assignment_alias}.status = '{BudgetPositionAssignmentStatus.VACANCY_OPEN.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS vacancies,
            (CASE WHEN
                    {self.assignment_alias}.status IN
                    ('{BudgetPositionAssignmentStatus.RESERVE.value}',
                    '{BudgetPositionAssignmentStatus.VACANCY_PLAN.value}')
                    AND budget_position.headcount > 0
                    AND {self.assignment_alias}.creates_new_position
                  THEN budget_position.headcount
                  ELSE 0 END)
                AS vacancies_plan_new,
             (CASE WHEN
                    {self.assignment_alias}.status IN
                    ('{BudgetPositionAssignmentStatus.RESERVE.value}',
                    '{BudgetPositionAssignmentStatus.VACANCY_PLAN.value}')
                    AND budget_position.headcount > 0
                    AND NOT {self.assignment_alias}.creates_new_position
                   THEN budget_position.headcount
                   ELSE 0 END)
                AS vacancies_plan_replacement,
             (CASE WHEN
                    {self.assignment_alias}.status = '{BudgetPositionAssignmentStatus.RESERVE.value}'
                    AND budget_position.headcount < 0
                   THEN budget_position.headcount
                   ELSE 0 END)
                AS credit,
             (CASE WHEN next_assignment.status = '{BudgetPositionAssignmentStatus.OCCUPIED.value}'
                AND {self.assignment_alias}.status != '{BudgetPositionAssignmentStatus.MATERNITY.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS working_crossing,
             (CASE WHEN next_assignment.status = '{BudgetPositionAssignmentStatus.OFFER.value}'
                AND {self.assignment_alias}.status != '{BudgetPositionAssignmentStatus.MATERNITY.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS offer_crossing,
             (CASE WHEN next_assignment.status = '{BudgetPositionAssignmentStatus.VACANCY_PLAN.value}'
                AND {self.assignment_alias}.status != '{BudgetPositionAssignmentStatus.MATERNITY.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS vacancies_plan_crossing,
             (CASE WHEN next_assignment.status = '{BudgetPositionAssignmentStatus.VACANCY_OPEN.value}'
                AND {self.assignment_alias}.status != '{BudgetPositionAssignmentStatus.MATERNITY.value}'
                THEN budget_position.headcount ELSE 0 END)
                AS vacancies_crossing
        FROM {self._budget_position_assignment_table} AS {self.assignment_alias}
        INNER JOIN {self._budget_position_table} AS budget_position
            ON (budget_position.id = {self.assignment_alias}.budget_position_id)
        LEFT JOIN {self._budget_position_assignment_table} AS next_assignment
            ON (next_assignment.previous_assignment_id = {self.assignment_alias}.id
                AND next_assignment.intranet_status = 1)
        WHERE {self.assignment_alias}.intranet_status = 1
        """

    def build(self) -> str:
        return self._static_part()

    @property
    def assignment_alias(self) -> str:
        return 'assignment'
