<template>
  <operation-dialog
    persistent
    sign
    ref="dialogOrganizationCreate"
    title="Создание организации"
    class="CreateModalForm"
    v-model="opened"
    @hide="close"
  >
    <div class="CreateModalForm__Content">
      <r-input
        class="CreateModalForm__Field"
        label="Полное наименование*"
        v-model="createdOrganization.fullname"
        validate-on-blur
        :rules="[(val) => !isEmptyVal(val) || 'Обязательное поле']"
      />
      <r-input
        class="CreateModalForm__Field"
        label="ОПФ"
        v-model="createdOrganization.leg"
      />
      <r-input
        class="CreateModalForm__Field"
        label="Сокращённое наименование*"
        v-model="createdOrganization.shortname"
        validate-on-blur
        :rules="[(val) => !isEmptyVal(val) || 'Обязательное поле']"
      />
      <r-input
        class="CreateModalForm__Field"
        label="Код военного комиссариата"
        v-model="createdOrganization.militaryCode"
        :rules="[
          (val) =>
            !val || val.match(/^[0-9]{8}$/) || 'Должен состоять из 8 цифр',
        ]"
      />
      <div class="CreateModalForm__Field">
        <span class="CreateModalForm__FieldLabel">Адрес организации</span>
        <BasicMAddressComponent
          :id.sync="createdOrganization.addressId"
          :value.sync="createdOrganization.address"
          filled
          dense
          options-dense
          dropdown-icon="pgs-shevron-down-off"
          :showManualEnter="false"
        />
      </div>
      <div class="CreateModalForm__Field">
        <span class="CreateModalForm__FieldLabel">
          Почтовый адрес организации
        </span>
        <BasicMAddressComponent
          :id.sync="createdOrganization.postalAddressId"
          :value.sync="createdOrganization.postalAddress"
          filled
          dense
          options-dense
          dropdown-icon="pgs-shevron-down-off"
          :showManualEnter="false"
        />
      </div>
      <r-select
        label="Субъект РФ*"
        :options="regionOptions"
        v-model="createdOrganization.region"
        emit-value
        map-options
        clearable
        :rules="[(val) => !!val || 'Обязательное поле']"
      />
      <r-input
        class="CreateModalForm__Field"
        label="Часовой пояс"
        v-model="createdOrganization.timezone"
        :rules="[
          (val) => !val || rulesTimezone(val) || 'Должен быть в формате +01:30',
        ]"
      />
      <!-- TODO: создать компонент q-select с инпутом -->
      <div class="CreateModalForm__Field">
        <span class="CreateModalForm__FieldLabel">Вышестоящая организация</span>
        <q-select
          v-model="parentOrganizationSelected"
          dense
          options-dense
          filled
          menu-anchor="bottom start"
          :options="optionsOrg"
          :loading="loadingOrg"
          dropdown-icon="pgs-shevron-down-off"
          option-label="shortname"
          option-value="id"
          use-input
          input-debounce="1000"
          @filter="filterOrg"
        />
      </div>
      <r-select
        class="CreateModalForm__Field"
        label="Тип организации"
        :options="orgTypes"
        v-model="createdOrganization.govOrganizationType"
        emit-value
        map-options
      />
      <div class="CreateModalForm__Field">
        <span class="CreateModalForm__FieldLabel">
          Дата гос. регистрации организации
        </span>
        <q-input dense filled v-model="govRegistrationDate" :mask="inputMask">
          <template v-slot:append>
            <q-icon name="event" class="CreateModalForm__FieldIcon">
              <q-popup-proxy
                ref="qDateProxy"
                transition-show="scale"
                transition-hide="scale"
              >
                <q-date v-model="govRegistrationDate" :mask="dateMask" />
              </q-popup-proxy>
            </q-icon>
          </template>
        </q-input>
      </div>
      <r-input
        class="CreateModalForm__Field"
        label="ИНН*"
        v-model="createdOrganization.inn"
        validate-on-blur
        :rules="[
          (val) => val.match(/^[0-9]{10}$/) || 'Должен состоять из 10 цифр',
        ]"
      />
      <r-input
        class="CreateModalForm__Field"
        label="ОГРН*"
        v-model="createdOrganization.ogrn"
        validate-on-blur
        :rules="[
          (val) => val.match(/^[0-9]{13}$/) || 'Должен состоять из 13 цифр',
        ]"
      />
      <r-input
        class="CreateModalForm__Field"
        label="КПП"
        v-model="createdOrganization.kpp"
        :rules="[
          (val) =>
            !val.length ||
            val.match(/^[0-9]{9}$/) ||
            'Должен состоять из 9 цифр',
        ]"
      />
      <r-input
        class="CreateModalForm__Field"
        label="ОКТМО"
        v-model="createdOrganization.oktmo"
      />
      <r-input
        class="CreateModalForm__Field"
        label="Адрес электронной почты"
        v-model="createdOrganization.email"
        type="email"
      >
        <template v-slot:icon>
          <q-icon name="email" />
        </template>
      </r-input>
      <div class="CreateModalForm__Field">
        <span class="CreateModalForm__FieldLabel">Телефон</span>
        <q-input
          fill-mask
          filled
          dense
          mask="+7 (###) ###-##-##"
          unmasked-value
          v-model="createdOrganization.phone"
        >
          <template v-slot:prepend>
            <q-icon name="phone" />
          </template>
        </q-input>
      </div>
      <div class="CreateModalForm__TogglesBlock">
        <q-toggle
          v-model="createdOrganization.reportsEnabled"
          :label="
            createdOrganization.reportsEnabled
              ? 'Включать в отчеты'
              : 'Исключать из отчетов'
          "
        />
        <q-toggle
          v-model="createdOrganization.enabled"
          :label="
            createdOrganization.enabled ? 'Заблокировать' : 'Разблокировать'
          "
          :true-value="false"
          :false-value="true"
        />
      </div>
    </div>
    <template #process>
      <result-block
        header="Создание организации"
        icon="pgs-document"
        type="info"
      />
    </template>
    <template #result>
      <result-block :header="resultMessage" :type="resultType" />
    </template>
    <template #left-actions-panel>
      <r-btn
        outline
        :label="isFinishStep ? 'Закрыть' : 'Отмена'"
        icon="pgs-close"
        color="primary"
        @click="close"
      />
    </template>
    <template #right-actions-panel>
      <r-btn
        v-if="!isFinishStep"
        outline
        label="Подтверждение"
        icon="pgs-save"
        positive
        :disable="!validateForm"
        @click="submit"
      />
    </template>
  </operation-dialog>
