<i18n>
{
  "en": {
    "PaymentsRequestDialogvue": {
      "requestPayments": "request payments",
      "title": "Charges request",
      "type": "type",
      "requestBy": "request by"
    }
  },
  "ru": {
    "PaymentsRequestDialogvue": {
      "requestPayments": "Запросить платежи",
      "title": "Запрос платежей",
      "type": "Выберите тип запроса *",
      "requestBy": "Запросить по *"
    }
  }
}
</i18n>

<template>
  <div>
    <q-btn
      outline
      class="q-ml-lg"
      color="primary"
      :label="$t('PaymentsRequestDialogvue.requestPayments')"
      @click="openDialogWindow()"
    />
    <q-dialog v-model="dialog" @hide="clearModel" persistent>
      <q-card class="no-shadow" style="max-width: 80vw; width: 700px;">
        <q-form ref="paymentRequestForm" greedy @submit="handler">
          <q-card-section>
            <div class="text-h6">
              {{ $t('PaymentsRequestDialogvue.title') }}
            </div>
          </q-card-section>
          <q-card-section class="q-p row justify-center">
            <div class="col-11 q-gutter-sm">
              <q-select
                v-model="model.type"
                :options="typeOptions"
                :label="$t('PaymentsRequestDialogvue.type')"
                ref="inputType"
                class="q-mb-sm"
                dense
                filled
                :rules="[rulesRequired]"
                hide-bottom-space
                options-dense
                option-value="id"
                option-label="label"
              />
              <q-select
                v-model="model.requestBy"
                :options="requestByOptions"
                :label="$t('PaymentsRequestDialogvue.requestBy')"
                :disable="!model.type"
                class="q-mb-sm"
                dense
                filled
                :rules="[rulesRequired]"
                hide-bottom-space
                options-dense
                option-value="id"
                option-label="label"
              />
              <template v-if="model.requestBy.id === '1'">
                <div class="flex items-center">
                  <q-select
                    v-if="!customUIN"
                    v-model="model.UIN"
                    :options="uinOptions"
                    class="q-mb-sm width60"
                    dense
                    filled
                    :rules="[rulesRequired]"
                    hide-bottom-space
                    :label="'Выберите УИН *'"
                  />
                  <q-input
                    v-else
                    v-model="model.UIN"
                    class="q-mb-sm width60"
                    dense
                    filled
                    :rules="[rulesRequired]"
                    hide-bottom-space
                    mask="##############################"
                    :label="'Введите УИН *'"
                  ></q-input>
                  <q-checkbox v-model="customUIN" class="q-ml-md q-mb-sm" label="Ввести УИН вручную" />
                </div>
                <div class="flex items-center q-mt-none">
                  <span class="q-mr-md">Выберите период</span>
                  <XDateRange
                    :from.sync="model.range.from"
                    :to.sync="model.range.to"
                  />
                </div>
                <q-checkbox v-model="model.isSBP" label="Платеж через СБП" />
              </template>
              <template v-if="model.requestBy.id === '2'">
                <q-input
                  v-model="model.UIP"
                  class="q-mb-sm"
                  dense
                  mask="################################"
                  filled
                  :rules="[rulesRequired, exactNumberOfCharsRule(32)]"
                  hide-bottom-space
                  :label="'Введите УИП *'"
                ></q-input>
              </template>
              <template v-if="model.requestBy.id === '3'">
                <q-select
                  v-model="model.payerType"
                  :options="payerTypeOptions"
                  class="q-mb-sm"
                  dense
                  filled
                  :rules="[rulesRequired]"
                  :label="'Тип плательщика *'"
                  hide-bottom-space
                  options-dense
                  option-value="code"
                  option-label="value"
                />
                <template v-if="model.payerType.code">
                  <template v-if="model.payerType.code === '1'">
                    <q-select
                      v-model="model.DUL"
                      :options="dulOptions"
                      ref="inputType"
                      class="q-mb-sm"
                      dense
                      filled
                      :rules="[rulesRequired]"
                      hide-bottom-space
                      options-dense
                      option-value="code"
                      option-label="value"
                      :label="'Вид документа, удостоверяющего личность *'"
                    />
                    <q-input
                      v-model="model.documentNumber"
                      class="q-mb-sm"
                      dense
                      filled
                      :rules="[rulesRequired]"
                      hide-bottom-space
                      :label="'Номер документа *'"
                    />
                  </template>
                  <template v-else>
                    <q-input
                      v-model="model.organisationName"
                      class="q-mb-sm"
                      dense
                      filled
                      label="Наименование организации"
                    />
                    <div 
                      class="flex row items-center" 
                      :class="model.payerType.code === '2' && 'justify-between'"
                    >
                      <q-input
                        v-if="isKio"
                        v-model="model.payerKIO"
                        class="q-mb-sm width49"
                        dense
                        filled
                        :rules="[rulesRequired, exactNumberOfCharsRule(5)]"
                        hide-bottom-space
                        :label="'КИО *'"
                      />
                      <template v-else>
                        <q-input
                          v-if="model.payerType.code == '4'"
                          v-model="model.payerINN"
                          class="q-mb-sm width49"
                          dense
                          filled
                          :rules="[rulesRequired, exactNumberOfCharsRule(12)]"
                          hide-bottom-space
                          mask="############"
                          :label="'ИНН *'"
                        />
                        <q-input
                          v-if="model.payerType.code !== '4'"
                          v-model="model.payerINN"
                          class="q-mb-sm width49"
                          dense
                          filled
                          :rules="[rulesRequired, exactNumberOfCharsRule(10)]"
                          hide-bottom-space
                          mask="##########"
                          :label="'ИНН *'"
                        />
                      </template>
                      <q-checkbox 
                        v-model="isKio" 
                        v-if="model.payerType.code === '3'" 
                        class="q-ml-md q-mb-sm" 
                        :label="'Ввести КИО'" 
                      />
                      <q-input
                        v-show="model.payerType.code !== '4'"
                        v-model="model.payerKPP"
                        class="q-mb-sm width49"
                        dense
                        filled
                        :rules="[rulesRequired, exactNumberOfCharsRule(9)]"
                        lazy-rules 
                        hide-bottom-space
                        mask="#########"
                        :label="'КПП *'"
                      />
                    </div>
                  </template>
                  <div class="flex items-center q-mt-none">
                    <span class="q-mr-md">Выберите период</span>
                    <XDateRange
                      :from.sync="model.range.from"
                      :to.sync="model.range.to"
                    />
                  </div>
                  <KbkInput :options="kbkOptions" @kbkValue="setKbkValue" />
                </template>
              </template>
              <template v-if="model.requestBy.id === '4'">
                <div class="flex items-top q-mt-none">
                  <span class="q-mr-md q-mt-md">Выберите период *</span>
                  <XDateRange
                    :from.sync="model.range.from"
                    :to.sync="model.range.to"
                    :rules="[rulesRequired]"
                    minimal
                    required
                    focus
                    hideBottomSpace="false"
                  />
                </div>
                <KbkInput :options="kbkOptions" @kbkValue="setKbkValue" />
              </template>
            </div>
          </q-card-section>
          <q-card-section
            v-if="
              (model.requestBy.id === '3' && model.payerType.code) ||
              model.requestBy.id === '4'
            "
          >
            <q-separator />
            <q-expansion-item
              label="Идентификация получателя средств"
              header-class="text-primary"
            >
              <q-card>
                <q-card-section>
                  <div class="flex row justify-between items-start">
                    <q-input
                      v-model="model.beneficiaryINN"
                      class="q-mb-sm width49"
                      dense
                      filled
                      disable 
                      readonly
                      hide-bottom-space
                      mask="############"
                      label="ИНН"
                    />
                    <q-input
                      v-model="model.beneficiaryKPP"
                      class="q-mb-sm width49"
                      dense
                      filled
                      disable 
                      readonly
                      hide-bottom-space
                      mask="#########"
                      label="КПП"
                    />
                  </div>
                </q-card-section>
              </q-card>
            </q-expansion-item>
          </q-card-section>
          <q-card-actions class="q-pa-md" align="right">
            <q-btn
              :disable="false"
              :label="'Отмена'"
              outline
              unelevated
              color="primary"
              @click="closeDialogWindow"
            />
            <q-btn
              type="submit"
              :disable="false"
              :label="'Запросить'"
              unelevated
              color="primary"
            />
          </q-card-actions>
        </q-form>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
