<i18n>
{
    "en": {
        "upload": {
            "SignDialog": {
                "document": "Document",
                "additionalDocuments": "Additional documents",
                "sign": "Sign",
                "fileToSignWasNotFound": "The file to sign was not found",
                "cryptoProIncorrectlyConfigured": "The CryptoPro program is incorrectly configured or the browser plug-in is not installed.",
                "failedGenerate": "Failed to generate the resulting document files.",
                "isNotValid": "Signature generation error. Invalid certificate.",
                "listOfCertificates": "List of certificates",
                "documentSignature": "Document signature",
                "validTo": "Valid to",
                "s3Error": "S3 service error",
                "s3PutError": "Error loading file into S3"
            }
        }
    },
    "ru": {
        "upload": {
            "SignDialog": {
                "document": "Документ",
                "additionalDocuments": "Дополнительные документы",
                "sign": "Подписать",
                "fileToSignWasNotFound": "Файлы для подписания не найдены.",
                "cryptoProIncorrectlyConfigured": "Неверно настроена программа \"КриптоПро\" или не установлен плагин для браузера.",
                "failedGenerate": "Не удалось сформировать файлы результирующего документа.",
                "isNotValid": "Ошибка формирования подписи. Невалидный сертификат или лицензия.",
                "listOfCertificates": "Список сертификатов",
                "documentSignature": "Подпись документа",
                "validTo": "Действителен до",
                "s3Error": "Ошибка сервиса s3",
                "s3PutError": "Ошибка при загрузке файла в S3"
            }
        }
    }
}
</i18n>

<template>
  <div>
    <q-dialog v-model="open" @hide="hideModal">
      <q-card class="full-width no-shadow" style="max-width: 580px">
        <q-card-section>
          <div class="text-h6">
            {{ $t('upload.SignDialog.documentSignature') }}
          </div>
        </q-card-section>
        <q-card-section class="q-gutter-y-md">
          <table class="text-primary" v-if="model">
            <tr>
              <td>
                <q-item>
                  <q-item-section>
                    <q-item-label class="text-grey-9">
                      {{ $t('statements.DocumentsCard.document') }}
                    </q-item-label>
                  </q-item-section>
                </q-item>
              </td>
              <td>
                <q-item>
                  <q-item-section>
                    <q-item-label>
                      {{ model.title }}
                    </q-item-label>
                  </q-item-section>
                </q-item>
              </td>
            </tr>
          </table>
          <q-select
            v-model="certificate"
            :disable="!certificates.length"
            :options="certificates"
            class="full-width"
            filled
            :label="$t('upload.SignDialog.listOfCertificates')"
          >
            <template #option="{ opt, toggleOption, selected }">
              <q-item
                @click="toggleOption(opt)"
                :class="{
                  'bg-red-1': isExpired(opt.data.validTo),
                  'bg-blue-1': selected,
                }"
                clickable
              >
                <div>
                  <div class="text-grey-8">{{ opt.label }}</div>
                  <div :style="{ fontSize: '0.75rem' }" class="">
                    {{ $t('upload.SignDialog.validTo') }}:
                    {{ convertDateFromBackendFormat(opt.data.validTo) }}
                  </div>
                </div>
              </q-item>
            </template>
          </q-select>
        </q-card-section>
        <q-card-actions align="right">
          <!-- v-if="model && model.reportLink" -->
          <q-btn
            :disable="!isValidSystemSetup || !certificate"
            :loading="loading"
            :label="$t('upload.SignDialog.sign')"
            unelevated
            color="primary"
            @click="handler('sign')"
          >
            <template #loading>
              <q-spinner-gears />
            </template>
          </q-btn>
        </q-card-actions>
        <q-inner-loading :showing="loading">
          <q-spinner-gears color="primary" size="50px" />
        </q-inner-loading>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
// @ts-nocheck
import { convertDateFromBackendFormat, isPastDate } from '@utils/format-date';
import { notifyError, notifySuccess } from '@utils/notify';
import S3UrlSignerFilesService from '@services/s3urlsigner/files';
import { Component, Prop, PropSync, Watch, Vue } from 'vue-property-decorator';
// import { RegistryApi } from '@openapi/registry-data';
import get from 'lodash/get';
import { WorkflowServiceApi } from '@openapi/wf';
import last from 'lodash/last';
import cloneDeep from 'lodash/cloneDeep';
import { ExportApi } from '@openapi/refugee-compensation';

const wfApi = new WorkflowServiceApi();

const PDF_FORMAT = 'PDF';
const XML_FORMAT = 'XML';
// const CREATE_SIGN_PROCESS_CODE = 'RegistryKompensDectskOtdMIRCreateSign';
// const fileLinkTmp = 's3://pgs-application/6b57fbf7-7910-4d07-b6e7-47be9b9af5de/unloading_1656050459--2905902086444034571.xml';
// const file2LinkTmp = 's3://pgs-application/6b57fbf7-7910-4d07-b6e7-47be9b9af5de/unloading_1638549820-8202329290425180067.xml';

