<template>
  <div class="AccountBaseForm">
    <r-input
      class="AccountBaseForm__Field"
      label="Фамилия*"
      v-model="editPersonData.surname"
      validate-on-blur
      :rules="[rules.rusStringDashSpace, rules.required]"
    />
    <r-input
      class="AccountBaseForm__Field"
      label="Имя*"
      v-model="editPersonData.firstname"
      validate-on-blur
      :rules="[rules.rusStringDashSpace, rules.required]"
    />
    <r-input
      class="AccountBaseForm__Field"
      label="Отчество"
      v-model="editPersonData.middlename"
      :rules="[rules.rusStringDashSpace]"
    />
    <r-select
      class="AccountBaseForm__Field"
      label="Пол"
      :options="['Мужской', 'Женский']"
      v-model="editPersonData.sex"
      emit-value
      map-options
    />

    <div class="AccountBaseForm__Field">
      <span class="AccountBaseForm__FieldLabel">Дата рождения</span>
      <q-input v-model="birthdate" filled dense :mask="inputMask">
        <template #append>
          <q-icon name="event" class="AccountBaseForm__FieldIcon">
            <q-popup-proxy
              ref="qDateProxy"
              transition-show="scale"
              transition-hide="scale"
            >
              <q-date v-model="birthdate" :mask="dateMask" />
            </q-popup-proxy>
          </q-icon>
        </template>
      </q-input>
    </div>

    <div class="AccountBaseForm__Field">
      <span class="AccountBaseForm__FieldLabel" :class="snilsErrorClass">
        СНИЛС*
      </span>
      <q-input
        v-model="editPersonData.snils"
        mask="###-###-### ##"
        unmasked-value
        dense
        filled
        :rules="snilsRules"
        :error="haveDuplicateSnils"
        :error-message="
          haveDuplicateSnils ? 'Сотрудник с таким СНИЛС уже есть в системе' : ''
        "
        :loading="isCheckingDuplicateSnils"
        required
      />
    </div>

    <r-input
      class="AccountBaseForm__Field"
      label="Адрес электронной почты"
      v-model="editPersonData.email"
      type="email"
      :rules="emailRules"
    >
      <template v-slot:icon>
        <q-icon name="email" />
      </template>
    </r-input>

    <r-input
      v-if="canChangeIpAddress"
      class="AccountBaseForm__Field"
      label="IP-адрес"
      v-model="ipAddress"
      :rules="[(val) => validIpAddressRule(val) || 'Некорректный IP-адрес']"
    >
      <template v-slot:icon>
        <q-icon name="laptop" />
      </template>
    </r-input>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import RInput from '@/recruits/components/common/r-input/index.vue';
import RSelect from '@/recruits/components/common/r-select.vue';
import { validEmailRuleBoolean } from '@utils/field-validation/basic';
import { snilsFormatRuleBoolean } from '@utils/field-validation/employees';
import {
  convertDateFormat,
  convertDateFromBackendFormat,
  convertDateToBackendFormat,
} from '@utils/format-date';
import { PersonData } from '@/recruits/components/accounts/utils/types';
import isString from 'lodash/isString';
import { PersonApi } from '@/openapi/idm';
import {
  VALIDATION_CHECKS,
  VALIDATION_RULES,
} from '@/recruits/utils/validation-rules';

const personApi = new PersonApi();

@Component({
  components: {
    RInput,
    RSelect,
  },
  methods: {
    snilsFormatRuleBoolean,
    validEmailRuleBoolean,
  },
})
export default class AccountBaseForm extends Vue {
  @Prop({ default: null }) personData: PersonData | null;
  @Prop({ default: false }) canChangeIpAddress: boolean;
  @Prop({}) submitFunction: (personData: PersonData) => void;
  @Prop({ default: 0 }) triggerSubmit: number;

  public rules = VALIDATION_RULES;

  editPersonData: PersonData = {
    id: '',
    surname: '',
    firstname: '',
    middlename: '',
    sex: '',
    email: '',
    birthdate: '',
    snils: '',
    ipAddresses: [],
  };

  birthdate = '';
  ipAddress = '';

  haveDuplicateSnils = false;
  isCheckingDuplicateSnils = false;

  @Watch('personData', { immediate: true, deep: true })
  private personDataHandler(): void {
    if (this.personData) {
      this.editPersonData.surname = this.personData.surname || '';
      this.editPersonData.firstname = this.personData.firstname || '';
      this.editPersonData.middlename = this.personData.middlename || '';
      this.editPersonData.sex = this.personData.sex || '';
      this.editPersonData.email = this.personData.email || '';
      this.editPersonData.birthdate = this.personData.birthdate || '';
      this.editPersonData.snils = this.personData.snils || '';
      this.editPersonData.ipAddresses = this.personData.ipAddresses || [];
      this.editPersonData.id = this.personData.id || '';
      if (this.editPersonData.birthdate) {
        this.birthdate = convertDateFromBackendFormat(
          this.editPersonData.birthdate,
          this.dateMask
        );
      }

      if (this.editPersonData.ipAddresses?.length) {
        this.ipAddress = this.editPersonData.ipAddresses[0];
      }
    } else {
      this.editPersonData.id = '';
      this.editPersonData.surname = '';
      this.editPersonData.firstname = '';
      this.editPersonData.middlename = '';
      this.editPersonData.sex = '';
      this.editPersonData.email = '';
      this.editPersonData.birthdate = '';
      this.editPersonData.snils = '';
      this.editPersonData.ipAddresses = [];
      this.birthdate = '';
      this.ipAddress = '';
    }
  }