import XDateRange from '@components/reports/components/x-datetime-range.vue';
import KbkInput from './components/payments/KbkInput.vue';

import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import {
  convertDateFormatWithoutLocale,
  DateFormat,
} from '@/utils/format-date';
import { notifyError, notifyInfo } from '@/utils/notify';
import { BaseCardCommon } from '@/interfaces';
import { cloneDeep, get, isEmpty } from 'lodash';
import { Dictionary, DictionaryDocument } from '@openapi/registry-service';
import { CardNeedToUpdateType } from '@constants/models/Card';
import { Organization } from '@openapi/idm';
import { Payment } from '@openapi/mz-payment-service';

@Component({
  components: {
    XDateRange,
    KbkInput,
  },
})
export default class PaymentsRequestDialogvue extends Vue {
  @Prop() common?: BaseCardCommon;
  @Prop() statementModel?: any;
  @Prop() dictionaries: Dictionary[];

  private dialog = false;
  private loading = false;
  private customUIN = false;
  private isKio = false;

  private payerTypeOptions: any = [];
  private dulOptions: any = [];
  private kbkOptions: string[] = [];
  private uinOptions: string[] = [];
  private typeOptions = [
    { label: 'Все активные (неаннулированные) платежи', value: 'PAYMENT' },
    { label: 'Все платежи, имеющие статус уточнения', value: 'PAYMENTMODIFIED' },
  ];

