<template>
  <q-dialog v-model="dialog" :persistent="loading">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-inner-loading :showing="loadingSchema">
        <q-spinner-gears color="primary" size="50px" />
      </q-inner-loading>
      <q-form v-if="!loadingSchema" @submit="create">
        <h2 class="text-h5 q-px-md q-mb-none">
          {{ $t('registries.createFormTitle') }}
        </h2>
        <q-card-section>
          <FormGeneratorWrapper
            :model="model"
            :schema="schema"
            mode="create"
            :padded-groups="true"
            class="q-my-md"
          />
        </q-card-section>
        <q-card-actions align="right" class="q-px-md">
          <q-btn
            type="submit"
            :loading="loading"
            :label="$t('registries.createBtnLabel')"
            icon="create"
            color="primary"
          >
            <template #loading>
              <q-spinner-gears />
            </template>
          </q-btn>
        </q-card-actions>
      </q-form>
    </q-card>
  </q-dialog>
</template>

<script lang="ts">
import { Component, Prop, PropSync, Vue, Watch } from 'vue-property-decorator';
import FormGeneratorWrapper from '@components/common/node-generator/FormGeneratorWrapper.vue';
import mergeSchemas from '@utils/schema-merge';
import createView from '@utils/registry-view-generator';
import { MetaClassSchemaRaw } from '@devsun/eva-models/dist/models/Schema';
import { DocumentApi } from '@openapi/registry-data';
import {
  Registry,
  RegistryMapping,
  RegistryMappingApi,
  Service,
} from '@openapi/registry-service';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import { notifyError } from '@utils/notify';

const ACCREDITATION_CODE = 'RegistryAccreditation';
const ACCREDITATION_STATUS_DICT = 'accreditation_it_1_0_1__application_status';
const ACCREDITATION_DEPARTMENT_ID = 'f7861971-8777-4703-be9f-93a8c911644a';
const ACCREDITATION_DEPARTMENT =
  'МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ';

@Component({
  components: {
    FormGeneratorWrapper,
  },
})
export default class CreateRegistryItem extends Vue {
  @PropSync('open') dialog?: boolean;
  @Prop() registry!: Registry;
  private loading = false;
  private loadingSchema = true;

  model = {
    serviceFullName: this.registry.description,
    Goal: '',
    departmentFullName: '',
    orderId: '',
    finishDate: '',
    applicationSystem: {
      startDate: '',
    },
    status: {
      internal: '',
    },
    entityStatus: '',
    document: {
      number: '',
      resAuthDepName: '',
      type: {
        code: '',
      },
    },
    departmentId: this.$store.getters['oidcClient/currentUser'].domain_id,
    assigneeId: this.$store.getters['oidcClient/currentUser'].sub,
  };

  commonSchema = {};

  service: Service;
  registryMapping: RegistryMapping;

  get isCustomForm(): boolean {
    return get(this.registry, 'isCustomForm', true);
  }

  get schema() {
    return mergeSchemas([this.commonSchemaPatched, this.dataSchema]);
  }

  get commonSchemaPatched() {
    if (!this.service) {
      return {};
    }
    const schema = cloneDeep(this.commonSchema);
    // @ts-ignore todo OPENAPI
    const goalsList = this.service.goalsList || [];
    const goal = parseInt(this.model.Goal, 10);
    const resultDocs = this.filterDocsByGoal(
      goal,
      this.registryMapping.resultCodes
    ).map((code) => ({
      code: code,
      label:
        // @ts-ignore todo expanded interface
        this.service?.documents?.find((doc) => doc.code === code)?.name || code,
    }));
    // TODO: TS.
    // this.addGoalAndResultDoc(schema, goalsList, resultDocs);
    this.addGoalAndResultDoc(schema, goalsList as any, resultDocs);
    return schema;
  }

  filterDocsByGoal(goal: number, docCodes: string[]): string[] {
    if (isNaN(goal)) {
      return docCodes;
    }
    const findDocInStages = (docCode: string) =>
      // @ts-ignore todo OPENAPI
      (this.service?.stages || [])
        .flatMap((st: any) => [
          ...(st?.documents?.apply || []),
          ...(st?.documents?.reject || []),
        ])
        .find(
          (doc: any) =>
            doc === docCode ||
            (doc.code === docCode && (!doc.goal || doc.goal.includes(goal)))
        );

    return docCodes.filter((d) => findDocInStages(d));
  }

  addGoalAndResultDoc(common: any, goalsList: any[], resultDocs: any[]): void {
    const goalInput = this.makeGoalInput(goalsList);
    const resDocInput = this.makeResultDocInput(resultDocs);

    common.attrList.push(goalInput);
    common.attrList.push(resDocInput);
    common.groupList[0].attrList.splice(2, 0, goalInput.name);
    common.groupList[0].attrList.splice(3, 0, resDocInput.name);
  }