</template>

<script lang="ts">
import {
  Component,
  Prop,
  Mixins,
  Watch,
  Ref,
  Vue,
} from 'vue-property-decorator';
import get from 'lodash/get';
import isPlainObject from 'lodash/isPlainObject';
import ProcessStarter from '@/mixins/ProcessStarter';
import OperationDialog from '@/components/common/operation-dialog/index.vue';
import { RegionApi, OrganizationApi, Organization } from '@openapi/idm';
import { oidcClientComputed } from '@state/modules/oidc-client';
import { DateFormat } from '@constants/utils/format-date';
import { convertDateFormat } from '@utils/format-date';
import RInput from '@/recruits/components/common/r-input/index.vue';
import RSelect from '@/recruits/components/common/r-select.vue';
import BasicMAddressComponent from '@components/m-address/index.vue';
import { v4 } from 'uuid';
import isString from 'lodash/isString';

const regionApi = new RegionApi();
const organizationApi = new OrganizationApi();

const oidcClientMixin = Vue.extend({
  computed: {
    ...oidcClientComputed,
  },
});

@Component({
  components: {
    RInput,
    RSelect,
    BasicMAddressComponent,
  },
})
export default class CreateOrganizationModal extends Mixins(
  ProcessStarter,
  oidcClientMixin
) {
  @Prop({ default: false }) showModal: boolean;
  @Prop({ default: 'milBaseCreateOrganisationIDMProcess' })
  declare processKey: string;

  @Ref('dialogOrganizationCreate') operationDialog: OperationDialog;

  opened = false;
  isFinishStep = false;

  resultType: 'positive' | 'negative' | '' = '';
  resultMessage = '';

  createdOrganization: Organization = {
    certificate: '',
    aliasKey: '',
    passKey: '',
    enabled: true,
    id: '',
    email: '',
    fullname: '',
    inn: '',
    kpp: '',
    ogrn: '',
    oktmo: '',
    govOrganizationType: '',
    phone: '',
    reportsEnabled: true,
    shortname: '',
    militaryCode: '',
    timezone: '',
    addressId: '',
    address: '',
    postalAddressId: '',
    postalAddress: '',
    dns: '',
    name: '',
    leg: '',
    region: '',
    tnsDepartmentId: '',
  };

  orgTypes: Array<{ label: string; value: string }> = [];
  regionOptions: Array<{ label: string; value: string }> = [];

  optionsOrg: Organization[] = [];
  loadingOrg = false;
  parentOrganizationSelected: Organization | null = null;
  govRegistrationDate = '';

  @Watch('showModal')
  private async showModalHandler(): Promise<void> {
    this.opened = false;
    this.isFinishStep = false;
    this.clearForm();
    this.operationDialog.reset();
    if (!this.showModal) return;
    this.opened = true;

    // get default options
    await this.getRegions();
    await this.getOrgTypes();
    await this.getOrganizations();
  }

  clearForm(): void {
    this.resultType = '';
    this.orgTypes = [];
    this.regionOptions = [];
    this.optionsOrg = [];
    this.loadingOrg = false;
    this.parentOrganizationSelected = null;
    this.govRegistrationDate = '';

    this.createdOrganization.certificate = '';
    this.createdOrganization.aliasKey = '';
    this.createdOrganization.passKey = '';
    this.createdOrganization.enabled = true;
    this.createdOrganization.id = v4();
    this.createdOrganization.email = '';
    this.createdOrganization.fullname = '';
    this.createdOrganization.inn = '';
    this.createdOrganization.kpp = '';
    this.createdOrganization.ogrn = '';
    this.createdOrganization.oktmo = '';
    this.createdOrganization.govOrganizationType = '';
    this.createdOrganization.phone = '';
    this.createdOrganization.reportsEnabled = true;
    this.createdOrganization.shortname = '';
    this.createdOrganization.militaryCode = '';
    this.createdOrganization.timezone = '';
    this.createdOrganization.addressId = '';
    this.createdOrganization.address = '';
    this.createdOrganization.postalAddressId = '';
    this.createdOrganization.postalAddress = '';
    this.createdOrganization.dns = '';
    this.createdOrganization.name = '';
    this.createdOrganization.leg = '';
    this.createdOrganization.region = '';
    this.createdOrganization.tnsDepartmentId = '';
  }

  async getOrgTypes(): Promise<void> {
    await this.$store
      .dispatch('registryService/referenceBooks/fetchReferenceBook', {
        id: 'rosregister_declarant_kind',
        limit: 200,
      })
      .then((dict) => {
        if (isPlainObject(dict)) {
          // eslint-disable-next-line array-callback-return
          Object.entries(dict).map(([key, value]) => {
            this.orgTypes.push({
              value: key,
              label: get(value, 'value', ''),
            });
          });
        }
      });
  }

  async getRegions(): Promise<void> {
    await regionApi
      .searchRegions()
      .then(({ data }) => {
        if (Array.isArray(data) && data.length > 0) {
          this.regionOptions = data.map((regionObject) => {
            return {
              value: get(regionObject, 'id'),
              label: get(regionObject, 'fullname') || get(regionObject, 'name'),
            };
          });
        }
      })
      .catch(() => {
        throw new Error(
          '[components][forms][OrganizationsFormsBasic][searchRegions]'
        );
      });
  }

  async getOrganizations(findOrgString?: string): Promise<void> {
    if (!this.loadingOrg) {
      this.loadingOrg = true;
      const query = findOrgString
        ? `fullname=like='%${findOrgString}%' or name=like='%${findOrgString}%'`
        : '';
      await organizationApi
        .searchOrganizations(undefined, query)
        .then((response) => {
          this.optionsOrg = response.data || [];
        })
        .finally(() => {
          this.loadingOrg = false;
        });
    }
  }

  /**
   * Функция фильтрации в поле выбора ролей
   * @param {string} val
   * @param {function} update
   */
  async filterOrg(val: string, update: () => void): Promise<void> {
    if (val.length > 1 || val === '') {
      await this.getOrganizations(val);
      update();
    }
  }

  get regionLabel(): string {
    let label = '';

    if (
      this.createdOrganization.region &&
      Array.isArray(this.regionOptions) &&
      this.regionOptions.length > 0
    ) {
      const regionObject = this.regionOptions.find(
        (item) => item.value === this.createdOrganization.region
      );

      label = get(regionObject, 'label', '');
    }

    return label || 'Не выбрано';
  }

  rulesTimezone(timezone: string): string | boolean {
    const regex = /^[+|-]((0[0-9]|1[0-1]):([0-5][0-9])|12:00)$/;
    const regexMinusZero = /^-00:00$/;
    return regex.test(timezone) && !regexMinusZero.test(timezone);
  }

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

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

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

  removeSpaces(val: string): string {
    return val.trim().replace(/ {1,}/g, ' ');
  }

  get validateForm(): boolean {
    return (
      !this.isEmptyVal(this.createdOrganization.fullname) &&
      !this.isEmptyVal(this.createdOrganization.shortname) &&
      (!this.createdOrganization.militaryCode?.length ||
        !!this.createdOrganization.militaryCode.match(/^[0-9]{8}$/)) &&
      !!this.createdOrganization.region &&
      (!this.createdOrganization.timezone?.length ||
        !!this.rulesTimezone(this.createdOrganization.timezone)) &&
      !!this.createdOrganization.inn.match(/^[0-9]{10}$/) &&
      !!this.createdOrganization.ogrn.match(/^[0-9]{13}$/) &&
      (!this.createdOrganization.kpp?.length ||
        !!this.createdOrganization.kpp.match(/^[0-9]{9}$/))
    );
  }

  close(): void {
    if (this.isFinishStep) {
      this.$emit('finish');
    } else {
      this.$emit('close');
    }
  }

  async submit(): Promise<void> {
    if (!this.validateForm) {
      return;
    }
    this.operationDialog.toProcess();
    const dataObject: {
      organization: Organization & { parent: string };
      transSertDelete: boolean;
      transExit: boolean;
      parentLabel: string;
      regionLabel: string;
    } = {
      organization: {
        certificate: this.createdOrganization.certificate,
        aliasKey: this.createdOrganization.aliasKey,
        passKey: this.createdOrganization.passKey,
        enabled: this.createdOrganization.enabled,
        id: this.createdOrganization.id,
        email: this.createdOrganization.email,
        fullname: this.removeSpaces(this.createdOrganization.fullname),
        inn: this.createdOrganization.inn,
        kpp: this.createdOrganization.kpp,
        ogrn: this.createdOrganization.ogrn,
        oktmo: this.createdOrganization.oktmo,
        govOrganizationType: this.createdOrganization.govOrganizationType,
        phone: this.createdOrganization.phone,
        reportsEnabled: this.createdOrganization.reportsEnabled,
        shortname: this.removeSpaces(this.createdOrganization.shortname),
        militaryCode: this.createdOrganization.militaryCode || 'emptyValue',
        timezone: this.createdOrganization.timezone,
        addressId: this.createdOrganization.addressId,
        address: this.createdOrganization.address,
        postalAddressId: this.createdOrganization.postalAddressId,
        postalAddress: this.createdOrganization.postalAddress,
        dns: this.createdOrganization.dns,
        name: this.createdOrganization.dns,
        leg: this.createdOrganization.leg,
        parent:
          this.parentOrganizationSelected?.id ||
          this.createdOrganization.region ||
          '',
        region: this.createdOrganization.region || '',
        tnsDepartmentId: this.createdOrganization.tnsDepartmentId,
      },
      transSertDelete: false,
      transExit: false,
      parentLabel: this.parentOrganizationSelected?.shortname || 'Не выбрано',
      regionLabel: this.regionLabel,
    };

    if (this.govRegistrationDate) {
      dataObject.organization.govRegistrationDate = convertDateFormat(
        this.govRegistrationDate,
        this.dateMask,
        DateFormat.dashedDate
      );
    }

    try {
      const traceId = await this.startProcess({
        ...dataObject,
      });

      this.isFinishStep = true;

      this.registerListener((message, removeListener) => {
        if (traceId !== message.traceId) return;
        if (message?.body?.type === 'finish') {
          this.resultType = 'positive';
          this.resultMessage = 'Организация создана';
          removeListener();
          this.$emit('refresh');
        }

        if (message?.body?.type === 'error') {
          this.resultType = 'negative';
          // get т.к. message может быть Task | PushMessage, а в Task нет поля msg
          this.resultMessage = get(
            message,
            'body.msg.message',
            'Произошла непредвиденная ошибка'
          );
          removeListener();
        }
      });
    } catch (error: any) {
      this.resultType = 'negative';
      this.$q.notify({
        message: error.message,
        color: 'negative',
      });
    } finally {
      this.operationDialog.toResult();
    }
  }
}
</script>

<style lang="scss" scoped>
.CreateModalForm {
  &__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;
  }

  &__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);
        padding: 0 8px;
      }

      .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;
  }

  &__TogglesBlock {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
  }
}
</style>
