<template>
  <div class="SingleSign">
    <r-btn
      :disable="disable"
      :label="label"
      dense
      icon="pgs-sign"
      no-wrap
      positive
      @click="open"
    >
      <!--TODO Вынести в отдельный компонент-->
      <q-tooltip anchor="bottom middle">
        <div class="SignTooltip">
          {{ file.s3Name }}
        </div>
      </q-tooltip>
    </r-btn>
    <operation-dialog
      ref="dialog"
      v-model="opened"
      :sub="sub"
      :title="titleWindow"
      persistent
      sign
      @hide="close"
      :show-close-on="['start']"
    >
      <!--TODO Вынести в отдельный компонент-->
      <div class="SingleSign__Recruits">
        <div class="SignRecruit">
          <div class="SignRecruit__Documents">
            <div class="SignRecruit__Document">
              <q-icon
                class="SignRecruit__DocumentIcon"
                name="pgs-document"
                size="18px"
              />
              <span class="SignRecruit__DocumentName">
                {{ file.s3Name }}
              </span>
              <span style="flex: 1 1 auto"></span>
              <base-preview
                v-if="file.format && file.s3url"
                :extension="file.format"
                :s3Url="file.s3url"
              >
                <q-icon class="SignRecruit__TableIcon" name="pgs-view">
                  <q-tooltip>Предпросмотр</q-tooltip>
                </q-icon>
              </base-preview>
            </div>
          </div>
        </div>
      </div>
      <r-input
        v-if="flagCancelButton"
        v-model="cancelComment"
        label="Комментарий"
      />
      <template #process>
        <result-block :header="processMessage" icon="pgs-sign" type="info">
          <TransitionGroup name="results" tag="div">
            <div v-for="res in resultList" :key="res.id">
              <q-icon color="info" name="pgs-sign-2" size="sm" />
              <span>{{ get(res, 'fullName') }}</span>
            </div>
          </TransitionGroup>
        </result-block>
      </template>
      <template #result>
        <result-block
          :header="resultMessage"
          :type="hasError ? 'negative' : 'positive'"
        >
          <div class="results">
            <div v-for="res in resultList" :key="res.id">
              <q-icon color="positive" name="pgs-check" size="sm" />
              <span>{{ get(res, 'fullName') }}</span>
            </div>
          </div>
        </result-block>
      </template>
      <template #right-actions>
        <r-btn
          v-if="needCancelButton && !flagCancelButton"
          icon="pgs-close"
          label="Отклонить"
          negative
          @click="openRejectModal()"
        >
        </r-btn>
        <r-btn
          v-if="!flagCancelButton"
          :disable="disable || !certificateIsActive"
          action
          icon="pgs-sign"
          label="Подписать"
          @click="action"
        />
        <r-btn
          v-if="flagCancelButton"
          :disable="disable"
          action
          icon="pgs-check"
          label="Продолжить"
          @click="action"
        />
      </template>
      <template
        v-if="operationDialog && operationDialog.formState === 'start'"
        #left-actions-panel
      >
        <r-btn
          color="primary"
          icon="pgs-close"
          label="Отмена"
          outline
          @click="closeModal"
        />
      </template>
      <template #right-actions-result>
        <r-btn
          action
          icon-right="pgs-shevron-right-off"
          label="Продолжить"
          @click="finish"
        />
      </template>
      <template v-if="!flagCancelButton" #sign-form>
        <crypto-pro-sign-form
          ref="signForm"
          process-key="milBaseMassSignProcess"
          :enable-submit-form="!model.signEntity"
          :task-process="taskProcess"
          :user-task="userTask"
          bucket="ervu-attachment"
          class="no-right-border-radius"
          @error="onError"
          @finish="onFinish"
          @signed="onSigned"
          @update:certificateIsActive="certificateIsActive = $event"
        />
      </template>
    </operation-dialog>
  </div>
</template>

