import sform
from staff.lib import waffle

from staff.departments.models import Department, HeadcountPosition
from staff.headcounts.permissions import Permissions
from staff.proposal.controllers.headcount import HeadcountDataCtl
from staff.proposal.forms.base import ProposalEntityActionForm, GridFieldWithMeta, ProposalBaseForm, actions_matcher
from staff.proposal.forms.fields import ValueStreamField, GeographyField


class HeadcountEditForm(ProposalEntityActionForm):
    headcount_code = sform.IntegerField(state=sform.REQUIRED)
    department = sform.SuggestField(
        queryset=Department.objects.filter(intranet_status=1),
        to_field_name='url',
        label_fields=('name', 'url'),
    )
    fake_department = sform.CharField(max_length=32)

    value_stream = ValueStreamField(
        queryset=Department.valuestreams.filter(intranet_status=1, hrproduct__intranet_status=1),
        to_field_name='url',
        label_fields=('name', 'url'),
    )

    geography = GeographyField(
        queryset=Department.geography.filter(intranet_status=1, geography_instance__oebs_code__isnull=False),
        to_field_name='url',
        label_fields=('name', 'url'),
    )

    force_recalculate_schemes = sform.BooleanField(default=False)

    def prepare_fields_state(self):
        if not waffle.switch_is_active('enable_proposal_geography'):
            self.fields.pop('geography')
        return super().prepare_fields_state()

    @staticmethod
    def clean_value_stream(value_stream):
        return value_stream and value_stream.url

    @staticmethod
    def clean_geography(geography):
        return geography and geography.url

    def clean_headcount_code(self, value):
        # В явном виде не проверяем право доступа при редактировании уже существующей заявки
        if self.initial.get('headcount__code') == value:
            return value

        observer = self.base_initial['author_user'].get_profile()

        error = sform.ValidationError(
            'headcount doesnt exist',
            code='invalid',
            params={},
        )

        permissions = Permissions(observer)
        allowed_deps = permissions.filter_by_observer(Department.all_types.all())
        hc_qs = HeadcountPosition.objects.filter(code=value)
        qs = hc_qs.filter(department_id__in=allowed_deps) | hc_qs.filter(valuestream_id__in=allowed_deps)

        if not qs.exists():
            raise error

        return value

    @staticmethod
    def clean_department(department):
        return department and department.url

    def clean_force_recalculate_schemes(self, value):
        return self._clean_hr_analyst_field('force_recalculate_schemes', value)


class HeadcountsGridFieldWithMeta(GridFieldWithMeta):
    def populate_with_meta(self, fields_list, base_initial):
        headcount_codes = [
            action['value']['headcount_code']['value']
            for action in fields_list['value']
        ]

        headcount_data_ctl = HeadcountDataCtl([code for code in headcount_codes if code], None)

        for field_dict in fields_list['value']:
            if field_dict['value']['headcount_code']['value']:
                field_dict['meta'] = headcount_data_ctl.as_meta(field_dict['value']['headcount_code']['value'])
            else:
                field_dict['meta'] = {}


class HeadcountsChangesProposalForm(ProposalBaseForm):
    actions = HeadcountsGridFieldWithMeta(
        sform.FieldsetField(HeadcountEditForm),
        values_matcher=actions_matcher,
    )