  private requestByOptions = [
    { label: 'По УИН', id: '1' },
    { label: 'По УИП', id: '2' },
    { label: 'По идентификатору плательщика', id: '3' },
    { label: 'За временной интервал', id: '4' },
  ];

  private model: RequestModel = {
    type: this.typeOptions && this.typeOptions[0] || '',
    requestBy: '',
    UIN: '',
    UIP: '',
    payerType: '',
    DUL: '',
    documentNumber: '',
    organisationName: '',
    payerINN: '',
    payerKPP: '',
    payerKIO: '',
    beneficiaryINN: '',
    beneficiaryKPP: '',
    beneficiaryKBK: [],
    isSBP: false,
    range: {
      from: '',
      to: '',
    }
  };

  @Watch('customUIN')
  clearValueUIN(val: boolean): void {
    if (!val) this.model.UIN = '';
  }

  @Watch('isKio')
  clearKioInn(val: boolean): void {
    if (val) {
      this.model.payerINN = '';
    } else {
      this.model.payerKIO = '';
      this.model.payerINN = '';
    }
  }

  @Watch('statementModel')
  statementModelChanged(): void {
    this.preFillForm();
  }

  rulesRequired(value: string) {
    return !!value || this.$t('validation.basic.required');
  }

  exactNumberOfCharsRule(numberOfChars: number) {
    return (val: string) => {
      return (
        !val ||
        val.trim().length === numberOfChars ||
        this.$i18n.t('validation.basic.exactNumOfChars', { num: numberOfChars })
      );
    };
  }

  setKbkValue(val: string[]): void {
    this.model.beneficiaryKBK = val;
  }

  openDialogWindow(): void {
    this.dialog = true;
    this.payerTypeOptions = this.dictionaries.find(
      ({ name }) => name === 'gis_gmp_payer_type'
    )?.documents;
    this.dulOptions = this.dictionaries.find(
      ({ name }) => name === 'gis_gmp_document_type'
    )?.documents;
    const charges = this.statementModel?.payments?.reduce(
      (acc: string[], payment: Payment) => {
        if (payment.charge?.supplierBillId) {
          acc.push(payment.charge.supplierBillId)
        }
        return acc;
      }, []
    );
    this.uinOptions = charges;
    this.preFillForm();
  }

  closeDialogWindow(): void {
    this.dialog = false;
    this.clearModel();
  }

  async preFillForm(): Promise<void> {
    const { inn, kpp } = await this.getOrganization();

    this.model.beneficiaryINN = inn || '';
    this.model.beneficiaryKPP = kpp || '';

    const { statement, system } = this.statementModel

    this.kbkOptions = this.serviceCard?.paymentLinks?.reduce(
      (acc: string[], charge: { [key: string]: string }) => {
        if (
          charge.regionCode.trim() === system.regionCode &&
          Number(charge.goal) === statement.goal
        ) {
          acc.push(charge.KBK);
        }
        return acc;
      }, []);

    const payment = cloneDeep(
      this.statementModel?.statement?.paymentData?.paymentsReceivedRequest
    );
    const payerIdentifier = cloneDeep(payment?.payerIdList?.structuredPayerIdentifier);
    if (!isEmpty(payerIdentifier)) {
      this.model.requestBy = this.requestByOptions[2] || '';
      this.model.payerType =
        this.payerTypeOptions.find(
          (el: any) => el.code === payerIdentifier.payerTypeCode
        ) || '';
      this.model.DUL =
        this.dulOptions.find(
          (el: any) => el.code === payerIdentifier.payerFLIdentDocCode
        ) || '';
      this.model.documentNumber = payerIdentifier.payerFLIdentDocValue || '';
      this.model.payerINN = payerIdentifier.payerIPINN 
        || payerIdentifier.payerULFRGINN 
        || payerIdentifier.payerULRFINN 
        || this.model.payerINN; 
      this.model.payerKIO = payerIdentifier.payerULFRGKIO || '';
      this.model.payerKPP = payerIdentifier.payerULFRGKPP 
        || payerIdentifier.payerULRFKPP 
        || this.model.payerKPP; 
    }
  }

