<i18n>
{
  "en": {
    "GenerateDmn": {
      "generateTable": "Generate table",
      "name": "Name",
      "type": "Type",
      "value": "Value",
      "create": "Create",
      "close": "Close",
      "AddDocumentEmptyError": "Fill in all the fields",
      "AddDocumentCodeError": "There is already an entry with this code",
      "generateDmnError": "An error occured while generating DMN-table",
      "splitApplicant": "Split applicant by types",
      "subjectList": "Subject list",
      "addRecord": "Add record",
      "confirm": "Confirm",
      "TableIsExists": "Table is already exists, do you want to replace it?",
      "createSubjectTypesDictionary": "Create a directory of subject types?",
      "updateSubjectTypesDictionary": "Update the directory of subject types?"
    }
  },
  "ru": {
    "GenerateDmn": {
      "generateTable": "Генерация таблицы",
      "code": "Код",
      "name": "Имя",
      "type": "Тип",
      "value": "Значение",
      "create": "Добавить",
      "close": "Закрыть",
      "AddDocumentEmptyError": "Заполните все поля",
      "AddDocumentCodeError": "Запись с таким кодом уже есть",
      "generateDmnError": "Произошла ошибка при генерации DMN-таблицы",
      "splitApplicant": "Разбить по видам заявителя",
      "subjectList": "Список субъектов",
      "addRecord": "Добавить запись",
      "confirm": "Подтверждение",
      "TableIsExists": "Такая таблица решений уже существует, вы хотите заменить ее?",
      "createSubjectTypesDictionary": "Создать справочник типов субъектов?",
      "updateSubjectTypesDictionary": "Обновить справочник типов субъектов?"
    }
  }
}
</i18n>

<template>
  <q-dialog v-model="dialogOpen" @hide="clearModel">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-card-section>
        <div class="text-h6">
          {{ $t('GenerateDmn.generateTable') }}
        </div>
      </q-card-section>

      <div v-if="dialogData">
        <q-card-section>
          <div class="row q-pb-md q-gutter-x-sm">
            <div class="col">
              <q-input
                filled
                readonly
                v-model="tableName"
                :label="$t('GenerateDmn.name')"
              />
            </div>
            <div class="col">
              <q-select
                filled
                v-model="dialogData.serviceCode"
                :options="goalsList"
                :label="$t('services.ProcessesCard.serviceCode')"
              />
            </div>
          </div>
          <q-checkbox
            :label="$t('GenerateDmn.splitApplicant')"
            v-model="splitApplicant"
          />
        </q-card-section>
        <q-card-section>
          <div class="text-h7 q-mb-sm">{{ $t('GenerateDmn.subjectList') }}</div>
          <div
            v-for="(item, index) in dialogData.subjects"
            :key="`document-${index}`"
            class="row q-gutter-sm q-mb-sm"
          >
            <div class="col">
              <q-input
                v-model="item.code"
                type="number"
                readonly
                filled
                :label="$t('GenerateDmn.code')"
              >
                <template #before>
                  <q-btn
                    text-color="primary"
                    dense
                    icon="delete"
                    flat
                    @click="deleteSubject(index)"
                  />
                </template>
              </q-input>
            </div>

            <div class="col">
              <q-input
                v-model="item.name"
                filled
                :label="$t('GenerateDmn.name')"
              />
            </div>
          </div>
        </q-card-section>
        <q-card-section>
          <div class="text-h7 q-mb-sm">{{ $t('GenerateDmn.addRecord') }}</div>
          <div class="row q-gutter-sm">
            <div class="col">
              <q-input
                v-model="newSubjectCode"
                type="number"
                filled
                dense
                :label="$t('GenerateDmn.code')"
              />
            </div>
            <div class="col">
              <q-input
                v-model="newSubjectName"
                filled
                dense
                :label="$t('GenerateDmn.name')"
              />
            </div>
            <div class="col">
              <q-btn
                @click="addSubject"
                :label="$t('GenerateDmn.create')"
                :loading="loading"
                color="primary"
              />
            </div>
          </div>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn
            @click="create"
            :label="$t('GenerateDmn.create')"
            unelevated
            :loading="loading"
            color="primary"
          />

          <q-btn
            @click="dialogOpen = false"
            :label="$t('GenerateDmn.close')"
            color="white"
            :loading="loading"
            text-color="primary"
            outline
          />
        </q-card-actions>
      </div>
      <div v-else>{{ $t('GenerateDmn.noResult') }}</div>
    </q-card>
  </q-dialog>
