from django.utils.functional import cached_property

from intranet.femida.src.staff.helpers import get_department_chiefs_chain, get_hr_partners


class IssueMembership:
    """
    Роли пользователей в понятиях JOB и SALARY тикетов

    chiefs (руководители) - люди, которые непосредственно участвуют в согласовании
      вакансий и офферов. Таковыми считаются:
      1. руководитель подразделения, куда производится наём;
      2. все вышестоящие руководители из направления, куда производится наём;
      Из этого списка всегда исключается volozh@ и заменяемый сотрудник,
      если это вакансия/оффер на замену.

    head (прямой руководитель) - прямым руководителем считается ближайший
      руководитель для подразделения, куда производится наём.

    hr_partners (HR-партнёры) - люди, которые числятся HR-партнёрами
      для подразделения на Стаффе.

    access (доступы) - люди, которые получат доступ в JOB-тикет.
      Список актуален только на момент создания тикета. В список входят
      все вышеперечисленные люди, а также явно заданные через `extra_access`.
      На момент создания тикета, например, в `extra_access` попадает
      нанимающий менеджер на вакансии.
      Из итогового списка исключается заменяемый сотрудник, если вакансия на замену.

    """
    def __init__(self, department=None, instead_of=None, extra_access=None):
        self.department = department
        self.instead_of = instead_of
        self.extra_access = extra_access or []

    @cached_property
    def _raw_chiefs(self):
        if not self.department:
            return []
        return get_department_chiefs_chain(
            department=self.department,
            from_current_direction_only=True,
        )

    @cached_property
    def chiefs(self):
        usernames_to_exclude = {'volozh'}
        if self.instead_of:
            usernames_to_exclude.add(self.instead_of.username)
        return [u for u in self._raw_chiefs if u.username not in usernames_to_exclude]

    @cached_property
    def head(self):
        return self._raw_chiefs[0] if self._raw_chiefs else None

    @cached_property
    def hr_partners(self):
        if not self.department:
            return []
        return get_hr_partners(self.department)

    @cached_property
    def access(self):
        result = set(self.chiefs) | set(self.hr_partners) | set(self.extra_access)
        return result - {self.instead_of}

    @classmethod
    def from_vacancy(cls, vacancy):
        extra_access = []
        if vacancy.hiring_manager:
            extra_access.append(vacancy.hiring_manager)
        return cls(
            department=vacancy.department,
            instead_of=vacancy.instead_of,
            extra_access=extra_access,
        )

    @classmethod
    def from_offer(cls, offer):
        return cls(
            department=offer.department,
            instead_of=offer.vacancy.instead_of,
        )
