<template>
  <div :class="{ invisible: hidden }">
    <slot name="button" v-bind="{ open, label }">
      <r-btn
        dense
        negative
        :disable="disable"
        label="Редактировать"
        @click="open"
        no-wrap
      />
    </slot>
    <operation-dialog
      persistent
      ref="dialog"
      :title="title"
      :sub="model.reason"
      :process-key="processKey"
      v-model="opened"
      @hide="close"
    >
      <div class="RejectApplication-Form">
        <div class="RejectApplication-FormLine">
          <data-block
            :formData="{
              label: 'Тип документа',
              value: getRejectDocumentType(model.reasonCode),
            }"
          />
        </div>
        <div class="RejectApplication-FormLine">
          <data-block
            :formData="{
              label: 'Дата',
              value: getNowDate(),
            }"
          />
        </div>
        <div class="RejectApplication-FormLine">
          <r-select
            placeholder="Причина отказа"
            :options="rejectTypes"
            v-model="rejectType"
            disable
          />
        </div>
        <r-textarea
          label="Комментарий на доработку"
          v-model="additionalRejectInfo"
        />
      </div>
      <template #process>
        <result-block type="info" header="Решение редактируется">
          {{ fileName }}
        </result-block>
      </template>
      <template #result>
        <result-block :type="resultType" :header="resultMessage">
          {{ fileName }}
        </result-block>
      </template>
      <template #right-actions>
        <r-btn
          action
          label="Редактировать"
          icon="pgs-edit"
          :disable="disable"
          @click="startProcess"
        />
      </template>
      <template #right-actions-result>
        <r-btn
          action
          label="Продолжить"
          icon-right="pgs-shevron-right-off"
          @click="finish"
        />
      </template>
    </operation-dialog>
  </div>
</template>

<script lang="ts">
import { Component, Mixins, Prop, Ref } from 'vue-property-decorator';
import DataBlock from '@components/cards/statements/components/dataBlock.vue';
import OperationDialog from '@/components/common/operation-dialog/index.vue';
import { notifyError } from '@/utils/notify';
import CryptoProSignForm from '@/components/common/cryptopro-sign-form/index.vue';
import RSelect from '@/recruits/components/common/r-select.vue';
import RInput from '@/recruits/components/common/r-input.vue';
import RTextarea from '@/recruits/components/common/r-textarea.vue';
import moment from 'moment/moment';
import { formatDate } from '@/recruits/utils';
import ProcessStarter from '@mixins/ProcessStarter';

interface FileInfo {
  fileName: string;
  fileSize: number;
  file: File;
  fileExt: string;
}

type FormModel = Record<string | symbol, unknown>;

interface ModelData extends FormModel {
  comment: string;
  file: File | null;
}

// FIXME: Временное решение, для реализации окна
// (в дальнейшем планируется вынос в
// отдельный nsi сервис для ЕРВУ
const reasonRejectDocument: {
  [key: string]: { label: string; code: string };
} = {
  militaryReg: {
    label: 'Решение об отказе в постановке на воинский учёт',
    code: 'ResultNotificationRegistrationRefuse',
  },
  deregister: {
    label: 'Решение об отказе в снятии с воинского учёта',
    code: 'ResultNotificationDeregistrationRefuse',
  },
  changeVK: {
    label: 'Решение об отказе в смене военного комиссариата',
    code: 'ResultChangeMilitaryOfficeRefuse',
  },
};

@Component({
  components: {
    RSelect,
    RInput,
    RTextarea,
    DataBlock,
    OperationDialog,
    CryptoProSignForm,
  },
  methods: {
    moment,
  },
})
export default class EditApplication extends Mixins(ProcessStarter) {
  @Prop({ default: false })
  hidden: boolean;

  @Prop({ default: () => ({}) })
  declare model: any;

  @Prop({ default: () => false })
  disable: boolean;

  @Prop(String) readonly label: string;

  @Prop(String) readonly personId: string;

  @Ref('dialog') operationDialog: OperationDialog;

  opened = false;
  files: FileInfo[] = [];

