<template>
  <div class="multi-sign">
    <r-btn
      dense
      positive
      :disable="disable"
      :label="label"
      icon="pgs-sign"
      no-wrap
      @click="open"
    >
      <q-tooltip v-if="!!attachments.length" anchor="bottom middle">
        <div
          class="tooltipe-recruit"
          v-for="attachment in attachments"
          :key="attachment.id"
        >
          <div class="tooltipe-recruit__name" v-if="attachments.length !== 1">
            {{ attachment.recruitFullName }}
          </div>
          <div class="tooltipe-recruit__document">
            {{ get(attachment, 'file.s3Name') }}
          </div>
        </div>
      </q-tooltip>
    </r-btn>
    <operation-dialog
      sign
      persistent
      ref="dialog"
      :title="title"
      :sub="sub"
      v-model="opened"
      @hide="close"
      :show-close-on="['start']"
    >
      <div v-if="!!attachments.length" class="multi-sign-recruits">
        <div
          v-for="attachment in attachments"
          :key="attachment.id"
          class="multi-sign-recruit"
        >
          <div class="multi-sign-recruit__name" v-if="attachments.length !== 1">
            {{ attachment.recruitFullName }}
          </div>
          <div class="multi-sign-recruit__document">
            <q-icon
              class="multi-sign-recruit__document-icon"
              name="pgs-document"
              size="18px"
            />
            <span class="multi-sign-recruit__document-name">
              {{ get(attachment, 'file.s3Name') }}
            </span>
            <span style="flex: 1 1 auto"></span>
            <base-preview
              :s3Url="get(attachment, 'file.s3url')"
              :extension="get(attachment, 'file.format')"
            >
              <q-icon class="SummonsTable-Icon" name="pgs-view">
                <q-tooltip>Предпросмотр</q-tooltip>
              </q-icon>
            </base-preview>
          </div>
        </div>
      </div>
      <template #process>
        <result-block
          type="info"
          icon="pgs-sign"
          :header="$tc('MultiSign.signing', selectedIds.length)"
        >
          <TransitionGroup name="results" tag="div">
            <div v-for="res in resultList" :key="res.id">
              <q-icon name="pgs-sign-2" color="info" size="sm" />
              <span>{{ get(res, 'fullName') }}</span>
            </div>
          </TransitionGroup>
        </result-block>
      </template>
      <template #result>
        <result-block
          icon="pgs-ok"
          type="info"
          :header="$tc('MultiSign.finished', selectedIds.length)"
        >
          <div class="results">
            <div v-for="res in resultList" :key="res.id">
              <q-icon
                :name="res.type === 'positive' ? 'pgs-check' : 'pgs-close'"
                :color="res.type"
                size="sm"
              />
              <span>{{ get(res, 'fullName') }}</span>
            </div>
          </div>
        </result-block>
      </template>
      <template #right-actions>
        <r-btn
          action
          label="Подписать"
          icon="pgs-sign"
          :disable="disable || !certificateIsActive"
          @click="action"
        />
      </template>
      <template
        v-if="operationDialog && operationDialog.formState === 'start'"
        #left-actions-panel
      >
        <r-btn
          outline
          label="Отмена"
          icon="pgs-close"
          color="primary"
          @click="closeModal"
        />
      </template>
      <template #right-actions-result>
        <r-btn
          action
          label="Продолжить"
          icon-right="pgs-shevron-right-off"
          @click="finish"
        />
      </template>
      <template #sign-form>
        <crypto-pro-sign-form
          ref="signForm"
          class="no-right-border-radius"
          :process-key="processKey"
          :user-task="userTask"
          :task-process="taskProcess"
          bucket="ervu-attachment"
          @update:certificateIsActive="certificateIsActive = $event"
          @signed="onSigned"
          @error="onError"
          @finish="onFinish"
        />
      </template>
    </operation-dialog>
  </div>
</template>

<i18n>
{
  "ru": {
    "MultiSign": {
      "selected": "не выбрано | {n} документ | {n} документа | {n} документов",
      "signing": " | Документ подписывается | Документы подписываются | Документы подписываются",
      "finished": "Подписание завершено"
    }
  }
}
</i18n>