  makeResultDocInput(resultDocs: any[]) {
    return {
      label: 'Результат оказания услуги',
      name: 'document.type.code',
      type: 'string',
      view: 'select',
      enum: resultDocs.map((d) => ({ key: d.code, value: d.label })),
      previewHidden: false,
      editHidden: false,
      editReadOnly: false,
      createHidden: false,
      createReadOnly: false,
      editRequired: true,
      createRequired: true,
    };
  }

  makeGoalInput(goalsList: any[]) {
    return {
      label: 'Цель',
      name: 'Goal',
      type: 'string',
      view: 'select',
      enum: goalsList.map((g) => ({ key: g.value, value: g.label })),
      previewHidden: false,
      editHidden: false,
      editReadOnly: false,
      createHidden: false,
      createReadOnly: false,
      editRequired: true,
      createRequired: true,
    };
  }

  @Watch('model.document.resRegStatus')
  async accreditationStatusHandler(value: string) {
    if (this.registry.code === ACCREDITATION_CODE) {
      const code = this.$store.getters[
        'registryService/referenceBooks/getCodeInBookByValue'
      ]({
        book: ACCREDITATION_STATUS_DICT,
        valueName: 'description',
        value,
      });
      if (code) {
        this.model.entityStatus = code;
      }
    }
  }

  get dataSchema() {
    // @ts-ignore todo registry.form OPENAPI
    if (this.isCustomForm && this.registry.form) {
      // @ts-ignore todo registry.form OPENAPI
      return this.registry.form;
    } else {
      const docCode = this.model.document.type.code;
      const goal = parseInt(this.model.Goal, 10);
      const document = cloneDeep(
        // @ts-ignore todo expanded interface
        this.service?.documents?.find((d: any) => d.code === docCode)
      );

      if (!document) {
        return {};
      }

      // @ts-ignore todo OPENAPI
      const formCode = (this.service?.stages || [])
        .flatMap((st: any) => [
          ...(st?.documents?.apply || []),
          ...(st?.documents?.reject || []),
        ])
        .filter((doc: any) => doc.code && doc.form && doc.goal)
        .find((doc: any) => doc.goal.includes(goal) && doc.code === docCode)
        ?.form;

      if (formCode) {
        document.form = (document.form || []).filter(
          (form: any) => form.name === formCode
        );
      }

      return createView([document]) as MetaClassSchemaRaw;
    }
  }

  async created() {
    await this.fetchCommonSchema();
    // @ts-ignore todo registry.form OPENAPI

    await new RegistryMappingApi()
      .pagingRegistryMapping(
        undefined,
        undefined,
        `registryCode==${this.registry.code}`
      )
      .then(({ data }) => {
        if (data.records && data.records[0])
          this.registryMapping = data.records[0];
      });

    if (!this.registryMapping) {
      notifyError('Реестр не найден');
      this.loadingSchema = false;
      return;
    }

    await this.$store
      .dispatch('registryService/services/getServiceMeta', {
        id: this.registryMapping?.serviceId,
        opts: {
          expand: ['documents', 'documents.form'],
        },
      })
      .then((data) => {
        this.service = data;
      });

    this.loadingSchema = false;

    if (this.registry.code === ACCREDITATION_CODE) {
      this.model.departmentId = ACCREDITATION_DEPARTMENT_ID;
      this.model.document.resAuthDepName = this.model.departmentFullName = ACCREDITATION_DEPARTMENT;
    } else {
      const organization = await this.$store.dispatch(
        'idm/organizations/getOrganization',
        { id: this.model.departmentId }
      );

      this.model.departmentId = organization.id;
      this.model.document.resAuthDepName = this.model.departmentFullName =
        organization.fullname;
    }
  }

  create() {
    this.loading = true;

    const formattedModel: any = this.model;
    formattedModel.Goal = +this.model.Goal;
    formattedModel.applicationSystem.serviceId = this.service?.id;
    const documentApi = new DocumentApi();
    documentApi
      .createDocument(this.registry.code, [formattedModel])
      .finally(() => {
        this.loading = false;
        this.dialog = false;
        setTimeout(() => {
          this.$emit('create');
        }, 1000);
      });
  }

  fetchCommonSchema() {
    return this.$store
      .dispatch('utils/components/fetchModelByCode', 'registries_common')
      .then((schema) => {
        this.commonSchema = schema;
      })
      .catch(() => {
        notifyError(this.$t('registries.errorLoadingModel') as string);
      });
  }
}
</script>
