<i18n>
  {
    "en": {
      "statements": {
        "DocumentsCard": {
          "errorLoadingDocuments": "Documents uploaded successfully",
          "documentsUploadedSuccessfully": "Documents uploaded successfully",
          "formingSolution": "Forming a solution"
        },
        "DocumentDialog": {
          "addingDocument": "Adding a document",
          "documentTypeLabel": "Document type",
          "formingSolution": "Формирование проекта решения"
        }
      }
    },
    "ru": {
      "statements": {
        "DocumentsCard": {
          "errorLoadingDocuments": "Ошибка при загрузке документов",
          "documentsUploadedSuccessfully": "Документы успешно загружены"
        },
        "DocumentDialog": {
          "addingDocument": "Добавление документа",
          "documentTypeLabel": "Тип документа"
        }
      }
    }
  }
</i18n>

<template>
  <div>
    <div
      class="cursor-pointer"
      v-if="$slots.button"
      @click="doAction"
      v-bind="button.props"
    >
      <slot name="button"> </slot>
    </div>
    <q-btn
      v-else
      :disable="disableAllButtons"
      class="q-ml-sm"
      outline
      :label="get(buttonSettings, 'props.label')"
      :color="get(buttonSettings, 'props.color')"
      @click="doAction"
      v-bind="button.props"
    />
    <!-- TODO: Доделать дефолтную кнопку с настраеваемым id(props) и label'ом  -->
    <q-dialog v-model="value" :persistent="loading">
      <q-card class="no-shadow" style="max-width: 80vw; width: 700px">
        <q-card-section class="text-h6">
          {{
            documentSource === 'result'
              ? $t('statements.DocumentDialog.formingSolution')
              : $t('statements.DocumentDialog.addingDocument')
          }}
        </q-card-section>
        <q-card-section class="full-width q-gutter-y-md">
          <q-select
            disable
            hide-dropdown-icon
            :options="availableDocumentTypeOptions"
            emit-value
            filled
            :label="$t('statements.DocumentDialog.documentTypeLabel')"
            map-options
            v-model="documentTypeObject"
          />
          <component
            ref="form"
            v-if="uploadFormComponent"
            :is="uploadFormComponent"
            @update="updateUploadFormModel"
            :type-object="documentTypeObject"
            :form="form"
            :sub="sub"
            mode="edit"
          /><!-- TODO: Доделать подгрузку форм -->
        </q-card-section>
        <q-card-section class="full-width flex justify-end">
          <q-btn
            class="q-mr-md"
            v-if="documentTypeObject && documentTypeObject.source === 'result'"
            @click="uploadDocuments($event, 'updateDocumentByTemplate')"
            :disable="!isValidFormValue"
            :label="$t('base.uploader.formSolution')"
            :loading="model.loading"
            color="primary"
          />
          <q-btn
            @click="uploadDocuments($event, 'updateDocumentAttributes')"
            :disable="!isValidFormValue"
            :label="$t('base.uploader.save')"
            :loading="model.loading"
            color="primary"
          />
        </q-card-section>
        <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 {
  convertDateFormatWithoutLocale,
  convertDateFromBackendFormat,
  convertDateToBackendFormat,
} from '@utils/format-date';
import { CardNeedToUpdateType } from '@constants/models/Card';
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import isArray from 'lodash/isArray';
import mergeWith from 'lodash/mergeWith';
import { WorkflowServiceApi } from '@openapi/wf';
import { AttachmentApi, DocumentApi } from '@openapi/document-registry';
import { notifyError, notifySuccess } from '@utils/notify';

const attachmentApi = new AttachmentApi();
const documentApi = new DocumentApi();
const wfApi = new WorkflowServiceApi();