<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 ProcessStarter from '@/mixins/ProcessStarter';
import CryptoProSignForm from '@/components/common/cryptopro-sign-form/index.vue';
import {
  PersonRegistryApi,
  BatchSigning,
  SignEntity,
} from '@/recruits/openapi/person-registry';
import { DecisionDocumentServiceApi } from '@/recruits/openapi/decision-document';
import get from 'lodash/get';
import { SignData, Task } from '@/mixins/CriptoProPlugin';
import RInput from '@/recruits/components/common/r-input.vue';
import { notifyError } from '@utils/notify';
import { convertDateFromBackendFormat, DateFormat } from '@utils/format-date';

type SignResult = {
  id: string;
  fullName: string;
  type: 'negative' | 'positive';
};

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

interface RecruitListItem {
  id: string;
  fio: string;
  idERN: string;
  documentName: string;
}

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

  @Prop({ default: () => [] }) data: BatchSigning[];

  @Prop({ default: () => [] })
  declare readonly selectedIds: string[];

  @Prop({ default: () => '' })
  readonly title: string;

  @Prop({ default: () => '' })
  declare processKey: string;

  @Ref('dialog') operationDialog: OperationDialog;

  @Ref('signForm') signForm: CryptoProSignForm;

  personRegistryApi = new PersonRegistryApi();
  decisionDocumentServiceApi = new DecisionDocumentServiceApi();

  opened = false;

  certificateIsActive = false;

  resultList: SignResult[] = [];

  get selectedItems(): BatchSigning[] {
    return this.data.filter((d) => this.selectedIds.includes(d.id));
  }

  get attachments(): (SignEntity & {
    recruitFullName: string;
    recruitIdERN: string;
  })[] {
    return this.selectedItems.map((b) => ({
      ...b.signEntity,
      recruitFullName: b.fullName,
      recruitIdERN: b.idERN,
    }));
  }

  get sub(): string {
    return `${this.$tc('MultiSign.selected', this.selectedIds.length)}`;
  }

  get formModel(): FormModel {
    const signDate = convertDateFromBackendFormat(
      Date.now(),
      DateFormat.backend
    );
    return {
      entityList: this.selectedItems.map((b) => b.signEntity),
      signDate,
    };
  }

  async action(): Promise<boolean | void> {
    this.$emit('onBeforeAction', 'pack_sign', {
      list: this.recruitsList,
    });

    this.operationDialog.toProcess();

    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);
    }
  }

  get recruitsList(): RecruitListItem[] {
    return this.attachments.map((a) => ({
      id: a.recruitId,
      fio: a.recruitFullName,
      idERN: a.recruitIdERN,
      documentName: get(a, 'file.s3Name'),
    }));
  }

  onSigned(data: SignData): void {
    const result: SignResult = {
      type: 'positive',
      id: data.operationInfo?.recruitId || Math.random().toString(),
      fullName: data.operationInfo?.recruitFullName || '-',
    };
    this.resultList.push(result);
  }

  onError(task: Task): void {
    const operationInfo: SignData['operationInfo'] = get(
      task.userTask,
      'operationInfo',
      {}
    );
    const result: SignResult = {
      type: 'negative',
      id: operationInfo?.recruitId || Math.random().toString(),
      fullName: operationInfo?.recruitFullName || '-',
    };
    this.resultList.push(result);
  }

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

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

  open(): void {
    if (this.disable) return;
    this.$emit('onBeforeAction', 'pack_prepare', {
      list: this.recruitsList,
    });
    this.opened = true;
    this.$emit('open');
  }

  closeModal(): void {
    this.close();
    this.$emit('onBeforeAction', 'pack_cancel', {
      list: this.recruitsList,
    });
  }

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

<style lang="scss" scoped>
.SummonsTable-Icon {
  overflow: hidden;
  color: #1491cf;
  font-size: 26px;
  padding: 6px 3px;
  cursor: pointer;
}

.tooltipe-recruit {
  margin-bottom: 8px;

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

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

.multi-sign-recruits {
  display: flex;
  flex-flow: column;
}

.multi-sign-recruit {
  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;
  }

  &__document-name,
  &__document-icon {
    color: #6c7276;
  }

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

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

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

// TODO вынести
.title-text {
  font-family: 'Golos Text', sans-serif;
  font-style: normal;
  font-weight: 500;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -0.015em;

  color: rgba(2, 12, 18, 0.9);
}
</style>
