<template>
  <div class="subpoena-awarded">
    <block-loader type="QBtn" :loading="loading && sendInfo.length">
      <r-btn
        dense
        :label="label"
        icon="pgs-ok"
        :positive="true"
        :disable="disable"
        @click="open"
        no-wrap
      />
    </block-loader>
    <operation-dialog
      persistent
      ref="dialog"
      :title="title"
      :sub="sub"
      v-model="opened"
    >
      <div class="wrapper">
        <div class="row flex flex-center Select">
          <q-list v-for="option in optionsArray" :key="option.code" class="Select-Type">
            <q-item-section v-if="checkTabOption(option.code)" :class="['Select-Type__Radio', { 'Select-Type__Radio-Selected': selectedField && selectedField.code === option.code}]" name="radio">
              <q-radio
                dense
                v-model="selectedField"
                :val="option"
                color="primary"
              >
                <q-icon size="24px" :name="option.icon" />
                {{ option.value }}
              </q-radio>
            </q-item-section>
          </q-list>
        </div>
        <div class="flex row">
          <div :class="['Select-Mail', {'Select-Mail-Open': selectedField && selectedField.code === '14'}]">
            <div class="Select-Mail__Address">
              <q-list v-for="info in currentAddressType('14')" :key="info.id" class="Select-Mail__Address__List">
                <q-item-section :class="['Select-Mail__Radio']" name="radio">
                  <q-radio
                    dense
                    v-model="radioInput['14']"
                    :val="info"
                    color="primary"
                  >
                    <span>{{ getAddressTypesDictionary[info.sendAddress.type] }}</span>
                    <span>{{ info.sendAddress.reg }}</span>
                  </q-radio>
                </q-item-section>
              </q-list>
              <r-date-time-input
                class="q-mt-md"
                v-model="summonDate"
                :emit-format="isoDateFormat"
                :date-options="isDateAvailable"
                :time-options="isTimeAvailable"
                :default-year-month="defaultYearMonth"
                :default-time="defaultTime"
                label="Дата и время вручения"
              />
            </div>
          </div>
          <div :class="['Select-Meet', {'Select-Meet-Open': selectedField && selectedField.code === '15'}]">
            <div class="Select-Meet__Address">
              <q-list v-for="info in currentAddressType('15')" :key="info.id" class="Select-Meet__Address__List">
                <q-item-section :class="['Select-Meet__Radio']" name="radio">
                  <q-radio
                    dense
                    v-model="radioInput['15']"
                    :val="info"
                    color="primary"
                  >
                    <span>{{ getAddressTypesDictionary[info.sendAddress.type] }}</span>
                    <span>{{ info.sendAddress.reg }}</span>
                  </q-radio>
                </q-item-section>
              </q-list>
              <r-date-time-input
                class="q-mt-md"
                v-model="summonDate"
                :emit-format="isoDateFormat"
                :date-options="isDateAvailable"
                :time-options="isTimeAvailable"
                :default-year-month="defaultYearMonth"
                label="Дата и время вручения"
              />
            </div>
          </div>
          <div :class="['Select-Fields', {'Select-Fields-Open': selectedField && selectedField.code === '16'}]">
            <div class="Select-Fields__Block">
              <r-input
                class="SearchBar-Line__Element"
                label="Номер акта об отказе во вручении повестки"
                v-model="radioInput['16'].actNumber"
              />
            </div>
            <div class="Select-Fields__Block">
              <r-input
                class="SearchBar-Line__Element"
                label="ФИО лица, уведомившего о последствиях отказа получения повестки"
                v-model="radioInput['16'].actFIO"
              />
            </div>
            <div class="Select-Fields__Block">
              <r-date-time-input
                v-model="summonDate"
                :emit-format="isoDateFormat"
                :date-options="isDateAvailable"
                :time-options="isTimeAvailable"
                :default-year-month="defaultYearMonth"
                label="Дата и время вручения"
              />
            </div>
          </div>
        </div>
      </div>
      <template #process>
        <result-block type="info" icon="pgs-document" :header="processMessage">
        </result-block>
      </template>
      <template #result>
        <result-block icon="pgs-document" :header="resultMessage">
        </result-block>
      </template>
      <template #right-actions>
        <r-btn
          action
          label="Подтвердить"
          :disable="canFormSubmit"
          @click="action"
        >
          <q-tooltip
            max-width="200px"
            v-if="validateTimeRange.validateCallTime"
          >
            {{ validateTimeRange.message }}
          </q-tooltip>
        </r-btn>
      </template>
      <template #right-actions-result>
        <r-btn
          action
          label="Продолжить"
          icon-right="pgs-shevron-right-off"
          @click="finish"
        />
      </template>
    </operation-dialog>
  </div>
