<template>
  <q-dialog v-model="open" @hide="clearModel" :persistent="saving">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-form class="full-width no-shadow q-py-md" @submit="submit()">
        <div class="text-h6 q-px-md">
          {{ $t('administration.startProcess.title') }}
        </div>
        <q-card-section class="q-gutter-y-md">
          <q-select
            v-model="selectedApplication"
            :options="massApplicationList"
            emit-value
            :rules="[requiredHendler]"
            map-options
            :label="$t('administration.startProcess.application')"
            filled
          />
          <BaseAutocompleteSelect
            :model.sync="organizations"
            :async-getter="getOrganizations"
            :rules="[(val) => val || 'Поле обязательно для заполнения']"
            v-if="selectedApplication === 'MassRouteApplicationProcess'"
            :field-label="$t('administration.startProcess.searchOrganization')"
            label-value="fullname"
            @value="setOrganizations"
          />

          <q-select
            filled
            v-model="status"
            :rules="[requiredHendler]"
            :options="statusList"
            v-if="selectedApplication === 'MassApplicationReset'"
            label="system.status.system"
            emit-value
            map-options
            stack-label
          />

          <q-select
            filled
            v-model="statusExternal"
            :rules="[requiredHendler]"
            :options="statusTypes"
            v-if="selectedApplication === 'MassApplicationReset'"
            label="system.status.external"
            emit-value
            map-options
            stack-label
          />

          <q-select
            filled
            v-model="statusInternal"
            :options="statusList"
            :rules="[requiredHendler]"
            v-if="selectedApplication === 'MassApplicationReset'"
            label="system.status.internal"
            emit-value
            map-options
            stack-label
          />
          <q-checkbox
            v-model="forceSend"
            v-if="selectedApplication === 'MassApplicationHide'"
            label="forceSend"
          />
          <q-file
            filled
            :accept="
              selectedApplication === 'MassApplicationImport' ? '.zip' : '.csv'
            "
            :rules="[() => uploadedFile || 'Поле обязательно для заполнения']"
            v-model="uploadedFile"
            :label="
              selectedApplication === 'MassApplicationImport'
                ? $t('administration.startProcess.uploadZip')
                : $t('administration.startProcess.upload')
            "
          />
        </q-card-section>
        <q-card-actions>
          <q-btn
            type="submit"
            :loading="saving"
            :label="$t('administration.start')"
            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, PropSync, Vue } from 'vue-property-decorator';
import { QSelectOption } from '@models/models-ui';
import { notifyError, notifySuccess } from '@utils/notify';
import { ImporterApiHelper } from '@services/importer-service';
import get from 'lodash/get';
import map from 'lodash/map';
import { startWithFiles } from '@services/wf';

const importerService = new ImporterApiHelper();

@Component({})
export default class StartProcessDialog extends Vue {
  @PropSync('openFormDialog') open: boolean;

  private selectedApplication = '';

  private saving = false;

  private forceSend = false;

  private status = '';

  private statusExternal = '';

  private statusInternal = '';

  private organizationName = '';

  private organizationId = '';

  private uploadedFile: File | null = null;

  private massApplicationList: QSelectOption[] = [
    {
      label: 'Маршутизация заявлений',
      value: 'MassRouteApplicationProcess',
    },
    {
      label: 'Изменение статуса заявлений',
      value: 'MassApplicationReset',
    },
    {
      label: 'Удаление заявления',
      value: 'MassApplicationHide',
    },
    {
      label: 'Переотправка заявления',
      value: 'MassApplicationResend',
    },
    {
      label: 'Импорт данных о ранних сроках беременности в реестр',
      value: 'MassApplicationImport',
    },
  ];

  private statusTypes: QSelectOption[] = [
    {
      label: 'Заявление зарегистрировано',
      value: '1',
    },
    {
      label: 'Услуга оказана',
      value: '3',
    },
    {
      label: 'Отказано в предоставлении услуги',
      value: '4',
    },
    {
      label: 'Заявление принято к рассмотрению',
      value: '6',
    },
    {
      label: 'Промежуточные результаты по заявлению',
      value: '7',
    },
    {
      label: 'Заявление требует исправления',
      value: '15',
    },
  ];