@Component({
  methods: {
    convertDateFromBackendFormat,
  },
  components: {},
})
export default class UkranianRefugeeUploadSignDialog extends Vue {
  @PropSync('openDialog') open?: boolean;
  @Prop() schema!: string;
  @Prop() model!: any;
  //@Prop() processInfo!: any;

  private certificate = null;
  private certificates = [];
  private isValidSystemSetup = false;
  private loading = false;
  private positionFromAccount = null;
  private signatureHash = '';

  private get currentUser() {
    return this.$store.getters['oidcClient/currentUser'] || null;
  }

  @Watch('model', { immediate: true })
  onDialogDataChange(val: any): void {
    if (val && this.open) {
      this.$store
        .dispatch('utils/cryptoPro/isValidSystemSetup')
        .then((isValid) => {
          this.isValidSystemSetup = isValid;

          if (isValid) {
            this.$store
              .dispatch('utils/cryptoPro/fetchCertificates')
              .then((certificates) => {
                this.certificates = certificates.map((certificate) => ({
                  label: certificate.subjectName,
                  value: certificate,
                  data: certificate,
                }));
              });
          } else {
            notifyError(
              this.$t('upload.SignDialog.cryptoProIncorrectlyConfigured')
            );

            this.loading = false;
          }
        })
        .catch((e) => {
          const message = get(e, 'message');

          if (message) {
            notifyError(message);
          } else {
            notifyError(
              this.$t('upload.SignDialog.cryptoProIncorrectlyConfigured')
            );
          }
          this.loading = false;
        });
    }
  }

  async handler() {
    if (!this.model) {
      this.hideModal();
      notifyError('Попробуйте снова');
      return;
    }
    this.loading = true;
    const isValid = await this.$store
      .dispatch(
        'utils/cryptoPro/isValidSystemCertificate',
        this.certificate.value
      )
      .catch((e) => {
        const message = get(e, 'message');
        if (message) {
          notifyError(message);
        } else {
          notifyError(
            this.$t('upload.SignDialog.cryptoProIncorrectlyConfigured')
          );
        }
        this.loading = false;
      });
    if (typeof isValid !== 'undefined' ? isValid : false) {
      try {
        const updatedRecord = cloneDeep(this.model);

        if (this.model.registryFileLink) {
          updatedRecord.registryFileLinkSig = await this.signFileByUrl(this.model.registryFileLink);
        }

        if (this.model.registrySberFileLink) {
          updatedRecord.registrySberFileLinkSig = await this.signFileByUrl(this.model.registrySberFileLink);
        } 

        updatedRecord.state = 'Подписан';
        updatedRecord.modified = new Date().getTime();

        const exportApi = new ExportApi();
        await exportApi.updateExportRecord([
          updatedRecord
        ]);

        this.hideModal();
        this.$emit('listRefresh');
        notifySuccess('Документы успешно подписаны');
      } catch (e) {
        notifyError(e.message.toString());
        this.hideModal();
      }
    } else {
      this.loading = false;
      notifyError(this.$t('upload.SignDialog.isNotValid'));
    }
  }

  isExpired(date: string): boolean {
    return isPastDate(date);
  }

  private async signFileByUrl(url) {
    return await S3UrlSignerFilesService.fetchFileFromS3ByUrl({ url })
      .then(({ file }) =>
        this.$store.dispatch('utils/cryptoPro/generateHash', {
           file,
        })
      )
      .then((hash) =>
        this.$store.dispatch('utils/cryptoPro/createSignature', {
          hash,
          certificate: this.certificate.value,
        })
      )
      .then((signature) => {
        const blob = new Blob([signature], {
          type: 'text/plain',
        });
        const name = last(url.split('/'));
        const signFile = new File([blob], `${name}.sig`);
        // pgs-application
        const path = `Applications/${this.model.id}/sign/${signFile.name}`;
        return S3UrlSignerFilesService.uploadFileToS3ByPath({
          file: signFile,
          path,
        });
    }).then((s3url) => {
      return s3url
    });
  }

  private abortSignProcess(): void {
    wfApi.submitForm(this.processInfo?.taskId, {
      cert: null,
    });
  }

  private hideModal(): void {
    if (this.processInfo && !this.processInfo.success) {
      this.abortSignProcess();
    }
    this.open = false;
    this.certificate = undefined;
    this.certificates = [];
    this.model = undefined;
    this.isValidSystemSetup = false;
    this.loading = false;
    this.signatureHash = '';
    this.processInfo = null;
  }

  async getAccountFromPosition(): void {
    const accId = get(this.currentUser, 'sub');
    const account = await this.$store.dispatch('idm/accounts/dispatchAccount', {
      id: accId,
    });

    this.positionFromAccount = get(account, 'position', null);
  }

  create(): void {
    this.getAccountFromPosition();
  }
}
</script>