<i18n>
{
  "ru": {
    "SingleSign": {
      "selected": "не выбрано | {n} документ | {n} документа | {n} документов",
      "signing": " | Документ подписывается | Документы подписываются | Документы подписываются",
      "signed": " | Документ подписан | Документы подписаны | Документы подписаны",
      "error": " | Документ не подписан | Документы не подписаны | Документы не подписаны"
    },
    "SingleReject": {
      "selected": "не выбрано | {n} документ | {n} документа | {n} документов",
      "rejecting": " | Документ отклоняется | Документы отклоняются | Документы отклоняются",
      "rejected": " | Документ отклонен | Документы отклонены | Документы отклонены",
      "error": " | Документ не отклонен | Документы не отклонены | Документы не отклонены"
    }
  }
}
</i18n>

<style lang="scss" scoped>
.SingleSign {
  &__Recruits {
    display: flex;
    flex-flow: column;
  }
}

.SignTooltip {
  margin-bottom: 8px;

  &:last-child {
    margin-bottom: 0;
  }

  &__Name {
    margin-bottom: 2px;
    font-weight: 500;
  }
}

.SignRecruit {
  background: #ffffff;
  border-bottom: 1px solid rgba(1, 72, 116, 0.11);
  box-shadow: none;
  padding: 8px 0;

  &__Name {
    font-weight: bold;
  }

  &__Documents {
    display: flex;
    flex-flow: column;
  }

  &__Document {
    display: flex;
    flex-flow: row;
    align-items: center;
  }

  &__DocumentName,
  &__DocumentIcon {
    color: #6c7276;
  }

  &__DocumentIcon {
    transform: translateX(-2px);
  }

  &__TableIcon {
    overflow: hidden;
    color: #1491cf;
    font-size: 26px;
    padding: 6px 3px;
    cursor: pointer;
  }
}

.results-enter-active,
.results-leave-active {
  transition: all 0.5s ease;
}

.results-enter-from,
.results-leave-to {
  opacity: 0;
  transform: translateY(-30px);
}
</style>

<script lang="ts">
import { Component, Mixins, Prop, Ref } from 'vue-property-decorator';
import dataBlock from '@components/cards/statements/components/dataBlock.vue';
import TaskButton from '@/mixins/TaskButton';
import OperationDialog from '@/components/common/operation-dialog/index.vue';
import CryptoProSignForm from '@/components/common/cryptopro-sign-form/index.vue';
import {
  RecruitV3,
  S3File,
  SignEntity,
} from '@/recruits/openapi/person-registry';
import { MilitaryCommissarDecisions } from '@/recruits/openapi/decision-document';
import get from 'lodash/get';
import { SignData } from '@/mixins/CriptoProPlugin';
import isEmpty from 'lodash/isEmpty';
import RInput from '@/recruits/components/common/r-input.vue';
import { notifyError } from '@utils/notify';
import { convertDateFromBackendFormat, DateFormat } from '@utils/format-date';
import { DataForRecruit } from '@/recruits/components/recruit-card/masthead/interfaces';
import ProcessStarter from '@/mixins/ProcessStarter';

type PersonInfo = {
  id: string;
  fullName: string;
};

interface Entity {
  id?: SignEntity['id'];
  recruitId?: SignEntity['recruitId'];
  type?: SignEntity['type'];
  rejectComment?: string;
}

interface FormModel {
  entityList: Entity[];
  signDate: string | null;
}

interface RecruitWithAttachments extends RecruitV3 {
  attachedDecisions: MilitaryCommissarDecisions[];
}

@Component({
  components: {
    dataBlock,
    CryptoProSignForm,
    RInput,
  },
  methods: {
    get,
  },
})
export default class SingleSign extends Mixins(TaskButton, ProcessStarter) {
  get: typeof get;

  @Prop({ default: () => ({}) }) declare readonly model: DataForRecruit;
  @Prop({ default: 'milBaseMassDecisionRejectProcess' })
  declare processKey: string;

  @Ref('dialog') operationDialog: OperationDialog;
  @Ref('signForm') signForm: CryptoProSignForm;

  opened = false;
  certificateIsActive = false;
  hasError = false;
  resultList: PersonInfo[] = [];
  recruits: RecruitWithAttachments[] = [];
  flagCancelButton = false;
  cancelComment = '';

