import sform
from staff.lib import waffle

from staff.departments.models.vacancy import Vacancy

from staff.departments.models import Department
from staff.headcounts.permissions import Permissions

from staff.proposal.controllers.vacancy import VacancyDataCtl
from staff.proposal.forms.base import (
    ProposalBaseForm,
    ProposalEntityActionForm,
    GridFieldWithMeta,
    actions_matcher,
)
from staff.proposal.forms.fields import ValueStreamField, GeographyField


class VacancyEditForm(ProposalEntityActionForm):
    vacancy_id = 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_vacancy_id(self, value):
        # В явном виде не проверяем право доступа при редактировании уже существующей заявки
        if self.initial.get('vacancy_id') == value:
            return value

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

        # аналитики и волож имеют доступ ко всем вакансиям
        if Permissions(observer).has_special_role():
            return value

        if Vacancy.objects.filter(id=value, vacancymember__person=observer).exists():
            return value

        # Ругаемся что вакансии не существует, если кто-то без прав доступа к вакансии пытается
        # либо добавить ее к существующей заявке либо добавить к новой заявке
        raise sform.ValidationError(
            'vacancy doesnt exist',
            code='invalid',
            params={},
        )

    @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 VacancyGridFieldWithMeta(GridFieldWithMeta):

    def populate_with_meta(self, fields_list, base_initial):
        vacancy_ids = [
            action['value']['vacancy_id']['value']
            for action in fields_list['value']
        ]

        vacancy_data_ctl = VacancyDataCtl([v_id for v_id in vacancy_ids if v_id], None)

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


class VacancyChangesProposalForm(ProposalBaseForm):
    actions = VacancyGridFieldWithMeta(
        sform.FieldsetField(VacancyEditForm),
        values_matcher=actions_matcher,
    )