</template>

<script lang="ts">
// @ts-nocheck
import axios from 'axios';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { DocumentApi } from '@openapi/registry-service';
import {
  createDocument,
  updateAttachment,
  updateDocument,
} from '@services/registry-service';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import isEqual from 'lodash/isEqual';
import { uploadDMN } from '@services/wf';
import { notifyError } from '@utils/notify';

const documentApi = new DocumentApi();

@Component({})
export default class GenerateDmnDialog extends Vue {
  @Prop()
  common: any;

  dialogData = null;
  loading = false;
  addDocuments = false;
  dialogOpen = false;
  newSubjectCode = '';
  newSubjectName = '';
  splitApplicant = true;
  defaultTableModel = {
    serviceCode: '',
    subjects: [
      {
        code: '1',
        name: 'Заявитель',
      },
    ],
  };

  get goalsList() {
    const card = cloneDeep(
      this.$store.getters['registryService/services/servicesCard']
    );
    return (card.goalsList || []).map((i) => i.value);
  }

  get tableName() {
    const card = this.$store.getters['registryService/services/servicesCard'];
    const goal = this.dialogData.serviceCode || '';
    return `${card.name}_0${goal}`;
  }

  get subjectTypesDictId() {
    const card = this.$store.getters['registryService/services/servicesCard'];
    return `${card.name}_subject_types`;
  }

  get subjectTypesDictionary() {
    const card = this.$store.getters['registryService/services/servicesCard'];
    return card.subjectsList || [];
  }

  createApplicant(applicantSubjectType: string) {
    if (this.splitApplicant) {
      return [
        {
          applicantType: '1',
          subjectType: applicantSubjectType,
          name: 'Заявитель - Физическое лицо',
          bool: 'true',
        },
        {
          applicantType: '2',
          subjectType: applicantSubjectType,
          name: 'Заявитель - Юридическое лицо',
          bool: 'true',
        },
        {
          applicantType: '3',
          subjectType: applicantSubjectType,
          name: 'Заявитель - Индивидуальный предприниматель',
          bool: 'true',
        },
      ];
    } else {
      return [
        {
          subjectType: applicantSubjectType,
          name: 'Заявитель',
          bool: 'true',
        },
      ];
    }
  }

  createRequestBody() {
    const applicantSubjectType = this.dialogData.subjects.find(
      (subj) => subj.name === 'Заявитель'
    )?.code;

    const subjects = this.dialogData.subjects.map((subj) => ({
      subjectType: subj.code,
      name: subj.name,
      bool: 'true',
    }));
    const body = {
      id: this.dialogData.serviceId,
      decisionId: this.tableName,
      goal: this.dialogData.serviceCode,
      annotation: [
        ...(applicantSubjectType
          ? this.createApplicant(applicantSubjectType)
          : []),
        ...subjects.filter((subj) => subj.subjectType !== applicantSubjectType),
        {
          name: 'Проверка не пройдена',
          bool: 'false',
        },
      ],
      extensions: [
        {
          label: 'Тип субъекта',
          variable: 'subjectType',
          type: 'string',
        },
      ],
    };
    if (this.splitApplicant && applicantSubjectType) {
      body.extensions.push({
        label: 'Тип заявителя',
        variable: 'applicantType',
        type: 'string',
      });
    }
    return body;
  }

  addSubject() {
    if (this.newSubjectCode === '') {
      notifyError(this.$t('GenerateDmn.AddDocumentEmptyError'));
      return;
    }
    const isValidCode = !this.dialogData.subjects.find(
      (subj) => subj.code === this.newSubjectCode
    );
    if (!isValidCode) {
      notifyError(this.$t('GenerateDmn.AddDocumentCodeError'));
      return;
    }
    this.dialogData.subjects.push({
      code: this.newSubjectCode,
      name: this.newSubjectName,
    });
    this.newSubjectCode = '';
    this.newSubjectName = '';
  }

  deleteSubject(index) {
    this.dialogData.subjects.splice(index, 1);
  }

