<i18n>
{
  "en": {
    "statements": {
      "DialogCommentAndDocuments": {
        "description": "Sending the regulations to the applicant on suspension of the conclusion and submission of extended documents and (or) presentation",
        "commentLabel": "Comment",
        "actionLabel": "Request",
        "documentTypeLabel": "Document type"
      }
    }
  },
  "ru": {
    "statements": {
      "DialogCommentAndDocuments": {
        "description": "Направление уведомления заявителю о приостановлении заявления и представлении дополнительных документов и (или) сведений",
        "commentLabel": "Комментарий",
        "actionLabel": "Отправить",
        "documentTypeLabel": "Тип документа"
      }
    }
  }
}
</i18n>

<template>
  <div>
    <q-btn
      :disable="disableAllButtons || buttonDisable"
      class="q-ml-sm"
      outline
      :label="get(buttonSettings, 'props.label')"
      :color="get(buttonSettings, 'props.color')"
      :class="{ hidden: !get(buttonSettings, 'props.visible', true) }"
      @click="doAction"
    />
    <q-dialog v-model="dialogVisible">
      <q-card
        class="no-shadow"
        :style="{
          maxWidth: '80vw',
          width: '700px',
        }"
      >
        <q-form @submit="submit">
          <q-card-section class="text-h6">
            <q-banner rounded class="q-mt-md grey-banner q-py-xs">
              <div class="text-grey-9">{{ descriptionText }}</div>
            </q-banner>
          </q-card-section>

          <q-card-section>
            <q-input
              v-model="comment"
              :label="
                $t('statements.DialogCommentAndDocuments.commentLabel')
              "
              filled
              required
              type="textarea"
              :disable="loading"
            />
          </q-card-section>

          <q-card-section>
            <q-select
              :options="availableDocumentTypeOptions"
              emit-value
              filled
              :label="
                $t('statements.DialogCommentAndDocuments.documentTypeLabel')
              "
              map-options
              :hide-dropdown-icon="disabledSelectDocument"
              :disable="disabledSelectDocument || loading"
              v-model="documentTypeObject"
              clearable
              :popup-content-style="{ width: '40%' }"
            />
          </q-card-section>

          <q-card-section>
            <base-uploader
              @input="(inputFiles) => (files = inputFiles)"
              :need-file="true"
              :show-description="false"
              :show-action="false"
              accept=".ppt, .odt, .pdf, .doc, .docx, .xls, .xlsx"
              :disable="disabledSelectDocument || loading"
            />
          </q-card-section>

          <q-inner-loading :showing="loading">
            <q-spinner-gears color="primary" size="50px" />
          </q-inner-loading>

          <q-card-actions class="q-pa-md" align="left">
            <q-btn
              type="submit"
              :label="
                $t('statements.DialogCommentAndDocuments.actionLabel')
              "
              color="primary"
              unelevated
              :disable="loading || chooseOneOfDocumentTypeOrFiles"
            />
          </q-card-actions>
        </q-form>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

import get from 'lodash/get';
import getUUID from 'uuid-by-string';

import { notifyError, notifySuccess } from '@utils/notify';
import S3UrlSignerFilesService from '@services/s3urlsigner/files';

// @TODO надо в будущем вывести общие типы сервисов, чтобы не было any...
type UUID = string;

type DocumentServiceSource = string; // MVZ...
type DocumentServiceCode = string; // handDocChildSub{FLOAT}
type DocumentService = {
  _service_id: UUID;
  code: DocumentServiceCode;
  id: UUID;
  modified: number;
  name: string;
  result: boolean;
  schema: string;
  source: DocumentServiceSource;
  version: number;
};
export type DocumentTypeOption = {
  type: DocumentServiceCode;
  label: string;
  data: DocumentService;
};

type RequestDocumentType = {
  code: string;
  name: string;
};
type RequestDocumentFile = {
  name: string;
  url: string;
};
type RequestDocument = {
  id: string;
  dateRegistered: string;
  type: RequestDocumentType;
  comment: string;
  file: RequestDocumentFile;
};

@Component({
  methods: {
    get,
  },
})
export default class DialogCommentAndDocuments extends Vue {
  @Prop() readonly model: any;
  @Prop() readonly disableAllButtons: any;
  @Prop({ required: true }) readonly userTask!: any;
  @Prop() readonly buttonSettings: any;
  @Prop() readonly common: any;
  @Prop({ default: null }) readonly filterDocument: (data: DocumentTypeOption) => boolean

