import logging
from datetime import datetime

from django.contrib.auth import get_user_model

from ..validators import DateRangeValidator, PeriodRangeValidator, SubsetValidator
from .base import BaseRule

User = get_user_model()


logger = logging.getLogger(__name__)


class BaseStaffProfileRule(BaseRule):
    abstract = True

    def get_profile(self, user: User):
        return getattr(user, 'staffprofile', None)

    def get_profile_data(self, profile):
        raise NotImplementedError('get_profile_data() must be implemented.')

    def get_user_data(self, user: User):
        staff_profile = self.get_profile(user)
        if not staff_profile:
            return None

        return self.get_profile_data(staff_profile)


class StaffJoinedDateRule(BaseStaffProfileRule):
    label = 'staff_joined_date'
    validator_class = DateRangeValidator

    def get_profile_data(self, profile):
        return profile.joined_at.date() if profile.joined_at else None


class StaffWorkPeriodRule(StaffJoinedDateRule):
    label = 'staff_working_period'
    validator_class = PeriodRangeValidator


class StaffLeadershipDateRule(BaseStaffProfileRule):
    label = 'staff_leadership_date'
    validator_class = DateRangeValidator

    def check(self, user: User):
        profile = self.get_profile(user)
        if not profile:
            return False

        for dt in profile.leadership_joined_dates:
            if dt and isinstance(dt, datetime) and self.validator(dt.date()):
                return True

        return False


class StaffLeadershipPeriodRule(StaffLeadershipDateRule):
    label = 'staff_leadership_period'
    validator_class = PeriodRangeValidator


class StaffCityRule(BaseStaffProfileRule):
    label = 'staff_city'

    def get_profile_data(self, profile):
        return profile.city_id


class StaffOfficeRule(BaseStaffProfileRule):
    label = 'staff_office'

    def get_profile_data(self, profile):
        return profile.office_id


class StaffIsHeadRule(BaseStaffProfileRule):
    label = 'staff_is_head'

    def get_profile_data(self, profile):
        return profile.is_head


class StaffIsDeputyRule(BaseStaffProfileRule):
    label = 'staff_is_deputy'

    def get_profile_data(self, profile):
        return profile.is_deputy


class StaffGroupRule(BaseStaffProfileRule):
    label = 'staff_group'
    validator_class = SubsetValidator
    nested = False

    def get_validator_params(self, initial):
        args, kwargs = super().get_validator_params(initial)

        group_id = kwargs.pop('group_id', None)
        self.nested = kwargs.pop('nested', False)

        if group_id is None:
            group_id = args[0]

        return [int(group_id)], kwargs

    def get_profile_data(self, profile):
        if len(profile.groups_tree) == 0:
            return []

        if self.nested:
            return profile.groups_tree

        return [profile.groups_tree[-1]]