</template>

<i18n>
  {
    "ru": {
      "RNA": {
        "selected": "не выбрано | один рекрут | {n} рекрута | {n} рекрутов",
        "process": " | Документ формируется | Документы формируются | Документы формируются",
        "result": " | Документ сформирован | Документы сформированы | Документы сформированы"
      }
    }
  }
</i18n>

<style lang="scss" scoped>
.wrapper {
  overflow: hidden;
  margin: 0 -15px;
  .Select {
    gap: 15px;
    padding-bottom: 20px;
    margin: 0 -20px;
    border-bottom: 1px solid #e0e0e0;
    &-Type {
      background: #e5edf5;
      border-radius: 10px;

      &__Radio {
        ::v-deep.q-radio__inner {
          position: absolute;
          visibility: hidden;
        }

        ::v-deep.q-radio__label {
          padding: 10px;
        }
      }

      &__Radio-Selected {
        transition: background-color 0.3s;
        background: #4898cb;
        border-radius: 10px;
      }
    }

    &-Fields,
    &-Mail,
    &-Meet {
      transition: transform 0.3s;
      transform: translateX(300%);
      display: flex;
      flex-direction: column;
      gap: 10px;
      height: 0;
      opacity: 0;
      padding: 0;
      width: 100%;
      &__Block {
        gap: 10px;
        display: flex;
        justify-content: space-between;
        width: 100%;
        &:nth-child(1) label {
          width: 100%;
        }
        &:nth-child(2) label {
          width: 100%;
        }
      }
      &__Radio {
        display: flex;
        flex-direction: column;
        font-family: 'Golos UI', sans-serif;
        font-style: normal;
        font-weight: 400;
        font-size: 12px;
        line-height: 14px;
        color: rgba(2, 12, 18, 0.58);
        align-self: center;
        span {
          display: flex;
          &:nth-child(2n) {
            color: rgba(2, 12, 18, 1);
            font-size: 14px;
          }
        }
      }
      &__Address {
        gap: 10px;
        display: flex;
        justify-content: space-between;
        flex-direction: column;
      }
      &-Open {
        height: auto;
        padding: 10px;
        opacity: 1;
        transition: transform 0.3s;
        transform: translateX(0);
      }
    }
  }
}
</style>

<script lang="ts">
import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator';
import TaskButton from '@/mixins/TaskButton';
import { RecruitV3 } from '@/recruits/openapi/person-registry';
import {
  SendInfoByRecruitV1,
  SubpoenaByRecruitV5,
  SubpoenaOneResponseV3,
} from '@/recruits/openapi/subpoena-service';
import OperationDialog from '@/components/common/operation-dialog/index.vue';
import { isArray, isNull } from 'lodash';
import ProcessStarter from '@/mixins/ProcessStarter';
import Dialog from '@/mixins/Dialog';
import RDateTimeInput from '@/recruits/components/common/r-date-time-input.vue';
import RSelect from '@/recruits/components/common/r-select.vue';
import RInput from '@/recruits/components/common/r-input.vue';
import moment from 'moment';
import { notifyError } from '@utils/notify';
import { DataForRecruit } from '@/recruits/components/recruit-card/masthead/interfaces';

interface IOption {
  code: string;
  icon: string;
  value: string;
}

interface IModelObject extends SubpoenaOneResponseV3 {
  recruit: RecruitV3;
}

type DeliveryCase = '14' | '15' | '16';