  dialogVisible = false;
  loading = false;

  documentTypeOptions: DocumentTypeOption[] = [];
  availableDocumentTypeOptions: DocumentTypeOption[] = [];
  documentTypeObject: DocumentTypeOption | null = null;
  files: File[] = [];
  comment = '';

  get chooseOneOfDocumentTypeOrFiles():boolean {
    return !!(
      (this.files.length && !this.documentTypeObject) || 
      (this.documentTypeObject && !this.files.length))

  }

  get buttonId():string | null {
    return get(this.buttonSettings, 'id', null);
  }

  get buttonCode() {
    if (!this.buttonId) return this.buttonId
    return this.buttonId[0].toUpperCase() + this.buttonId.slice(1);
  }

  get buttonDisable() {
    return get(this.buttonSettings, 'props.disable', false);
  }

  get statementId() {
    return get(this.common, 'id', null);
  }

  get disabledSelectDocument() {
    return !this.availableDocumentTypeOptions.length;
  }

  get availableDocs() {
    return get(
      this.userTask,
      `userTask.outData.availableDocs["${this.buttonId}"]`,
      []
    );
  }

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

  get descriptionDefault(): string {
    return this.$t('statements.DialogCommentAndDocuments.description') as string;
  }

  get descriptionText(): string {
    const description = this.userTask.userTask?.outData[`description${this.buttonCode}`] || '';

    return description ? description : this.descriptionDefault;
  }

  get commentDefault(): string {
    return this.userTask.userTask?.outData?.commentTemplate || ''
  }

  mounted(): void {
    const comment = this.userTask.userTask?.outData[`commentTemplate${this.buttonCode}`] || '';
    
    this.comment = comment || this.commentDefault;
  }

  initDocumentType() {
    return new Promise((resolve, reject) => {
      const comparator = this.$store.getters['i18N/localeComparator'];
      const { documents } = this.serviceMeta;

      if (documents) {
        this.documentTypeOptions = (documents as DocumentService[])
          .map((document) => ({
            type: document.code,
            label: document.name,
            data: document,
          }))
          .sort((a, b) => comparator(a.label, b.label));

        resolve(this.documentTypeOptions);
      } else {
        reject();
      }
    });
  }

  availableDocumentTypeOptionsByAction() {
    if (typeof this.filterDocument !== 'function') {
      return this.documentTypeOptions;
    }

    return this.documentTypeOptions.filter(this.filterDocument);
  }

  doAction() {
    this.initDocumentType().then(() => {
      this.availableDocumentTypeOptions = this.availableDocumentTypeOptionsByAction();
    });

    this.dialogVisible = true;
  }

  async uploadDocuments() {
    const documents: RequestDocument[] = [];

    if (!this.files?.length || !this.documentTypeObject) return documents;

    this.loading = true;

    const file = this.files[0];
    const fileName = file.name;
    const ext = fileName.split('.').pop();
    const UUIDFromFileName = `${getUUID(fileName)}.${ext}`;

    const messageError = this.$t(
      'statements.DocumentsCard.errorLoadingDocuments'
    ) as string;

    try {
      const s3Url = await S3UrlSignerFilesService.uploadFileToS3ByPath({
        file,
        path: `Applications/${this.statementId}/file/${UUIDFromFileName}`,
      });

      if (!s3Url) throw new Error(messageError);

      const messageSuccess = this.$t(
        'statements.DocumentsCard.documentsUploadedSuccessfully'
      ) as string;

      notifySuccess(messageSuccess);

      documents.push({
        id: '',
        dateRegistered: '',
        type: {
          code: this.documentTypeObject?.type || '',
          name: this.documentTypeObject?.label || '',
        },
        comment: '',
        file: {
          name: fileName,
          url: s3Url,
        },
      });

      this.loading = false;
      return documents;
    } catch (error) {
      notifyError(messageError);
    }

    this.loading = false;
    return null;
  }

  async submit() {
    const documents = await this.uploadDocuments();
    if (!documents) return;

    this.$emit('update', {
      comment: this.comment,
    });

    this.$emit('submit', {
      buttonId: this.buttonId,
      data: {
        comment: this.comment,
        documents,
      },
      force: true,
    });

    this.dialogVisible = false
  }
}
</script>
