<template>
  <q-dialog v-model="settingsDialog">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-card-section>
        <div class="text-h6">
          {{ isEditForm ? 'Редактирование процесса' : 'Создание процесса' }}
        </div>
      </q-card-section>
      <div v-if="dialogData">
        <q-card-section class="q-pb-md q-gutter-y-md">
          <div class="flex justify-between items-start no-wrap">
            <q-select
              filled
              option-value="code"
              option-label="value"
              emit-value
              map-options
              class="full-width"
              :rules="[requiredHendler]"
              v-model="dialogData.processType"
              :options="processTypes"
              label="Тип"
            />
          </div>
          <div
            v-if="!isEditForm"
            class="flex justify-between items-start no-wrap"
          >
            <q-file
              :accept="
                schemaName === 'SettingsForServiceProcess' ? '.bpmn' : '.dmn'
              "
              clearable
              filled
              counter
              label="Загрузить"
              ref="processDialogFile"
              :rules="[validateFileName]"
              :error-message="
                upload.file
                  ? $t('processes.validationErrors.errorFileName')
                  : $t('processes.validationErrors.errorFileRequired')
              "
              v-model="upload.file"
              @input="fileHandler"
            />
            <q-btn
              v-if="schemaName === 'SettingsForServiceProcess'"
              color="primary"
              class="q-ml-sm flex-item-button"
              filled
              label="import"
              @click="isBpmnCloudLoader = true"
            />
            <BaseBpmnCloudLoader
              :show.sync="isBpmnCloudLoader"
              value-mode="file"
              @getBpmn="bpmnSchemaUploadHandler"
            />
          </div>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn
            v-if="isEditForm"
            label="Cохранить"
            unelevated
            color="primary"
            @click="edit"
          />
          <q-btn
            v-else
            label="Создать"
            unelevated
            color="primary"
            @click="create"
          />
          <q-btn
            @click="settingsDialog = false"
            label="Закрыть"
            color="white"
            text-color="primary"
            outline
          />
        </q-card-actions>
      </div>
    </q-card>
  </q-dialog>
</template>

<script>
import { codemirror } from 'vue-codemirror';
import { multipleUseValidator } from '@/utils/field-validation/multipleUse';
import { fileNameValidator } from '@/utils/field-validation/fileName';
import BaseBpmnCloudLoader from '@components/common/base-bpmn-cloud-loader/index.vue';
import cloneDeep from 'lodash/cloneDeep';
import axios from 'axios';
import {
  SettingsForServiceProcessApi,
  DocumentApi,
} from '@openapi/registry-service';

const settingsForServiceProcessApi = new SettingsForServiceProcessApi();
const documentApi = new DocumentApi();