  get processMessage(): string {
    return this.flagCancelButton
      ? this.$tc('SingleReject.rejecting', this.length)
      : this.$tc('SingleSign.signing', this.length);
  }

  get resultMessage(): string {
    if (this.hasError) {
      return this.flagCancelButton
        ? this.$tc('SingleReject.error', this.length)
        : this.$tc('SingleSign.error', this.length);
    }
    return this.flagCancelButton
      ? this.$tc('SingleReject.rejected', this.length)
      : this.$tc('SingleSign.signed', this.length);
  }

  get length(): number {
    return this.personIds?.length;
  }

  get sub(): string {
    return this.model.mainInfo?.fullName || '';
  }

  get personIds(): string[] {
    return [this.model.id];
  }

  get formModel(): FormModel {
    const signDate = convertDateFromBackendFormat(
      Date.now(),
      DateFormat.backend
    );
    const { id, type, recruitId } = this.model.signEntity || {};
    return {
      entityList: [{ id, type, recruitId, rejectComment: this.cancelComment }],
      signDate,
    };
  }

  get needCancelButton(): boolean {
    return !!this.model.signEntity?.rejectEnable;
  }

  get titleWindow(): string {
    return this.flagCancelButton ? 'Отклонение' : 'Подписание';
  }

  get file(): S3File {
    return {
      s3Name: '',
      s3url: '',
      format: '',
      ...this.model.signEntity?.file,
    };
  }

  async action(): Promise<boolean | void> {
    if (this.flagCancelButton && !this.cancelComment) {
      notifyError('Поле комментарий обязательно к заполнению');
      return false;
    }

    this.operationDialog.toProcess();

    if (this.flagCancelButton) {
      this.emitOnBeforeActionWitchExtraInfo('register_reject_form');

      try {
        const traceId = await this.startProcess(
          (this.formModel as unknown) as Record<string | symbol, unknown>
        );

        this.registerListener((message, removeListener) => {
          if (traceId !== message.traceId) return;
          if (message.body.type === 'finish') {
            this.operationDialog.toResult();
            removeListener();
          }
        });
      } catch (error: any) {
        this.operationDialog.reset();
        notifyError(error.message);
        console.error(error);
      }
    } else {
      this.emitOnBeforeActionWitchExtraInfo('register_sign_result');

      try {
        await this.signForm.sendDataForSign(
          (this.formModel as unknown) as Record<string | symbol, unknown>
        );
      } catch (error: any) {
        this.operationDialog.reset();
        notifyError(error.message);
        console.error(error);
      }
    }
  }

  onSigned(data: SignData): void {
    const personInfo: PersonInfo = {
      id: data.operationInfo?.recruitId,
      fullName: data.operationInfo?.recruitFullName,
    };
    if (!isEmpty(personInfo)) this.resultList.push(personInfo);
  }

  emitOnBeforeActionWitchExtraInfo(codeButton: string): void {
    const journalInfo =
      this.$store.getters[
        'ervuDictionaries/recruitStatusJournalEventDictionary'
      ]?.[this.model.status] || '';
    this.$emit('onBeforeAction', codeButton, {
      previewInfo: [
        {
          value: journalInfo,
        },
      ],
    });
  }

  onError(): void {
    this.hasError = true;
    this.operationDialog.toResult();
  }

  onFinish(): void {
    this.operationDialog.toResult();
  }

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

  open(): void {
    if (this.disable) return;
    this.emitOnBeforeActionWitchExtraInfo('register_sign');
    this.opened = true;
    this.$emit('open');
  }

  closeModal(): void {
    if (this.flagCancelButton) {
      this.flagCancelButton = false;
      this.emitOnBeforeActionWitchExtraInfo('register_reject_cancel');
    } else {
      this.close();
      this.emitOnBeforeActionWitchExtraInfo('register_sign_cancel');
    }
  }

  openRejectModal(): void {
    this.flagCancelButton = true;
    this.emitOnBeforeActionWitchExtraInfo('register_reject_prepare');
  }

  close(): void {
    this.opened = false;
    this.resultList = [];
    this.operationDialog.reset();
    this.$emit('close');
  }
}
</script>
