from copy import deepcopy
from random import randrange

from django.core.exceptions import ValidationError

from staff.departments.controllers.proposal import ProposalCtl
from staff.departments.controllers.actions.person_action import PersonAction
from staff.groups.models import GROUP_TYPE_CHOICES, GroupMembership
from staff.lib.db import atomic


class AddPersonChangeUseCase:
    def __init__(self, proposal_id: str):
        self._proposal_ctl = ProposalCtl(proposal_id)

    def _validate_person(self, person_login):
        if person_login in {action.login for action in self._proposal_ctl.person_action_objs}:
            raise ValidationError(f'Login {person_login} already in proposal', code='login_already_in_proposal')

    def change_person_department(self, person_login: str, dep_url: str, reason: str):
        self._validate_person(person_login)

        with atomic():
            proposal_data = deepcopy(self._proposal_ctl.proposal_object)
            proposal_data['actions'] = []  # sometimes we are loosing empty dep actions
            persons_actions = proposal_data['persons']['actions']
            services_qs = (
                GroupMembership.objects
                .filter(staff__login=person_login, group__type=GROUP_TYPE_CHOICES.SERVICE, group__intranet_status=1)
            )
            new_person_action = PersonAction(
                login=person_login,
                sections=['department'],
                action_id=f'act_{randrange(10000, 100000)}',
                comment=reason,
                department=PersonAction.DepartmentChange(
                    changing_duties=False,
                    department=dep_url,
                    with_budget=True,
                    service_groups=[gm.group.url for gm in services_qs]
                ),
            )

            persons_actions.append(new_person_action.as_dict())
            self._proposal_ctl.update(proposal_data)
            self._proposal_ctl.save()

    def recalculate_person_schemes(self, person_login: str, reason: str):
        self._validate_person(person_login)

        with atomic():
            proposal_data = deepcopy(self._proposal_ctl.proposal_object)
            proposal_data['actions'] = []  # sometimes we are loosing empty dep actions
            persons_actions = proposal_data['persons']['actions']
            new_person_action = PersonAction(
                login=person_login,
                sections=['grade'],
                action_id=f'act_{randrange(10000, 100000)}',
                comment=reason,
                grade=PersonAction.GradeChange(force_recalculate_schemes=True),
            )

            persons_actions.append(new_person_action.as_dict())
            self._proposal_ctl.update(proposal_data)
            self._proposal_ctl.save()

    def change_office_person_schemes(self, person_login: str, office_id: int, reason: str):
        self._validate_person(person_login)

        with atomic():
            proposal_data = deepcopy(self._proposal_ctl.proposal_object)
            proposal_data['actions'] = []  # sometimes we are loosing empty dep actions
            persons_actions = proposal_data['persons']['actions']
            new_person_action = PersonAction(
                login=person_login,
                sections=['office'],
                office=office_id,
                action_id=f'act_{randrange(10000, 100000)}',
                comment=reason,
            )

            persons_actions.append(new_person_action.as_dict())
            self._proposal_ctl.update(proposal_data)
            self._proposal_ctl.save()