  rejectTypes: { label: string; value: string; description: string }[] = [
    {
      label: 'отсутствуют основания для постановки на воинский учёт',
      value: 'militaryReg',
      description: 'militaryRegRefusal',
    },
    {
      label: 'отсутствуют основания для снятия с воинского учёта',
      value: 'deregister',
      description: 'deregisterRefusal',
    },
    {
      label: 'отсутствуют основания для смены военного комиссариата',
      value: 'changeVK',
      description: 'changeVKRefusal',
    },
  ];

  formModel: ModelData | null = null;
  loading = false;
  isErrorSign = false;
  privateRejectType: { label: string; value: string; description: string } = {
    label: '',
    value: '',
    description: '',
  };

  get rejectType(): { label: string; value: string; description: string } {
    const rejectType = this.rejectTypes.filter(
      (rejectType) => rejectType.value === this.model.reasonCode
    );
    const rejectTypeDefault = rejectType.length
      ? rejectType[0]
      : { label: '', value: '', description: '' };
    return this.privateRejectType?.value
      ? this.privateRejectType
      : rejectTypeDefault;
  }

  set rejectType(type: { label: string; value: string; description: string }) {
    this.privateRejectType = type;
  }

  privateAdditionalRejectInfo = '';

  get additionalRejectInfo(): string {
    const defaultAdditionalRejectInfo = this.model.returnText || '';
    return this.privateAdditionalRejectInfo
      ? this.privateAdditionalRejectInfo
      : defaultAdditionalRejectInfo;
  }

  set additionalRejectInfo(text: string) {
    this.privateAdditionalRejectInfo = text;
  }

  get fileName(): string {
    return this.formModel?.file?.name || '';
  }

  get resultMessage(): string {
    return this.isErrorSign ? 'Произошла ошибка' : 'Решение отредактировано';
  }

  get resultType(): string {
    return this.isErrorSign ? 'negative' : 'positive';
  }

  get title(): string {
    return `Редактирование решения об отказе по заявлению № ${this.model.number}`;
  }

  getRejectDocumentType(reasonCode: string): string {
    return reasonRejectDocument[reasonCode]?.label || '';
  }

  getNowDate(): string {
    return formatDate(new Date().toString());
  }

  // @ts-ignore
  async startProcess(): Promise<void> {
    if (!this.model.reasonCode) {
      notifyError('Не удалось определить тип документа');
      return;
    }
    if (!this.rejectType.value) {
      notifyError('Не выбрана причина отклонения');
      return;
    }
    if (!this.additionalRejectInfo) {
      notifyError('Не заполнено поле дополнительная информация');
      return;
    }
    this.operationDialog.toProcess();
    try {
      this.loading = true;
      const { traceId } = await this.$store.dispatch(
        'wfActions/processes/dispatchProcess',
        {
          processKey: 'milBaseRouteProcess',
          data: {
            personIds: [this.personId],
            applicationsId: [this.model.id],
            actionType: 'editApplicationReject',
            reasonCode: this.model.reasonCode,
            refusalCode: this.rejectType?.description || '',
            refusalText: this.rejectType?.label || '',
            additionalInfo: this.additionalRejectInfo,
          },
        }
      );

      this.registerListener((message, removeListener) => {
        if (traceId !== message.traceId) return;
        if (message.body.type === 'finish') {
          this.operationDialog.toResult();
          this.loading = false;
          this.finish();
          removeListener();
        }
      });
    } catch (error) {
      if (error instanceof Error) notifyError(error.message);
      this.showResult(true);
    }
  }

  showResult(isError = false): void {
    this.isErrorSign = isError;
    this.operationDialog.toResult();
  }

  finish(): void {
    this.close();
    this.$emit('done');
  }

  open(): void {
    if (this.disable) return;
    this.files = [];
    this.formModel = {
      comment: '',
      file: null,
    };
    this.opened = true;
  }

  close(): void {
    this.$emit('close');
    this.rejectType = { label: '', value: '', description: '' };
    this.opened = false;
  }
}
</script>

<style lang="scss">
.RejectApplication {
  &-Form {
    display: flex;
    flex-direction: column;
  }
  &-FormLine {
    &:not(:last-child) {
      margin-bottom: 4px;
    }
  }
}
</style>