  sendRequest(body) {
    return axios.request({
      url: '/service/dmn/dmn',
      method: 'POST',
      data: body,
    });
  }

  async create() {
    if (!get(this.dialogData, 'serviceCode')) {
      notifyError(this.$t('GenerateDmn.AddDocumentEmptyError'));
      return;
    }

    const oldTable = await documentApi
      .searchDocuments('Table', `name==${this.tableName}`)
      .then(({ data }) => data || []);

    if (oldTable.length > 0) {
      this.$q
        .dialog({
          title: this.$t('GenerateDmn.confirm'),
          message: this.$t('GenerateDmn.TableIsExists'),
          cancel: true,
          persistent: true,
        })
        .onOk(() => {
          this.createOrUpdateDictionary().then(this.generateTable);
        });
    } else {
      this.createOrUpdateDictionary().then(this.generateTable);
    }
  }

  async createOrUpdateDictionary() {
    const subjects = this.dialogData.subjects.map((subj) => ({
      value: subj.code,
      label: subj.name,
    }));

    const isNotModified = isEqual(subjects, this.subjectTypesDictionary);

    if (isNotModified) {
      return;
    }

    const isNeedToCreate = await new Promise((resolve) => {
      this.$q
        .dialog({
          message: this.subjectTypesDictionary
            ? this.$t('GenerateDmn.updateSubjectTypesDictionary')
            : this.$t('GenerateDmn.createSubjectTypesDictionary'),
          cancel: true,
          persistent: true,
        })
        .onOk(() => {
          resolve(true);
        })
        .onCancel(() => {
          resolve(false);
        })
        .onDismiss(() => {
          resolve(false);
        });
    });

    if (!isNeedToCreate) {
      return;
    }

    const card = cloneDeep(
      this.$store.getters['registryService/services/servicesCard']
    );
    card.subjectsList = subjects;
    this.$store.dispatch('registryService/services/setCardForJson', card);
  }

  async generateTable() {
    const requestBody = this.createRequestBody();
    let resultDmn = null;
    try {
      resultDmn = await this.sendRequest(requestBody).then((data) => data.data);
    } catch (e) {
      notifyError(this.$t('GenerateDmn.generateDmnError'));
      return;
    }

    try {
      this.dialogData.name = this.tableName;
      this.loading = true;
      const { data: docResult } = await createDocument('Table', [
        this.dialogData,
      ]);

      this.dialogData.id = get(docResult, 'objectIds[0]');
      this.dialogData.schema = 'Table';
      const blob = new Blob([resultDmn], { type: 'multipart/form-data' });
      const file = new File([blob], `${this.tableName}.dmn`);

      const { data: attachResult } = await updateAttachment(
        'Table',
        get(this.dialogData, 'id'),
        undefined,
        [file]
      );

      this.dialogData.modified = attachResult.modified;

      this.dialogData.attachment = true;

      const { data: docResultUpdated } = await updateDocument('Table', [
        this.dialogData,
      ]);
      this.dialogData.modified = docResultUpdated.modified;

      const card = cloneDeep(
        this.$store.getters['registryService/services/servicesCard']
      );
      const tables = card.tables || [];

      tables.push(this.dialogData);

      card.tables = tables;
      this.$store.dispatch('registryService/services/setCardForJson', card);
      await uploadDMN(file);
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.loading = false;
      this.dialogOpen = false;
    }
  }

  clearModel() {
    this.dialogData = cloneDeep(this.defaultTableModel);
    this.$emit('commonModels', {
      GenerateDmnDialog: {
        data: null,
      },
    });
  }

  destroyed() {
    this.clearModel();
  }

  @Watch('common.models.GenerateDmnDialog.data', { immediate: true })
  onDialogDataChange(val) {
    if (val) {
      this.dialogOpen = true;
      this.dialogData = cloneDeep(this.defaultTableModel);
      this.dialogData.serviceId = val.serviceId;
      if (this.subjectTypesDictionary?.length) {
        this.dialogData.subjects.length = 0;
        this.subjectTypesDictionary.forEach((d) => {
          this.dialogData.subjects.push({
            code: d.value,
            name: d.label,
          });
        });
      }
    }
  }
}
</script>

<style scoped lang="scss">
.flex-item-button {
  min-width: 90px;
  height: 56px;
}
</style>