  get serviceCard() {
    return this.$store.getters['registryService/services/servicesCard'];
  }

  async getOrganization(): Promise<Organization> {
    const currentOrganisation = get(
      this.statementModel,
      'system.department.id'
    );

    const organization = await this.$store.dispatch(
      'idm/organizations/getOrganization',
      { id: currentOrganisation }
    );
    return organization;
  }

  private async requestPayments(params: any): Promise<void> {
    this.loading = true;
    const sendData = {
      applicationId: this.common?.id,
      "parameters": params
    }
    const { traceId } = await this.$store
      .dispatch('wf/processes/dispatchProcess', {
        processKey: 'PaymentsReceivedRequestSend',
        data: sendData,
      })
      .catch((e) => notifyError(e.toString()))
      .finally(() => notifyInfo('Запрос отправлен'))
    if (traceId) {
      const handler = (e: any) => {
        const data = JSON.parse(get(e, 'data', '{}'));
        if (data.traceId === traceId) {
          this.loading = false;
          this.$store.commit(
            'utils/cards/needToUpdate',
            CardNeedToUpdateType.MODEL
          );
          this.$websockets.removeListener(handler);
        }
      };
      this.$websockets.addListener(handler);
    }
  }

  private handler(): void {
    const params: any = {};
    if (typeof this.model.requestBy === 'string') return;
    if (this.model.requestBy.id === '4') {
      if (!this.model.range.to || !this.model.range.from) return;
    } 
    switch (this.model.requestBy.id) {
      case '1':
        params.supplierBillIdList = { supplierBillId: this.model.UIN };
        if (this.model.isSBP) {
          params.paymentMethod = '1';
        }
        break;
      case '2':
        params.paymentIdList = {paymentId: this.model.UIP};
        break;
      case '3':
        params.payerIdList = {payerIdentifier: this.generateUIP(this.model)}; // custom UIP
        break;
      default:
        break;
    }

    if (this.model.range.from) {
      params.startDate = convertDateFormatWithoutLocale(this.model.range.from, DateFormat.backend);
    }
    if (this.model.range.to) {
      params.endDate = convertDateFormatWithoutLocale(this.model.range.to, DateFormat.backend);
    }
    if (this.model.beneficiaryKBK) {
      params.kbkList = { KBK: this.model.beneficiaryKBK };
    }
    if (this.model.type) {
      params.kind = this.model.type?.value;
    }
    this.requestPayments(params);
    this.closeDialogWindow();
  }

  private generateUIP(model: RequestModel) {
    let UIP = '';
    if (typeof model.payerType !== 'string') {
      switch (model.payerType.code) {
        case '1':
          if (typeof model.DUL !== 'string') {
            UIP =
              '1' +
              model.DUL.code +
              this.generateDocumentNumber(model.documentNumber);
          }
          break;
        case '2':
        case '3':
          if (model.payerKIO) {
            UIP = '3' + '00' + '00000' + model.payerKIO + model.payerKPP;
          } else {
            UIP = model.payerType.code + '00' + model.payerINN + model.payerKPP;
          }
          break;
        case '4':
          UIP = '4' + '00' + '0000000' + model.payerINN;
          break;
        default:
          UIP = '0000000000000000000000';
          break;
      }
    }
    return UIP || '0000000000000000000000';
  }

  private generateDocumentNumber(documentNumber: string) {
    return documentNumber
      .replace(/[\W_]+/g, '')
      .toUpperCase()
      .padStart(19, '0');
  }

  private clearModel(): void {
    this.model = {
      type: this.typeOptions && this.typeOptions[0] || '',
      requestBy: '',
      UIN: '',
      UIP: '',
      payerType: this.payerTypeOptions && this.payerTypeOptions[0] || '',
      DUL: '',
      documentNumber: '',
      organisationName: '',
      payerINN: '',
      payerKPP: '',
      payerKIO: '',
      beneficiaryINN: '',
      beneficiaryKPP: '',
      beneficiaryKBK: [],
      isSBP: false,
      range: {
        from: '',
        to: '',
      }
    }
  }
}

type RequestModel = {
  type: {label: string; value: string},
  requestBy: {id: string, label: string} | string,
  UIN: string,
  UIP: string,
  payerType: {
        value: string;
        code: string;
      } | string,
  DUL: {code: string, value: string} | string,
  documentNumber: string,
  organisationName: string,
  payerINN: string,
  payerKPP: string,
  payerKIO: string,
  beneficiaryINN: string,
  beneficiaryKPP: string,
  beneficiaryKBK: string[],
  isSBP: boolean,
  range: {
    from: string,
    to: string,
  }
}
</script>
<style lang="sass">
.width60
  width: 60%
.width49
  width: 49%
</style>