<i18n>
{
  "en": {
    "interRequests": {
      "RequestCard": {
        "tab": "Request data"
      },
      "ResponseCard": {
        "tab": "Response data"
      },
      "BasicCard": {
        "title": "Interdepartmental request",
        "tab": "Request data",
        "print": "Print",
        "resend": "Resend",
        "inDeveloping": "In developing",
        "dueDateReq": "Due date",
        "noDiscoveryData": "No response data of discovery",
        "fileSuccess": "File has been downloaded successful",
        "fileError": "Error in downloading file",
        "discoveryError": "Error loading from discovery service",
        "certificateError": "Electronic signature of the data provider is missing"
      }
    }
  },
  "ru": {
    "interRequests": {
      "RequestCard": {
        "tab": "Данные запроса"
      },
      "ResponseCard": {
        "tab": "Данные ответа"
      },
      "BasicCard": {
        "title": "Межведомственный запрос",
        "tab": "Данные запроса",
        "print": "Печать",
        "resend": "Отправить повторно",
        "inDeveloping": "В разработке",
        "dueDateReq": "Регламентная дата исполнения",
        "noDiscoveryData": "Нет ответа на запрос данных по discovery",
        "fileSuccess": "Файл загружен успешно",
        "fileError": "Ошибка при загрузке файла",
        "discoveryError": "Ошибка загрузки из сервиса discovery",
        "certificateError": "Электронная подпись поставщика данных отсутствует"
      }
    }
  }
}
</i18n>

<template>
  <div>
    <a v-show="false" ref="export" />
    <q-card
      v-if="!loading"
      class="bg-grey-custom no-shadow q-gutter-y-md q-mx-md q-mt-md"
    >
      <div
        class="rounded-borders bg-white items-center justify-between row q-pa-md"
      >
        <div class="text-h6 text-grey-9 col q-pr-md">
          <q-btn
            padding="xs"
            class="text-grey-7 q-mr-md"
            :disable="!this.statementId"
            color="grey-3"
            icon="arrow_back"
            @click="backToStatement"
          />
          {{ $t('interRequests.BasicCard.title') }}
          {{
            get(model, 'departmentRecipient')
              ? '(' + get(model, 'departmentRecipient') + ')'
              : ''
          }}
          <strong>{{ get(model, 'requestName') }}</strong>
          <span class="text-grey-6">{{ get(model, 'number') }}</span>
        </div>
        <div class="center row-md">
          <div class="q-pb-md q-pb-md-none">
            <q-btn
              v-if="false"
              color="white"
              text-color="primary"
              class="q-mr-md"
              outline
              :label="$t('interRequests.BasicCard.resend')"
              disable
              type="button"
            />
            <q-tooltip>
              {{ $t('interRequests.BasicCard.inDeveloping') }}
            </q-tooltip>
          </div>
          <div class="justify-end flex">
            <q-btn
              v-if="showPrintButton"
              color="white"
              text-color="primary"
              class="q-mr-md"
              outline
              :label="$t('interRequests.BasicCard.print')"
              type="button"
              :disable="!recentStatus"
              @click="printRequest"
            />
          </div>
        </div>
      </div>

      <div class="rounded-borders bg-white q-gutter-y-md q-pa-md">
        <FormGeneratorWrapper
          v-if="!loading"
          :model="formModel"
          :schema="schema || {}"
          :hide-nulls="true"
        />
      </div>
    </q-card>

    <base-tabs v-if="!loading" :current-tab="tabs.current" :tabs="tabs.list" />
    <q-inner-loading :showing="loading">
      <q-spinner-gears color="primary" size="50px" />
    </q-inner-loading>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { BaseCardCommon } from '@interfaces/components';
import FormGeneratorWrapper from '@components/common/node-generator/FormGeneratorWrapper.vue';
import preparePrintData from '@utils/print-form';
import PrinterService from '@services/printer/index';
import { convertDateFormat } from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';
import get from 'lodash/get';
// eslint-disable-next-line no-restricted-imports
import { parseISO } from 'date-fns';
import { fetchAttachment } from '@services/registry-service';
import { DocumentApi } from '@openapi/document-registry';
import { InteragencyRequest } from '@interfaces/entities/InteragencyRequest';
import { BaseTabs } from '@interfaces/base/BaseTabs';
import { Schema } from '@devsun/eva-models';
import { notifyError, notifySuccess } from '@utils/notify';

