import sform
from django.conf import settings
from django.core.exceptions import ValidationError

from staff.departments.models import DepartmentRoles
from staff.lib.models.roles_chain import has_roles_for_department

from staff.preprofile.forms.fields import (
    contacts_fields,
    helpdesk_fields,
    official_fields,
    personal_fields,
    technical_fields,
)
from staff.preprofile.forms.validation import (
    validate_hardware_profile_by_department,
    validate_login_with_candidate_type,
)
from staff.preprofile.models import CANDIDATE_TYPE, PREPROFILE_STATUS


class OutstaffForm(sform.SForm):
    _editable_statuses = [PREPROFILE_STATUS.NEW, PREPROFILE_STATUS.PREPARED]

    last_name = personal_fields.last_name()
    first_name = personal_fields.first_name()
    middle_name = personal_fields.middle_name(required=False)
    first_name_en = personal_fields.first_name_en()
    last_name_en = personal_fields.last_name_en()
    gender = personal_fields.gender()
    birthday = personal_fields.birthday(required=False)
    citizenship = personal_fields.citizenship()

    address = contacts_fields.address(required=False)
    email = contacts_fields.email(required=False)
    phone = contacts_fields.phone(required=True)

    login = official_fields.human_login()
    office = official_fields.office(default=settings.HOMIE_OFFICE_ID)
    join_at = official_fields.join_at()
    organization = official_fields.organization()
    department = official_fields.department(restrict_to_department_url='outstaff')
    abc_services = official_fields.abc_services(required=False)
    position_staff_text = official_fields.position_staff_text(required=False)
    candidate_type = official_fields.candidate_type(
        without=[CANDIDATE_TYPE.EXTERNAL_EMPLOYEE, CANDIDATE_TYPE.CURRENT_EMPLOYEE],
    )

    lang_ui = helpdesk_fields.lang_ui()
    need_vpn = helpdesk_fields.need_vpn()

    hardware_profile = helpdesk_fields.hardware_profile()
    hardware_profile_description = helpdesk_fields.hardware_profile_description(required=False)
    need_internal_phone = helpdesk_fields.need_internal_phone()
    need_sip_redirect = helpdesk_fields.need_sip_redirect()

    uid = technical_fields.uid(readonly=True)
    guid = technical_fields.guid(readonly=True)
    created_at = technical_fields.created_at(readonly=True)
    modified_at = technical_fields.modified_at(readonly=True)
    status = technical_fields.status(readonly=True)
    chief = technical_fields.chief(readonly=True)
    adopted_by = technical_fields.adopted_by(readonly=True)
    approved_by = technical_fields.approved_by(readonly=True)
    ext_form_link = technical_fields.ext_form_link(readonly=True)

    @property
    def action_context(self):
        return self.base_initial['action_context']

    @property
    def is_editing(self):
        return self.action_context.preprofile

    @property
    def requested_by(self):
        return self.action_context.requested_by

    def editing_verified_phone(self, name):
        return (
            name == 'phone'
            and self.is_editing
            and self.action_context.preprofile.is_eds_phone_verified
        )

    def get_field_state(self, name):
        preprofile = self.action_context.preprofile
        if preprofile and (preprofile.status not in self._editable_statuses):
            return sform.READONLY

        if name == 'login':
            if self.data and self.data.get('candidate_type') == CANDIDATE_TYPE.CURRENT_EMPLOYEE:
                return sform.REQUIRED
            return sform.NORMAL

        if self.editing_verified_phone(name):
            return sform.READONLY

        return super(OutstaffForm, self).get_field_state(name)

    def clean_department(self, value):
        roles = [DepartmentRoles.DEPUTY.value, DepartmentRoles.CHIEF.value]

        if not has_roles_for_department(value, self.requested_by, roles):
            raise ValidationError('Wrong department', code='invalid_choice')

        return value

    def clean_login(self, value):
        return value if value else None

    def clean(self):
        cleaned_data = self.cleaned_data

        required_fields = ['login', 'candidate_type']

        if any([
            not cleaned_data.get(field)
            for field in required_fields
        ]):
            return super(OutstaffForm, self).clean()

        login = cleaned_data['login']
        candidate_type = cleaned_data['candidate_type']

        preprofile = self.base_initial['action_context'].preprofile

        validate_login_with_candidate_type(login, candidate_type, preprofile_id=preprofile and preprofile.id or None)

        department_url = getattr(self.cleaned_data.get('department'), 'url', None) or self.initial.get('department')
        hardware_profile = self.cleaned_data.get('hardware_profile')
        validate_hardware_profile_by_department(
            profile=hardware_profile,
            department_url=department_url,
            form=self,
        )

        return super(OutstaffForm, self).clean()
