from django.db import models

from staff.departments.models import Department, DepartmentRoles


class AccessControlList(models.Model):
    """
    Список контроля доступа. Описывает профили данных соответствуют группе
    """
    name = models.CharField(max_length=256, default='Not specified!')
    description = models.CharField(max_length=1024, default='Not specified!')
    group = models.OneToOneField(to='django_intranet_stuff.Group',
                                 related_name='acl')
    dataprofiles = models.ManyToManyField('DataProfile', related_name='acl',
                                          blank=True)

    def __str__(self):
        return '%s (group: %s)' % (self.name, self.group.name)


class DataProfile(models.Model):
    """
    Профиль данных определяет, какие сущности доступны владельцу
    """

    # владельцу доступны сущности со значением в поле departament,
    # совпадающим с департаментом владельца профиля
    own_department_only = models.BooleanField(default=False)

    # владельцу доступны сущности со значением в поле departament,
    # входящим во множество подразделений, в которых владелец профиля
    # имеет роль Chief
    chiefed_departments_only = models.BooleanField(default=False)

    # сущности с конкретным значением в поле department
    department = models.ForeignKey(
        to='django_intranet_stuff.Department',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )

    # владельцу доступны сущности со значением в поле office,
    # совпадающим с офисом владельца профиля
    own_office_only = models.BooleanField(default=False)

    # сущности с конкретным значением в поле office
    office = models.ForeignKey(
        to='django_intranet_stuff.Office',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )

    def __str__(self):
        if self.own_department_only:
            department = 'own'
        elif self.chiefed_departments_only:
            department = 'chiefed'
        else:
            department = self.department or '*'
        return 'department:%s, office:%s' % (
            department,
            'own' if self.own_office_only else self.office or '*',
        )

    def to_Q(self, staff):
        """
        Метод превращает датапрофиль в Q-объект для конкретного пользователя,
        готовый для использования в фильтре.
        """
        Q = models.Q
        q = Q()

        def get_dep_q(dep):
            return Q(
                department__tree_id=dep.tree_id,
                department__lft__gte=dep.lft,
                department__rght__lte=dep.rght,
            )

        if self.own_department_only:
            q &= get_dep_q(staff.department)

        elif self.chiefed_departments_only:
            departments = (
                Department.objects
                .filter(
                    intranet_status=1,
                    departmentstaff__staff_id=staff.id,
                    departmentstaff__role_id=DepartmentRoles.CHIEF.value,
                )
            )
            sub_q = Q(id=None)
            for department in departments:
                sub_q |= get_dep_q(department)
            q &= sub_q

        elif self.department:
            q &= get_dep_q(self.department)

        if self.own_office_only:
            q &= Q(office=staff.office)
        elif self.office:
            q &= Q(office=self.office)

        return q
