from typing import List, AnyStr

from django.conf import settings

from staff.departments.models import Department
from staff.person.models import Staff
from staff.person_profile.controllers.subordinates import all_subordinates_q

from staff.gap.controllers.utils import is_chief_of
from staff.gap.workflows.choices import GAP_STATES as GS
from staff.gap.workflows import TRIP_WORKFLOWS


def _filter_subordinates(person_id, logins):
    return set(
        Staff.objects
        .filter(login__in=logins)
        .filter(all_subordinates_q(person_id))
        .values_list('login', flat=True)
    )


def can_manage_gaps(observer):
    return observer.has_perm('django_intranet_stuff.can_manage_gaps')


def divide_by_perms(observer, logins):
    observer_login = observer.get_profile().login

    if can_see_all_gaps(observer, logins):
        return logins[:], []

    can_see_all = _filter_subordinates(observer.get_profile().id, logins)
    if observer_login in logins:
        can_see_all.add(observer_login)

    return list(can_see_all), list(set(logins) - can_see_all)


def can_see_all_gaps(observer, logins):
    # STAFF-17109
    if settings.LOGIN_TIGRAN in logins and observer.get_profile().login != settings.LOGIN_TIGRAN:
        return False
    return (
        observer.is_superuser or
        (len(logins) == 1 and logins[0] == observer.get_profile().login) or
        can_manage_gaps(observer)
    )


def can_see_gap(gap, observer, person):
    if can_see_all_gaps(observer, [person['login']]):
        return True

    # STAFF-17109
    if person['login'] == settings.LOGIN_TIGRAN and observer.get_profile().login != settings.LOGIN_TIGRAN:
        return False

    return not (
        gap['workflow'] in TRIP_WORKFLOWS and
        gap['state'] != GS.CONFIRMED
    )


def can_see_issues(gap, observer, person_login, is_chief=None):
    observer_login = observer.get_profile().login
    can_see = person_login == observer_login or observer.is_superuser or can_manage_gaps(observer)

    # STAFF-17109
    if person_login == settings.LOGIN_TIGRAN and observer_login != settings.LOGIN_TIGRAN:
        return False

    if not can_see and gap['workflow'] in TRIP_WORKFLOWS:
        if is_chief is None:
            can_see = is_chief_of(observer_login, person_login)
        else:
            can_see = is_chief

    return can_see


def get_accessible_logins(observer: Staff, logins: List[AnyStr]) -> List[AnyStr]:
    if observer.is_internal():
        return logins
    res = []
    try:
        logins.remove(observer.login)
        if observer.user.has_perm('django_intranet_stuff.can_view_gap_as_external'):
            res.append(observer.login)
    except ValueError:
        pass
    if not logins:
        return res
    dep_q = observer.departments_by_outstaff_perm_query('django_intranet_stuff.can_view_gaps')
    res.extend(
        Staff.objects
        .filter(department__in=Department.objects.filter(dep_q), login__in=logins)
        .values_list('login', flat=True)
    )
    return res


def get_readable_accessible_logins(observer: Staff, logins: List[AnyStr]) -> List[AnyStr]:
    accessible_logins = get_accessible_logins(observer, logins)

    # STAFF-17109
    if settings.LOGIN_TIGRAN in logins and observer.login != settings.LOGIN_TIGRAN:
        accessible_logins.remove(settings.LOGIN_TIGRAN)

    return accessible_logins