type InputFields = Record<string, SendInfoByRecruitV1 & { actFIO: string; actNumber: string } | null >

const START_HOUR = 8;
const END_HOUR = 20;
const SUMMON_DELAY = 1;
const DESCISION_TYPE = 'decisionType';
const addressForSendDictionaryPath = 'ervuDictionaries/addressTypeDictionary';
const CALENDAR_DATE_FORMAT = 'YYYY-MM-DD';
const ISO_DATE_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
const iconArray = ['pgs-mail', 'pgs-user-check', 'pgs-file-no']
@Component({
  components: {
    RDateTimeInput,
    RSelect,
    RInput,
  },
})
export default class SubpoenaAwarded extends Mixins(
  TaskButton,
  Dialog,
  ProcessStarter
) {
  @Prop({ default: () => false })
  readonly sign: boolean;

  @Prop({
    default: () => 'Фиксация решения о признании причины неявки уважительной',
  })
  readonly title: string;

  @Prop({ default: '00:00' })
  readonly defaultTime: string;

  @Prop({ default: () => 'YYYY-MM-DDTHH:mm:ss.SSSZ' })
  readonly emitFormat: string;

  @Prop({ default: () => ({}) })
  declare readonly model: DataForRecruit | IModelObject;

  @Ref('dialog') operationDialog: OperationDialog;

  summonDate: string | null = null;
  selectedField: IOption | null = null;
  radioInput: InputFields = {
    '14': null,
    '15': null,
    '16': { actFIO: '', actNumber: '' },
  };

  @Watch('selectedField')
  clearFields() {
    this.summonDate = null;
    this.radioInput = { '14': null, '15': null, '16': { actFIO: '', actNumber: '' } };
  }

  get optionFields() {
    return this.$store.getters['ervuDictionaries/getDeliveryDirectionsFull'] || {};
  }

  get optionsArray() {
    return Object.keys(this.optionFields).reduce((acc, o, i) => {
      const option = {
        code: o,
        icon: iconArray[i],
        value: this.optionFields[o],
      };
      acc.push(option);
      return acc;
    }, [] as IOption[]);
  }

  isDateAvailable(date: string): boolean {
    const dateFormat: string = moment(date).format(CALENDAR_DATE_FORMAT);
    const currantDate: string = moment().format(CALENDAR_DATE_FORMAT);
    const sendingDate = moment(this.currentSubpoenaInfo?.sendingDate).format(CALENDAR_DATE_FORMAT)
    return moment(dateFormat).format(CALENDAR_DATE_FORMAT) >= sendingDate || moment(dateFormat).format(CALENDAR_DATE_FORMAT) >= currantDate;
  }

  get canFormSubmit(): boolean {
    if (this.selectedField?.code && this.radioInput?.[this.selectedField?.code as DeliveryCase]) {
      if (this.selectedField.code === '16') {
        return !this.radioInput?.['16']?.actNumber || !this.radioInput['16']?.actFIO || !this.summonDate || !this.isDateAvailable(this.summonDate) || this.validateTimeRange.validateCallTime;
      }
      return isNull(this.radioInput?.[this.selectedField?.code as DeliveryCase]) || !this.summonDate || !this.isDateAvailable(this.summonDate) || this.validateTimeRange.validateCallTime;
    }
    return true;
  }

  get validateTimeRange() {
    return {
      validateCallTime: !this.isTimeAvailable(
        this.momentSummonDate.hour(),
        this.momentSummonDate.minute()
      ),
      message: 'Время принятия решения должно быть с 8:00 до 20:00',
    }
  }

  get momentSummonDate(): moment.Moment {
    return moment(this.summonDate);
  }

  get defaultYearMonth(): string {
    let date = moment();
    while (!this.isDateAvailable(date.format(CALENDAR_DATE_FORMAT))) {
      date = date.add(1, 'day');
    }
    return date.format('YYYY/MM');
  }

  isTimeAvailable(
    hr: number,
    min: number | null,
    sec: number | null = null,
    isCurrentDate: boolean = this.momentSummonDate.format(
        CALENDAR_DATE_FORMAT
    ) === moment(this.currentSubpoenaInfo?.sendingDate).format(CALENDAR_DATE_FORMAT)
  ): boolean {
    if (isCurrentDate) {
      return this.isWorkHour(hr, true);
    }
    return this.isWorkHour(hr, false);
  }

  isDateAndTimeValid(): boolean {
    if (
      !this.isTimeAvailable(this.momentSummonDate.hour(), null) ||
      !this.isTimeAvailable(
        this.momentSummonDate.hour(),
        this.momentSummonDate.minute()
      )
    ) {
      notifyError(
          'Время принятия решения должно быть с 8:00 до 20:00'
      );
      return false;
    }
    return true;
  }

  isWorkHour(hour: number, isCurrentDate = false): boolean {
    return (
      hour >= START_HOUR &&
      (isCurrentDate ? hour <= END_HOUR - SUMMON_DELAY : hour < END_HOUR)
    );
  }

  get isoDateFormat(): string {
    return ISO_DATE_FORMAT;
  }

  get sub(): string {
    if (isArray(this.model))
      return `${this.$tc('RNA.selected', this.model.length)}`;
    return this.model?.mainInfo?.fullName || '';
  }

  get processMessage(): string {
    return this.$tc('RNA.process', this.personIds.length);
  }

  get resultMessage(): string {
    return this.$tc('RNA.result', this.personIds.length);
  }

  get getAddressTypesDictionary(): Record<string, string> {
    return this.$store.getters[addressForSendDictionaryPath] || {};
  }

  get currentSubpoenaInfo():
    | SubpoenaByRecruitV5
    | SubpoenaOneResponseV3['mainInfo'] {
    if (isArray((this.model as DataForRecruit)?.subpoenas)) {
      return (this.model as DataForRecruit)?.subpoenas?.find(e => (!e.subpoenaRejected && !e.recruitAttendanceConfirm)) || {} as SubpoenaByRecruitV5;
    } else {
      return (this.model as IModelObject)?.mainInfo;
    }
  }

  get sendInfo() {
    return this.currentSubpoenaInfo?.sendInfo;
  }

  checkTabOption(type: string): string | boolean {
    if (type !== '16') {
      return this.sendInfo?.filter(info => info.sendCode === type)?.[0]?.sendAddress?.reg || false;
    } else {
      return true;
    }
  }

  currentAddressType(type: string) {
    return this.sendInfo?.filter(info=> info.sendCode === type)
  }

  get personIds(): string[] {
    if ((this.model as DataForRecruit)?.subpoenas) {
      return [(this.model as DataForRecruit).id]
    } else {
      return [(this.model as IModelObject).recruit.id]
    }
  }

  get formModel() {
    if (this.selectedField?.code !== '16') {
      return {
        id: this.buttonSettings.id,
        deliveryInfo: {
          method: this.selectedField?.code,
          date: this.summonDate,
          sendInfoId: this.radioInput[this.selectedField?.code as DeliveryCase]?.id
        },
      };
    } else {
      return {
        id: this.buttonSettings.id,
        deliveryInfo: {
          method: this.selectedField?.code,
          actDate: moment(this.summonDate).format('YYYY-MM-DD'),
          actFIO: this.radioInput[this.selectedField?.code as DeliveryCase]?.actFIO,
          actNumber: this.radioInput[this.selectedField?.code as DeliveryCase]?.actNumber,
        },
      };
    }
  };


  async action(): Promise<void> {
    if (this.summonDate && !this.isDateAndTimeValid()) return;
    this.operationDialog.toProcess();
    try {
      const taskId = this.userTask.taskId;
      const traceId = this.taskProcess.traceId;
      await this.$store.dispatch('wfActions/processes/submitForm', {
        formModel: this.formModel,
        taskId,
        traceId,
      });

      this.registerListener((message, removeListener) => {
        if (traceId !== message.traceId) return;
        if (message.body.type === 'finish') {
          this.operationDialog.toResult();
          removeListener();
        }
      });
    } catch (error) {
      this.operationDialog.toResult();
      console.error(error);
    }
  }

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

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

  mounted(): void {
    this.initDescisionTypeDictionary();
  }

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

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