<template>
  <div v-if="schemaNotEmpty">
    <FormGeneratorWrapper
      ref="formGeneratorWrapper"
      :model="model"
      :schema="schema"
      :hide-nulls="!!hideNulls"
      :mode="mode"
      @update-validation="updateValidation"
    />
  </div>
</template>

<script lang="ts">
// @ts-nocheck
import FormGeneratorWrapper from '@components/common/node-generator/FormGeneratorWrapper.vue';
import mergeSchemas from '@utils/schema-merge';
import setReactive from '@utils/set-reactive';
import { sortByPriority } from '@utils/entities/Schema/prioritySort';
import cloneDeep from 'lodash/cloneDeep';
import isEqual from 'lodash/isEqual';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
import get from 'lodash/get';
import { MetaClassSchemaRaw } from '@devsun/eva-models/dist/models/Schema';
import { notifyError } from '@utils/notify';

const emptySchemaMock = {
  groupList: [],
  attrList: [],
  listAttrs: [],
  labelAttrs: [],
};

export default {
  name: 'ReviewDocumentsHiddenForm',
  components: {
    FormGeneratorWrapper,
  },
  props: [
    'typeObject',
    'form',
    'hideNulls',
    'mode',
    'formDefaults',
    'sub',
    'baseSchema',
  ],
  data() {
    return {
      model: {},
      prevModel: null,
      type: '',
      schema: emptySchemaMock as MetaClassSchemaRaw,
      requiredGroups: ['rejects'], // an array with the names of the groups requiring validation
      requiredFields: null,
      statement: null,
      service: null,
    };
  },
  computed: {
    schemaNotEmpty() {
      return (
        (this.schema.listAttrs && this.schema.listAttrs.length > 0) ||
        (this.schema.groupList && this.schema.groupList.length > 0)
      );
    },
  },
  created() {
    try {
      this.service = cloneDeep(
        this.$store.getters['registryService/services/servicesCard']
      );
      this.statement = cloneDeep(
        this.$store.getters['utils/cards/models'].statements
      );
    } catch (err) {
      console.log(
        '[ReviewDocumentsHiddenForm][created] Could not set statement data from store',
        this.statement,
        { err }
      );
    }

    this.setSchema(this.typeObject, false);
  },
  destroyed() {
    this.cleanDocumentsModel();
  },
  watch: {
    statement: {
      deep: true,
      handler(newStatement) {
        const goal = newStatement?.statement?.goal || '';

        this.model.goal = goal;
      },
    },
    typeObject(val) {
      if (this.type !== val.type) {
        this.setSchema(val);
      }
    },
    model: {
      handler(model) {
        if (isEqual(model, this.prevModel)) return;

        this.prevModel = cloneDeep(model);

        this.$emit('update', this.model);
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    cleanDocumentsModel() {
      const { model } = this;

      for (const value in model) {
        model[value] = void 0;
      }
      this.$emit('update', model);
    },
    setDefaults(schema) {
      const { attrList } = schema;

      if (this.formDefaults && attrList && Array.isArray(attrList)) {
        attrList.forEach((attr) => {
          if (!attr || typeof attr !== 'object') {
            return;
          }

          const defaultValue = get(this.formDefaults, attr.name);
          const statementValue = get(this.statement, attr.name);
          const isNotSetInModel =
            typeof get(this.model, attr.name) === 'undefined';

          if (get(attr, 'props.parent', '') === 'interDepartmentReq') {
            this.setDataFromInterDepartmentReq(attr, attr.name);
            return;
          }

          if (isNotSetInModel && (defaultValue || statementValue)) {
            const value = statementValue || defaultValue;
            setReactive(this.model, attr.name, value);
          }
        });
      }
    },
    async getSchemasFromRegistry() {
      const type = this.type || get(this.typeObject, 'type');

      if (!type) return;

      const serviceDocs = get(this.service, 'documents', []);
      const typeDoc = serviceDocs.find(
        (serviceDoc) => serviceDoc.code === type
      );

      if (!typeDoc) return;

      const schemas = get(typeDoc, 'form');
      const resDocSchemaName = type;
      const goalSchemaNames =
        this.sub && Array.isArray(this.sub)
          ? this.sub.map((goal) => resDocSchemaName + goal)
          : [];
      const allowed = [resDocSchemaName, ...goalSchemaNames];

      const form = get(this.typeObject, 'form', null);

      if (form) {
        return schemas && Array.isArray(schemas)
          ? schemas.filter((schema) => schema.name === form)
          : null;
      } else {
        return schemas && Array.isArray(schemas)
          ? schemas.filter((schema) => allowed.includes(schema.name))
          : null;
      }
    },
    async setSchema(val, resetModel = true) {
      if (val?.type) {
        this.type = val.type;
      } else {
        return;
      }

      if (resetModel) {
        this.cleanDocumentsModel();
      }

      let schemas: unknown[] = await this.getSchemasFromRegistry();
      if (!schemas) {
        /* todo
           releasing it in 2.3.40 - for collecing feedback
           afterwards remove fetchModelByCode call & backend/mock-api/resources/models/ReviewDocumentsHiddenForm
        * */
        notifyError(
          `Используется устаревшее хранилище ЭФ для: ${this.type}`,
          'info',
          'warning'
        );
        const serviceID = get(this.statement, 'system.serviceId');

        console.warn('--------------------------');
        console.warn('--------------------------');
        console.warn(
          '[Review documents hidden form] No form found in service registry for document:',
          get(this.typeObject, 'label'),
          get(this.typeObject, 'type')
        );
        console.warn(
          'You can add a form at this address:',
          `${location.origin}/microws/cards/services/${serviceID}?active=forms&components=index,processes,forms,directories,verifications,documents,interagencies,stages,formModel,digitalRegulations`
        );
        console.warn('--------------------------');
        console.warn('--------------------------');

        const keys = [`ReviewDocumentsHiddenForm_${this.type}`];

        if (Array.isArray(this.sub)) {
          this.sub.forEach((subkey) => keys.push(keys[0] + subkey));
        }

        schemas = await Promise.all(
          keys.map((key) =>
            this.$store
              .dispatch('utils/components/fetchModelByCode', key)
              .catch(() => null)
          )
        );
      }
      schemas.sort(sortByPriority);

      if (!schemas[0]) {
        schemas[0] = emptySchemaMock;
      }

      if (this.baseSchema) {
        schemas.unshift(this.baseSchema);
      }

      const schema = mergeSchemas(schemas);

      this.setDefaults(schema);
      this.schema = schema;
      this.setRequiredFields(schema);

      if (this.type === 'vprAssignResult') {
        const childBlock = get(this.model, 'statement.family.child.childBlock');
        if (childBlock) {
          this.$set(
            this.model,
            'statement.family.child.childBlock',
            childBlock.filter((child) => child.isChildPayment)
          );
        }
      }

      if (this.type === 'FamilyChildSubAssignResult') {
        const relatives = get(this.model, 'relatives');
        if (relatives) {
          this.$set(
            this.model,
            'relatives',
            relatives.filter(
              (child) =>
                child.checkSubsidi === true &&
                child.relation &&
                child.relation.code === 2
            )
          );
        }
      }
      this.model = Object.assign({}, this.form, this.model);
    },
    setRequiredFields(schema) {
      const groupList = get(schema, 'groupList');
      const reqObj = {};

      if (isArray(groupList)) {
        groupList.forEach((item) => {
          if (this.requiredGroups.includes(get(item, 'name'))) {
            // this.requiredFields = get(item,'attrList') //TODO: изменить, т.к. перезаписывается, а не добавляется requiredFields
            const reqAttrs = get(item, 'attrList').map((item) => ({
              name: item,
              value: false,
            }));

            reqObj[get(item, 'name')] = {
              valid: false,
              attrs: reqAttrs,
            };
          }
        });
        this.requiredFields = isEmpty(reqObj) ? null : reqObj;
        this.$emit('update', this.model);
      }
    },
    generateResolutionDocFields() {
      const checkCondition = (condition) => {
        if (condition.type === 'eq') {
          return condition.value === get(this.statement, condition.field);
        }
        return true;
      };
      const generatedFields = {};
      const processField = (field) => {
        if (field.fieldValue.type === 'literal') {
          generatedFields[field.fieldName] = field.fieldValue.value;
        }
        if (field.fieldValue.type === 'dictionary') {
          const dict = this.$store.getters[
            'registryService/referenceBooks/referenceBooks'
          ][field.fieldValue.dictionary];
          const val = get(this.statement, field.fieldValue.field);
          generatedFields[field.fieldName] = get(dict, [val, 'value']);
        }
        if (field.fieldValue.type === 'docList') {
          generatedFields[field.fieldName] = (
            get(this.statement, 'documents') || []
          ).filter((el) => el.source === 'Applicant');
        }
        if (field.fieldValue.type === 'hasReject') {
          const val = field.fieldValue.rejectCodes.some(
            (code) => this.model[code] === true
          );
          generatedFields[field.fieldName] = val;
        }
      };

      return this.$store
        .dispatch('utils/components/fetchGeneratedFieldsByCode', this.type)
        .then((fields) => {
          fields
            .filter((f) => f.conditions.every(checkCondition))
            .forEach(processField);
          return generatedFields;
        });
    },
    /**
     * Set value from interDepartmentReq
     * @param attr {Object} - attr from schema attrList
     * @param attrName {String} - attr name
     */
    setDataFromInterDepartmentReq(attr, attrName) {
      const values = [];
      const mzClass = get(attr, 'props.class', '');
      const mzAttrs = get(attr, 'props.attrs', []);
      const mzObj =
        get(this, 'statement.interDepartmentReq', []).filter((item) => {
          return item.name === mzClass;
        })[0] || {};
      mzAttrs.forEach((a) => {
        values.push(get(mzObj, `${a}`, ''));
      });
      const value = values.join(', ');
      this.$set(this.model, attrName, value);
    },
    triggerValidation() {
      if (this.$refs.formGeneratorWrapper) {
        this.$refs.formGeneratorWrapper.triggerValidate();
      }
    },
    updateValidation(isValid: boolean): void {
      this.$emit('update-validation', isValid);
    },
  },
};
</script>
