import pytz
import sform
import yenv

from django import forms
from django.core.exceptions import ValidationError

from staff.lib.validators import validate_login, validate_department_url
from staff.map.models import Office
from staff.person.models import Staff, Organization
from staff.departments.models import Department, DepartmentRoles


class StaffChangeForm(forms.ModelForm):
    """Форма проверяющая данные для ручки меняющей стафа."""
    class Meta:
        model = Staff
        if yenv.type == 'production':
            fields = ('tz', 'lang_ui')
        else:
            fields = '__all__'

    tz = forms.ChoiceField(choices=((z, z) for z in pytz.common_timezones))

    EXTRA_FIELDS = 'nda_end_date', 'contract_end_date'
    nda_end_date = forms.DateField()
    contract_end_date = forms.DateField()

    def __init__(self, *args, **kwargs):
        super(StaffChangeForm, self).__init__(*args, **kwargs)
        for field in self.fields.values():
            field.required = False

    def clean(self):
        cd = self.cleaned_data

        if 'office' in cd and not cd['office']:
            del self.cleaned_data['office']

        cd = dict((k, v) for k, v in cd.items() if k in self.data)
        if not cd:
            raise forms.ValidationError('Nothing to update')
        return cd


class UrlHistoryForm(forms.Form):
    days = forms.IntegerField(min_value=1, max_value=30, required=False)


class HeadChangingForm(forms.Form):
    """Форма для валидации параметров ручки смены руководителя (Testing only)"""
    login = forms.CharField(required=False, validators=[validate_login])
    url = forms.CharField(required=True, validators=[validate_department_url])
    role = forms.ChoiceField(choices=DepartmentRoles.choices())

    def clean(self):
        cd = super(HeadChangingForm, self).clean()
        if cd.get('url'):
            cd['department'] = Department.objects.get(url=cd['url'])
        if cd.get('login'):
            cd['new_head'] = Staff.objects.get(login=cd['login'])

        self.cleaned_data = cd
        return self.cleaned_data


class CreatePersonInTestingForm(sform.SForm):
    id = sform.IntegerField(state=sform.REQUIRED)
    login = sform.CharField(max_length=50, state=sform.REQUIRED)
    uid = sform.CharField(max_length=16, state=sform.REQUIRED)
    guid = sform.CharField(max_length=47, state=sform.REQUIRED)
    first_name = sform.CharField(max_length=50, state=sform.REQUIRED)
    first_name_en = sform.CharField(max_length=50, state=sform.REQUIRED)
    middle_name = sform.CharField(max_length=50)
    hide_middle_name = sform.BooleanField(state=sform.REQUIRED)
    preferred_name = sform.CharField(max_length=50)
    preferred_name_en = sform.CharField(max_length=50)
    last_name = sform.CharField(max_length=100, state=sform.REQUIRED)
    last_name_en = sform.CharField(max_length=100, state=sform.REQUIRED)
    tz = sform.CharField(max_length=30, state=sform.REQUIRED)
    departments = sform.GridField(sform.CharField(max_length=255), state=sform.REQUIRED)
    gender = sform.CharField(max_length=1, state=sform.REQUIRED)
    office = sform.IntegerField(state=sform.REQUIRED)
    organization = sform.IntegerField(state=sform.REQUIRED)
    join_at = sform.DateField(state=sform.REQUIRED)
    position = sform.CharField(max_length=150)
    position_en = sform.CharField(max_length=150)
    work_email = sform.CharField(max_length=100, state=sform.REQUIRED)

    def clean_id(self, value):
        if Staff.objects.filter(id=value).exists():
            raise ValidationError(f'ID {value} already used', code='id_already_used')

        return value

    def clean_departments(self, value):
        if not value or not isinstance(value, list):
            raise ValidationError(f'invalid type', code='invalid_type')
        result = list(
            Department.objects
            .filter(url__in=value, intranet_status=1)
            .order_by('-level')
            .values_list('url', flat=True)
        )
        return result

    def clean_office(self, value):
        office = Office.objects.filter(id=value).first()
        return office or Office.objects.get(code='redrose')

    def clean_organization(self, value):
        org = Organization.objects.filter(id=value).first()
        return org or Organization.objects.get(id=41)  # Yandex.Technology