const documentApi = new DocumentApi();

const CLASS_MZ_EGRUL = 'egrul-inn';

const CLASS_MZ_EGRIP = 'egrip';

const PRINT_FILE_NAME = 'PrintFormMZ.pdf';

@Component({
  components: {
    FormGeneratorWrapper,
  },
  methods: {
    get,
  },
})
export default class InterRequest extends Vue {
  @Prop({}) private common?: BaseCardCommon;
  @Prop({}) private model?: InteragencyRequest;

  private printFormTemplate: File | null = null;

  private schemaCode = 'InterRequests_CardsInterRequest';

  private schema: Schema.MetaClassSchemaRaw | null = null;

  private formModel: any = null;

  private get activeTab(): string {
    return this.common?.active || 'basic';
  }

  private get tabs(): BaseTabs {
    return {
      current: this.activeTab,
      list: [
        {
          name: this.$t('interRequests.RequestCard.tab').toString(),
          path: 'request',
          visible: true,
        },
        {
          name: this.$t('interRequests.ResponseCard.tab').toString(),
          path: 'response',
          visible: true,
        },
      ],
    };
  }

  private get showPrintButton(): boolean {
    return !!get(this.model, 'response') && !!this.printFormTemplate &&
      get(this.model, 'status', 'empty') !== 'sendingFailed';
  }

  private get certificate(): string {
    let cert = get(this.model, 'senderCertificate', '');
    cert = cert.length > 0 ? cert : get(this.model, 'personalCertificate', '');
    cert = cert.length > 0 ? cert : get(this.model, 'smevCertificate', '');
    return cert;
  }

  // Подготовка параметров для печатной формы.
  // т.к. Mustache не дает проверить пустой массив или нет
  // для каждого массива формируется доп поле `${arrayVariable}+_has_items`
  private get preparedParams() {
    if (
      this.model?.requestData &&
      this.model?.responseData &&
      this.model.sendDate &&
      this.model.receiveDate
    ) {
      return preparePrintData({
        ...this.model.requestData,
        ...this.model.responseData,
        ...{
          sendDate: this.convertDateForMz(this.model.sendDate),
          receiveDate: this.convertDateForMz(this.model.receiveDate),
        },
      });
    }
    return {};
  }

  private get recentStatus(): boolean {
    return get(this.model, 'status', 'empty') !== 'fail';
  }

  private get loading(): boolean {
    return !this.formModel;
  }

  private get statementId(): string {
    const statement = this.$route.query.statement;
    return statement ? String(statement).trim() : '';
  }

  private get printParams() {
    let params = {
      certificate: this.certificate,
    };

    if (this.model) {
      params = {
        // ...(this.certificate && params),
        ...params,
        id: this.model.id,
        ...this.preparedParams,
      };
    }

    return params;
  }

  @Watch('common.active', {
    immediate: true,
  })
  activeWatcher(val: string): void {
    this.tabs.current = val;
  }

  @Watch('model', {
    immediate: true,
  })
  modelWatcher(val: InteragencyRequest): void {
    if (val) {
      this.setFormModel(val);
    }
  }

  private created(): void {
    this.init();
    this.getFormSchema();
  }

  private beforeDestroy(): void {
    this.$store.commit(`utils/cards/removeModel`, {
      path: this.common?.path,
    });

    this.$store.commit(`utils/cards/removeUserTask`, {
      path: this.common?.path,
    });
  }

  private convertDateForMz(date: string): string {
    return this.model?.class === CLASS_MZ_EGRUL ||
      this.model?.class === CLASS_MZ_EGRIP
      ? convertDateFormat(
          parseISO(date),
          DateFormat.backend,
          DateFormat.dateTimeFull
        )
      : date;
  }

  private backToStatement(): void {
    if (!this.statementId) {
      return;
    }

    this.$router.push({
      name: 'cards',
      params: {
        id: this.statementId,
        path: 'statements',
      },
      query: {
        active: 'cross',
        lock: 'true',
        components: this.$store.getters['cardComponents/statements/components'],
      },
    });
  }