export default {
  name: 'DocumentsEditDialog',
  props: [
    'row',
    'common',
    'model',
    'disable-all-buttons',
    'user-task',
    'button-settings',
  ],
  computed: {
    documentSource() {
      return this.row?.source?.toLowerCase() || '';
    },
    actions() {
      return get(this.userTask, 'userTask.outData.actions') || [];
    },
    availableDocs() {
      return get(this.userTask, 'userTask.outData.availableDocs', []);
    },
    documentsFormKey() {
      if (this.userTask && this.userTask.userTask) {
        return this.userTask.userTask.formKey;
      } else {
        return undefined;
      }
    },
    decisionNumbers() {
      return get(this.userTask, 'userTask.outData.decisionNumbers', {});
    },
    isResultDocument() {
      const buttonId = get(this.buttonSettings, 'id');

      return ['refuse', 'reject', 'accept'].includes(buttonId);
    },
    serviceMeta() {
      return this.$store.getters['registryService/services/servicesCard'];
    },
  },
  data() {
    return {
      loading: false,
      button: {
        props: {
          color: 'red',
          label: 'Отказать',
          loading: false,
        },
        id: '',
      },
      comment: '',
      files: [],
      documentTypeOptions: [],
      availableDocumentTypeOptions: [],
      isUploaded: false,
      documentTypeObject: null,
      isEdit: true,
      uploadFormComponent: undefined,
      documentId: '',
      sub: [],
      isValidFormValue: true,
      form: {
        resNumber: '',
        dateRegistered: '',
      },
      value: false,
    };
  },
  methods: {
    get,
    isDate2(date) {
      if (!date) return false;
      if (typeof date === 'string')
        return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(date);
      return date instanceof Date;
    },
    availableDocumentTypeOptionsByAction(action) {
      if (this.documentTypeOptions && this.availableDocs[action]) {
        const availableDocs = this.availableDocs[action];

        return this.documentTypeOptions.filter((doc) => {
          return (
            Array.isArray(availableDocs) && availableDocs.includes(doc.type)
          );
        });
      }
    },
    doAction() {
      this.initDocumentType().then(() => {
        this.initUploader();
      });
      this.value = true;
    },
    async uploadDocuments($event, action) {
      this.loading = true;
      const uploadFile = ({ opts }) => {
        return attachmentApi
          .updateDocumentFile(
            'Applications',
            this.common.id,
            undefined,
            undefined,
            opts
          )
          .then(({ data: response }) => {
            this.isUploaded = true;

            notifySuccess(
              this.$t('statements.DocumentsCard.documentsUploadedSuccessfully')
            );

            return this.saveDocument(opts, response);
          })
          .catch(() => {
            notifyError(
              this.$t('statements.DocumentsCard.errorLoadingDocuments')
            );
          });
      };

      const opts = {
        files: this.files || [],
        action: action,
      };
      const description = (this.description || '').trim();

      if (description) {
        opts.description = description.trim();
      }

      if (opts.files.length) {
        await uploadFile({
          opts,
        });
      } else {
        await this.saveDocument(opts);
      }
      this.$store.commit(
        'utils/cards/needToUpdate',
        CardNeedToUpdateType.MODEL
      );
      this.loading = false;
      this.value = false;
    },
    updateUploadFormModel(model) {
      this.isValidFormValue = this.isValidForm();
      if (isEqual(this.form, model)) return;
      Object.keys(model).forEach((key) => {
        let val = model[key];
        if (val === 'true') {
          val = true;
        } else if (val === 'false') {
          val = false;
        }
        this.form[key] = val;
      });
    },
    initDocumentType() {
      return new Promise((resolve, reject) => {
        const comparator = this.$store.getters['i18N/localeComparator'];
        const docs = this.serviceMeta?.documents;
        if (docs) {
          this.documentTypeOptions = docs
            .map((document) => ({
              label: document.name,
              type: document.code,
              source: document.source,
              data: document,
            }))
            .sort((a, b) => comparator(a.label, b.label));

          resolve(this.documentTypeOptions);
        } else {
          reject();
        }
      });
    },
    getDocumentUploadFormFields(doc) {
      const cleanDoc = ({
        type,
        hidden,
        id,
        modified,
        schema,
        source,
        ...rest
      }) => {
        return rest;
      };

      return cleanDoc(doc);
    },
    initUploader(buttonId) {
      const row = this.row;

      const doc = this.model.documents.find((el) => {
        return el.id === row.id;
      });
      const sub = [];
      if (doc) {
        if (doc.source?.toLowerCase() === 'result')
          sub.push(get(this.model, 'statement.goal'));
        const form = this.getDocumentUploadFormFields(doc);
        this.updateUploadFormModel(form, 'upload');
      } else {
        this.form.resNumber = row.resNumber || '';
        this.form.dateRegistered =
          convertDateFromBackendFormat(row.dateRegistered) || '';
      }
      this.form.statement = mergeWith(
        {},
        this.model?.statement,
        this.form.statement,
        (objValue, srcValue) => (isArray(objValue) ? srcValue : undefined)
      );
      this.sub = sub;
      this.availableDocumentTypeOptions = this.availableDocumentTypeOptionsByAction(
        buttonId
      );
      this.documentTypeObject =
        this.documentTypeOptions.find(
          (document) => document.type === row.type.code
        ) || null;
      this.comment = get(row, 'file.comment') || '';
      this.files = [];
      this.isUploaded = false;
      this.documentId = row.id || '';
      this.schema = row.schema || '';
      this.documentModified = row.modified || '';

      buttonId = buttonId || get(this.buttonSettings, 'id');

      this.button.id = buttonId;

      this.fetchForm();
    },
    submit({ buttonId, data }) {
      this.$emit('submit', {
        buttonId,
        data,
        force: true,
      });
    },
    fetchForm() {
      if (this.uploadFormComponent) {
        return;
      }

      this.uploadFormComponent = this.$GlobalComponentImporter.registerComponent(
        this.documentsFormKey,
        'forms/'
      );
    },
    async saveDocument(opts) {
      console.log('[DocumentEditDialog][saveDocument]');

      const form = this.$refs.form;
      if (typeof form?.generateResolutionDocFields === 'function') {
        try {
          await form.generateResolutionDocFields();
        } catch (e) {
          console.error('didnt found generated fields', e);
        }
      }

      const uploadForm = Object.assign({}, this.form);
      const file = opts.files[0];
      const comment = opts.description || '';
      const dateRegistered = convertDateFormatWithoutLocale(
        this.form.dateRegistered
      );

      for (const key in uploadForm) {
        const value = uploadForm[key];
        if (value === undefined) {
          delete uploadForm[key];
        } else if (this.isDate2(value)) {
          // todo test this
          const date = convertDateFormatWithoutLocale(value);
          uploadForm[key] = convertDateToBackendFormat(date); // dateRegistered
        }
      }
      console.dir(uploadForm);

      const documentTypeObjectType = get(this.documentTypeObject, 'type');
      const documentTypeObjectLabel = get(this.documentTypeObject, 'label');
      const documentTypeObjectSource = get(this.documentTypeObject, 'source');
      const documentObject = Object.assign({}, uploadForm, {
        id: this.documentId,
        resNumber: this.form.resNumber,
        dateRegistered: convertDateToBackendFormat(dateRegistered),
        type: {
          code: documentTypeObjectType,
          name: documentTypeObjectLabel,
        },
        schema: this.schema,
        modified: this.documentModified,
        comment,
      });

      const submit = async () => {
        if (this.isEdit) {
          const document = {
            ...documentObject,
            source: documentTypeObjectSource,
          };
          await documentApi
            .updateDocument(documentObject.schema, [document])
            .then(() => {
              if (document.source === 'result') {
                const requestBody = {
                  id: opts.action,
                  data: {},
                };
                switch (opts.action) {
                  case 'updateDocumentByTemplate':
                    requestBody.data.document = document;
                    break;
                  case 'updateDocumentAttributes':
                    requestBody.data.docIds = [document.id];
                    break;
                }
                wfApi.submitForm(
                  get(this.userTask, 'userTask.taskId'),
                  requestBody
                );
              }
            });
        } else if (this.userTask) {
          this.submit({
            buttonId: this.buttonSettings.id,
            data: {
              document: {
                ...documentObject,
              },
            },
            force: true,
          });
        }
      };

      if (file) {
        documentObject.file = {
          name: file.name,
          url: file.name, // todo класть реальный URL, когда появится S3
        };
      }

      await submit();
    },
    isValidForm() {
      return this.form.valid ?? true;
    },
  },
};
</script>