  get dateMask(): string {
    return this.$store.getters['i18N/localeMask'].date;
  }

  get inputMask(): string {
    return this.$store.getters['i18N/localeMask'].input;
  }

  get snilsErrorClass(): string {
    return this.editPersonData.snils &&
      (!snilsFormatRuleBoolean(this.editPersonData.snils) ||
        this.haveDuplicateSnils)
      ? 'AccountBaseForm__FieldLabel_Error'
      : '';
  }

  snilsRules = [
    (val: string): boolean | string => !!val.length || 'Обязательное поле',
    (val: string): boolean | string =>
      snilsFormatRuleBoolean(val) || 'Неверный формат СНИЛС',
  ];

  @Watch('editPersonData.snils')
  private async snilsHandler(): Promise<void> {
    if (
      this.editPersonData.snils === this.personData?.snils ||
      !snilsFormatRuleBoolean(this.editPersonData.snils)
    ) {
      this.haveDuplicateSnils = false;
    } else {
      this.isCheckingDuplicateSnils = true;
      const personResponse = await personApi
        .pagingPersons(undefined, 1, `snils=="${this.editPersonData.snils}"`)
        .then(({ data }) => data);
      this.haveDuplicateSnils = !!personResponse.foundRows;
      this.isCheckingDuplicateSnils = false;
    }
  }

  emailRules = [
    (val: string): boolean | string =>
      val.length ? validEmailRuleBoolean(val) || 'Некорректный email' : true,
  ];

  @Watch('dateMask')
  private dateMaskHandler(currentValue: string, oldValue: string): void {
    if (this.birthdate) {
      this.birthdate = convertDateFormat(
        this.birthdate,
        oldValue,
        currentValue
      );
    }
  }

  @Watch('ipAddress')
  private ipAddressHandler(newValue: string, oldValue: string): void {
    const splitDotValue = newValue.split('.');
    if (
      // проверка что предущее действие не было удаление
      newValue !== oldValue.slice(0, -1) &&
      // проверка что уже нет разбития на 4 блока IP-адреса
      splitDotValue.length < 4 &&
      // проверка что введено 3 символа
      splitDotValue[splitDotValue.length - 1].length === 3
    ) {
      this.ipAddress += '.';
    }
  }

  validIpAddressRule(val: string): boolean {
    const pattern = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
    const result = val.match(pattern);
    const haveError = val && (!result || result[0].length !== val.length);
    return !haveError;
  }

  isEmptyVal(val: string | null): boolean {
    return isString(val) ? !val.trim().length : true;
  }

  get validateForm(): boolean {
    return (
      !!this.editPersonData.surname.length &&
      VALIDATION_CHECKS.rusStringDashSpace(this.editPersonData.surname) &&
      !!this.editPersonData.firstname.length &&
      VALIDATION_CHECKS.rusStringDashSpace(this.editPersonData.firstname) &&
      (!this.editPersonData.middlename?.length ||
        VALIDATION_CHECKS.rusStringDashSpace(this.editPersonData.middlename)) &&
      (!this.ipAddress?.length || !!this.validIpAddressRule(this.ipAddress)) &&
      !!this.editPersonData.snils &&
      !!snilsFormatRuleBoolean(this.editPersonData.snils) &&
      !this.haveDuplicateSnils &&
      !this.isCheckingDuplicateSnils &&
      (!this.editPersonData.email?.length ||
        !!validEmailRuleBoolean(this.editPersonData.email))
    );
  }

  @Watch('validateForm', { immediate: true })
  private validateFormHandler(val: boolean): void {
    this.$emit('validateForm', val);
  }

  @Watch('triggerSubmit')
  private triggerSubmitHandler(): void {
    let birthdate = '';
    if (this.birthdate) {
      birthdate = convertDateToBackendFormat(this.birthdate, this.dateMask);
    }
    this.submitFunction({
      ...this.editPersonData,
      surname: this.editPersonData.surname.trim(),
      firstname: this.editPersonData.firstname.trim(),
      ipAddresses: this.ipAddress ? [this.ipAddress] : [],
      birthdate,
    });
  }
}
</script>

<style lang="scss" scoped>
.AccountBaseForm {
  &__FieldLabel {
    font-family: 'Golos Text', sans-serif;
    font-style: normal;
    display: inline-block;
    cursor: pointer;
    font-size: 12px;
    line-height: 16px;
    margin-bottom: 4px;
    font-weight: 600;
    color: rgba(2, 12, 18, 0.58);
    transition: 0.3s;

    &_Error {
      color: #c10525;
    }
  }

  &__Field {
    margin-bottom: 15px;
    &::v-deep {
      .q-field--with-bottom {
        padding-bottom: 0;
      }

      .q-field--auto-height .q-field__control {
        background: #e5edf5;
        border-bottom: 1px solid rgba(1, 72, 116, 0.18);
      }

      .q-field--filled.q-field--highlighted .q-field__control:before {
        opacity: 0;
      }

      .q-field--filled .q-field__control:after {
        height: 0;
      }

      .q-field--focused {
        &.q-field--filled .q-field__control {
          background: white;
          border: 1px solid #0148742e;
        }
      }

      .q-field--filled .q-field__control {
        background: #e5edf5;
        // border-bottom: 1px solid rgba(1, 72, 116, 0.18);
      }
    }
  }

  &__FieldIcon {
    cursor: pointer;
  }
}
</style>