  private init(): void {
    this.initModel().then((model: InteragencyRequest) => {
      this.fetchStatement()
        .then((statement) => {
          this.initPrintFormTemplate(model.class, statement.system?.serviceId);
          this.setTotalModel(
            {
              statement: statement,
            },
            model
          );
        })
        .catch((e) => {
          this.setTotalModel(
            {
              statement: null,
            },
            model
          );
          notifyError(e.message.toString());
        });
    });
  }

  initModel(): Promise<InteragencyRequest> {
    return new Promise((resolve, reject) => {
      try {
        documentApi
          .getDocument(
            'InterDepReq',
            this.common?.id ?? '',
            'interDepartmentReq, attachments'
          )
          .then(({ data: returnData }) =>
            resolve(returnData as InteragencyRequest)
          )
          .catch((e) => reject(e));
      } catch (e) {
        return reject(e);
      }
    });
  }

  fetchInteragency(
    mzClass: string,
    serviceId: string
  ): Promise<InteragencyRequest> {
    // eslint-disable-next-line no-async-promise-executor
    return new Promise(async (resolve, reject) => {
      try {
        const service = await this.$store.dispatch(
          'registryService/services/getServiceMeta',
          {
            id: serviceId,
            opts: {
              noCommit: false,
              expand: ['interagencies'],
            },
          }
        );
        const interagencies = service.interagencies || [];
        const interagency =
          interagencies.find(
            (record: InteragencyRequest) => record.class === mzClass
          ) || {};
        return resolve(interagency);
      } catch (err) {
        console.error('[inter requests][get interagency from registry]', {
          mzClass,
        });
        reject(err);
      }
    });
  }

  private fetchStatement(): Promise<any> {
    return new Promise((resolve) => {
      documentApi
        .getDocument('Applications', this.statementId)
        .then(({ data: statement }) => {
          resolve(statement);
        });
    });
  }

  private async initPrintFormTemplate(
    mzClass: string,
    serviceId: string
  ): Promise<void> {
    const interagency = await this.fetchInteragency(mzClass, serviceId);
    fetchAttachment(
      'Interagency',
      get(interagency, 'id', ''),
      get(interagency, 'templateUrl', ''),
      false
    ).then((file) => {
      this.printFormTemplate = file;
    });
  }

  private getFormSchema(): void {
    // TODO : Request this from SchemaRegistry. This one requests a static common one
    // Have to make a registry/ui for common schemas
    this.$store
      .dispatch('utils/components/fetchModelByCode', this.schemaCode)
      .then((schema) => {
        this.schema = schema;
      })
      .catch(() => {
        notifyError(this.$t('StatementCard.errorLoadingModel').toString());
      });
  }

  private setTotalModel(customObject: any, model: InteragencyRequest): void {
    const totalModel = Object.assign(customObject, model);
    this.$store.commit('utils/cards/addModel', {
      model: totalModel,
      path: this.common?.path,
    });
  }

  private setFormModel(model: InteragencyRequest): void {
    this.formModel = {
      'inter_requests.name': get(model, 'requestName', ''),
      'inter_requests.description': get(model, 'description'),
      'inter_requests.provider': get(model, 'provider'),
      'inter_requests.status': get(model, 'status', 'empty'),
    };
  }

  private printRequest(): void {
    console.log('[inter_requests][printRequest] printParams');
    console.dir(this.printParams);

    if (!this.printParams?.certificate) {
      notifyError(
        this.$t('interRequests.BasicCard.certificateError').toString()
      );

      return;
    }

    if (this.printFormTemplate) {
      const blob = new Blob([`${this.printFormTemplate}`], {
        type: 'text/html',
      });
      const bin = new File([blob], PRINT_FILE_NAME);

      PrinterService.fetchConvertedFileSyncWithStamp({
        fileName: PRINT_FILE_NAME,
        template: bin,
        parameters: JSON.stringify(this.printParams),
      })
        .then(() => {
          notifySuccess(
            this.$t('interRequests.BasicCard.fileSuccess').toString(),
            'check_circle_outline'
          );
        })
        .catch(() => {
          notifyError(this.$t('interRequests.BasicCard.fileError').toString());
        });
    }
  }
}
</script>