  private organizations = {
    pageSize: 20,
    lastPage: 0,
    nextPage: 1,
    search: '',
    records: [],
    selected: null,
    loading: false,
    coolDown: false,
  };

  private get statusList() {
    return map(
      this.$store.getters['registryService/referenceBooks/referenceBooks']
        .gpzu_2_application_status || {},
      (label, value) => ({ value, label: label.description })
    );
  }

  private getOrganizations() {
    return new Promise((resolve) => {
      this.organizations.loading = true;
      const arrQuery = [
        this.organizations.search
          ? `(fullname=searchphrase='${this.organizations.search}' or inn=searchphrase='${this.organizations.search}' or ogrn=searchphrase='${this.organizations.search}')`
          : null,
      ];
      const currentQuery = arrQuery.filter((filter) => !!filter).join(' and ');

      this.$store
        .dispatch('idm/organizations/dispatchOrganizations', {
          page: this.organizations.nextPage,
          perPage: this.organizations.pageSize,
          fulltext: currentQuery,
          handler: 'managed',
        })
        .then((data) => {
          resolve(data);
        });
    });
  }

  cancelSave(): void {
    this.open = false;
  }

  async created(): Promise<void> {
    await this.$store.dispatch(
      'registryService/referenceBooks/initReferenceBooks',
      [
        {
          force: true,
          id: 'gpzu_2_application_status',
        },
      ]
    );
  }

  private requiredHendler(val: string): boolean | string {
    return (!!val && val.length > 0) || 'Поле обязательно для заполнения';
  }

  private submit(): void {
    const data: any = {};
    this.saving = true;
    if (this.selectedApplication === 'MassApplicationImport') {
      const uploadedFile = this.uploadedFile || '';
      const blob = new Blob([uploadedFile]);
      const file = new File([blob], 'file');
      const formData = new FormData();
      formData.append('file', file);
      importerService
        .postFile(formData)
        .then(() => {
          notifySuccess('Архив загружен');
          this.saving = false;
          this.clearModel();
        })
        .catch((e: any) => {
          notifyError(e.message.toString());
        });
    } else {
      switch (this.selectedApplication) {
        case 'MassRouteApplicationProcess':
          data.departmentId = this.organizationId;
          data.departmentName = this.organizationName;
          break;
        case 'MassApplicationReset':
          data.status = {
            internal: this.statusInternal,
            external: this.statusExternal,
            system: this.status,
          };
          break;
        case 'MassApplicationHide':
          data.forceSend = this.forceSend;
          break;
      }

      if (this.uploadedFile) {
        startWithFiles({
          file: this.uploadedFile,
          json: {
            userId: this.$store.getters['oidcClient/currentUser'].sub,
            processKey: this.selectedApplication,
            data,
          },
        }).then(({ data: { msg = '' } }) => {
          const traceIdMatch = msg.match(/traceId=[a-zA-Z0-9-]+/);
          let traceId = '';
          if (traceIdMatch) {
            traceId = traceIdMatch[0].slice(8);
          }
          const handler = (e: any) => {
            const data = JSON.parse(get(e, 'data', '{}'));
            if (data.traceId === traceId) {
              if (data.body?.success) {
                notifySuccess('Процесс успешно запущен');
              }
              this.$websockets.removeListener(handler);
            }
          };
          this.$websockets.addListener(handler);
          this.saving = false;
          this.clearModel();
        });
      }
    }
  }

  clearModel(): void {
    this.forceSend = false;
    this.selectedApplication = '';
    this.status = '';
    this.statusExternal = '';
    this.statusInternal = '';
    this.organizationName = '';
    this.organizationId = '';
    this.uploadedFile = null;
    this.open = false;
  }

  setOrganizations(val: any): void {
    if (val) {
      this.organizationName = val.fullname || '';
      this.organizationId = val.id || '';
    } else {
      this.organizationName = '';
    }
  }
}
</script>