export default {
  name: 'ProcessDialog',
  components: {
    codemirror,
    BaseBpmnCloudLoader,
  },
  props: ['common', 'cardModel'],
  data() {
    return {
      dialogData: {
        processName: '',
        processType: '',
      },
      upload: {
        file: null,
        loading: false,
      },
      schemaName: 'SettingsForServiceProcess',
      settingsDialog: false,
      isBpmnCloudLoader: false,
      processTypes: [],
      isEditForm: false,
    };
  },
  computed: {
    processes() {
      return (
        this.$store.getters[
          'registryService/additionalSettings/settingsForServiceCard'
        ].settingsforserviceprocess || []
      );
    },
    dictTypes() {
      return (
        this.$store.getters[
          'registryService/additionalSettings/setSettingsDictionary'
        ].DictProcessTypeForSettingForService || []
      );
    },
  },
  methods: {
    async open(row) {
      this.clearForm();
      if (this.dictTypes.length) {
        let processesTypesFilt = this.processes.map((e) => e.processType);

        if (row)
          processesTypesFilt = processesTypesFilt.filter(
            (e) => e !== row.processType
          );
        this.processTypes = this.dictTypes.filter(
          (e) => !processesTypesFilt.includes(e.code)
        );
      }
      if (row) {
        this.isEditForm = true;
        this.dialogData = cloneDeep(row);
        if (!row.processName || !row.id) return;
        this.schemaName = row.schema;
      } else {
        this.isEditForm = false;
      }
      this.settingsDialog = true;
    },
    async create() {
      const validation = await this.validate();

      if (!validation.isValid) {
        this.$q.notify({
          color: 'negative',
          icon: 'error',
          message: validation.message,
        });
        return;
      }
      try {
        const formdata = new FormData();

        formdata.append('files', this.upload.file);
        formdata.append('parameters', JSON.stringify(this.dialogData));

        // await settingsForServiceProcessApi.createProcessWithAttachment([this.upload.file], this.dialogData)
        // TODO: Не работает запрос в openapi
        await axios
          .post(
            '/service/registry/service/settings-for-service-process/process-with-attachment',
            formdata
          )
          .then((response) => {
            this.dialogData = response.data.document;
            const card = cloneDeep(
              this.$store.getters[
                'registryService/additionalSettings/settingsForServiceCard'
              ]
            );
            const processes = card.settingsforserviceprocess || [];
            processes.push(this.dialogData);
            card.settingsforserviceprocess = processes;
            this.$store.dispatch(
              'registryService/additionalSettings/setCardForJson',
              card
            );
            this.$store.dispatch(
              'registryService/additionalSettings/setunsavedChanges',
              'processes'
            );
          });
      } catch (e) {
        this.$q.notify({
          color: 'negative',
          icon: 'error',
          message: e.message,
        });
      } finally {
        this.settingsDialog = false;
      }
    },
    async edit() {
      const validation = this.validateEdit();
      if (!validation.isValid) {
        this.$q.notify({
          color: 'negative',
          icon: 'error',
          message: validation.message,
        });
        return;
      }
      await settingsForServiceProcessApi
        .updateSettingsForServiceProcess([this.dialogData])
        .then(() => {
          const card = cloneDeep(
            this.$store.getters[
              'registryService/additionalSettings/settingsForServiceCard'
            ]
          );

          const processes = card.settingsforserviceprocess || [];
          processes.find(
            (e) => e.id === this.dialogData.id
          ).processType = this.dialogData.processType;
          card.settingsforserviceprocess = processes;
          this.$store.dispatch(
            'registryService/additionalSettings/setCardForJson',
            card
          );
          this.settingsDialog = false;

          this.$q.notify({
            color: 'positive',
            icon: 'check_circle_outline',
            message: 'Успешно',
          });
        });
    },

    fileHandler(file) {
      if (file && file.name) {
        this.dialogData.processName = file.name.replace('.bpmn', '');
      }
    },

    async validate() {
      if (!this.validateFileName(this.dialogData.processName)) {
        return {
          isValid: false,
          message: this.$t('processes.validationErrors.fileError'),
        };
      }
      if (this.dialogData.processType === '') {
        return {
          isValid: false,
          message: 'Поле тип должно быть заполнено',
        };
      }
      if (!this.upload?.file) {
        return {
          isValid: false,
          message: this.$t('processes.validationErrors.errorFileRequired'),
        };
      }
      if (!this.validateFileName(this.upload.file)) {
        return {
          isValid: false,
          message: this.$t('processes.validationErrors.fileError'),
        };
      }
      const fileNameValidation = await fileNameValidator(this.upload.file);
      if (!fileNameValidation.isValid) {
        return {
          isValid: false,
          message: this.$t('processes.validationErrors.fileNameMatchId', {
            processId: fileNameValidation.message ?? '',
          }),
        };
      }
      const multipleUseValidation = await multipleUseValidator(
        this.upload.file,
        this.$route.params.id
      );

      if (!multipleUseValidation.isValid) {
        return {
          isValid: false,
          message: this.$t('processes.validationErrors.idAlreadyInUse'),
        };
      }
      return {
        isValid: true,
        message: '',
      };
    },
    validateEdit() {
      if (!this.dialogData.processType) {
        return {
          isValid: false,
          message: 'Заполните все поля',
        };
      }
      return {
        isValid: true,
        message: '',
      };
    },
    bpmnSchemaUploadHandler(val) {
      this.dialogData.processName = val.code;
      this.upload.file = val.value;
    },
    validateFileName(value) {
      if (typeof value === 'string') {
        return value === value.match(/^[а-яёЁА-Я\w.]+$/)?.[0];
      } else if (value instanceof File) {
        return value.name === value.name.match(/^[а-яёЁА-Я\w.]+$/)?.[0];
      }
      return true;
    },
    requiredHendler(val) {
      return (!!val && val.length > 0) || 'Поле обязательно для заполнения';
    },
    clearForm() {
      this.upload = {
        file: null,
        loading: false,
      };
      this.dialogData = {
        processName: '',
        processType: '',
      };
    },
  },
};
</script>

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