<template>
  <div class="RecruitCard">
    <div class="RecruitCard-Header">
      <record-header
        :data="data"
        :loading="loading"
        class="RecruitCard-Record"
        @refresh="fetch"
        @send-data="sendConfirmData"
      />
      <redesigned-tabs
        :clickHandler="tabClickHandler"
        :current-tab="$route.name"
        :tabs="convertedTabs"
        dense
        class="RecruitCard-Tabs"
      />
    </div>
    <router-view
      :data.sync="data"
      :loading="loading"
      @refresh="fetch"
      @updateTabSections="updateTabSections($event)"
    />
  </div>
</template>

<script lang="ts">
import {
  PersonRegistryApi,
  RecruitMainInfoV3,
  RecruitV4,
  StateRecruitV3,
} from '@/recruits/openapi/person-registry';
import { ErvuIncidentsServiceApi } from '@/recruits/openapi/ervu-service';
import {
  DecisionDocuments,
  DecisionDocumentServiceApi,
} from '@/recruits/openapi/decision-document';
import {
  UpdateControllerApi,
  GetUpdateResponse,
  PutUpdatedRequest,
} from '@/recruits/openapi/data-update-controller';

import { JournalServiceApi } from '@/recruits/openapi/journal-service';
import {
  SubpoenaByRecruitV5,
  SubpoenaRegistryApi,
} from '@/recruits/openapi/subpoena-service';
import { Component, Vue } from 'vue-property-decorator';
import RecordHeader from './masthead/masthead.vue';
import { isDecisionSigned, subpoenaIsActive } from '@/recruits/utils';
import { notifyError, notifySuccess } from '@utils/notify';
import { isEmpty } from 'lodash';
import { Tab } from '@/interfaces/base/BaseTabs';
import { DataForRecruit } from './masthead/interfaces';
import { TabSection } from '@/recruits/components/recruit-card/tab-sections/interfaces';
import { INITIAL_PAGINATION } from '@/recruits/components/recruit-card/versions/search-filter';
import { PersonArchiveApi } from '@/recruits/openapi/person-archive';

const JOURNAL_SERVICE_API = new JournalServiceApi();
@Component({
  components: { RecordHeader },
})
export default class ArchiveRecord extends Vue {
  ArchiveApi = new PersonArchiveApi();
  RecruitApi = new PersonRegistryApi();
  SubpoenaApi = new SubpoenaRegistryApi();
  UpdateApi = new UpdateControllerApi();
  IncidentsService = new ErvuIncidentsServiceApi();
  DecisionsService = new DecisionDocumentServiceApi();

  public loading = true;

  public data: DataForRecruit = Object.assign({} as RecruitV4, {
    mainInfo: {} as RecruitMainInfoV3,
    updateInfo: {} as GetUpdateResponse,
    stateRecruit: {} as StateRecruitV3,
    decisions: {} as DecisionDocuments,
    subpoenas: [] as SubpoenaByRecruitV5[],
    versions: {},
  });

  public readonly recruitId: string = this.$route.params.id;

  pagination = {
    sortBy: 'createDate',
    descending: true,
    page: 1,
    rowsPerPage: 50,
  };

  get tabs(): Tab[] {
    return [
      {
        name: 'Личные сведения',
        path: 'recruit-personal',
      },
      {
        name: 'Подробные сведения',
        path: 'recruit-details',
      },
      {
        name: 'Заявления',
        path: 'application',
        visible: !isEmpty(this.data?.application),
        alert: this.data?.application?.some((app) => app.status !== '0')
          ? 'yellow-10'
          : false,
      },
      {
        name: 'Личное дело',
        path: 'recruit-pf-requests',
        visible: !isEmpty(this.data?.privateFile),
        alert: this.data?.status === '7.1' ? 'yellow-10' : false,
      },
      {
        name: 'Повестки',
        path: 'recruit-summons',
        visible:
          (this.data?.isThereActiveSubpoena &&
            this.data?.stateRecruit?.changeVkInProgress &&
            isEmpty(this.data?.subpoenas)) ||
          !isEmpty(this.data?.subpoenas),
        alert: this.data?.subpoenas?.some((subpoena) =>
          subpoenaIsActive(subpoena)
        )
          ? 'yellow-10'
          : false,
      },
      {
        name: 'Временные меры',
        path: 'recruit-temporary-measures',
        visible: !!this.data?.restrictions?.filter(
          (subpoena) => subpoena.restrictionDocumentItems?.length
        )?.length,
      },
      {
        name: 'Решения',
        path: 'recruit-attached-decision',
        alert:
          this.data.decisions.militaryCommissarDecisions?.some(
            (decision) => !isDecisionSigned(decision)
          ) ||
          this.data.decisions?.systemDocuments?.some(
            ({ status }) => status === 'formed'
          )
            ? 'yellow-10'
            : false,
      },
      {
        name: 'История',
        path: 'recruit-history',
      },
      {
        name: 'Документы',
        path: 'recruit-attached-documents',
      },
      {
        name: 'Версии',
        path: 'recruit-versions',
        visible:
          !isEmpty(this.data?.versions?.data) ||
          this.$route.name === 'recruit-versions',
        tooltip:
          'Содержит информацию об изменении сведений по гражданину. Каждый блок отображает список изменений по гражданину произошедших в этой версии, включая изменения технических атрибутов, параметров',
      },
      {
        name: 'Выписки',
        path: 'recruit-extracts',
      },
      {
        name: 'Инциденты',
        path: 'recruit-incidents',
        visible: !isEmpty(this.data?.incidentsByRecruit),
      },
    ];
  }

  tabSections: { [key: string]: Tab['tabSections'] } = {};

  updateTabSections(tabSections: TabSection[]): void {
    if (typeof this.$route.name === 'string')
      this.$set(this.tabSections, this.$route.name, tabSections);
  }

  get convertedTabs(): Tab[] {
    return this.tabs.map((tab: Tab) => ({
      ...tab,
      id: tab.path,
      visible: tab.visible !== false,
      tabSections: this.tabSections[tab.path],
    }));
  }

  get businessKey(): string | undefined {
    return this.data.recruitSystemInfo?.processIdMain;
  }

  public tabClickHandler(selectedTab: Tab): void {
    if (this.$route.name !== selectedTab.path) {
      this.$router.replace({
        name: selectedTab.path,
        params: { id: this.$route.params.id },
      });
    }
  }

  async requestProcessData(): Promise<void> {
    try {
      this.loading = true;
      await this.$store.dispatch(
        'wfActions/userTasks/fetchUserData',
        this.businessKey
      );
      this.loading = false;
    } catch (error) {
      console.error(error);
      console.error(
        `Ошибка при вызове wfApi.findUserTasks('${this.businessKey}',...)`,
        error
      );
      this.loading = false;
    }
  }

  private getInitialData(): DataForRecruit {
    return Object.assign({} as RecruitV4, {
      mainInfo: {} as RecruitMainInfoV3,
      updateInfo: {} as GetUpdateResponse,
      stateRecruit: {} as StateRecruitV3,
      decisions: {} as DecisionDocuments,
      versions: {},
    });
  }

  async mounted(): Promise<void> {
    await this.fetch();
    await this.requestProcessData();
    // @ts-ignore
    this.$recordActivity({
      event: 'navigation',
      extraInfo: {
        breadcrumbs: ['Карточка гражданина'],
        type: 'recruit',
        id: this.data?.id,
        fio: this.data?.mainInfo?.fullName,
        idERN: this.data?.systemInfo?.idERN,
      },
    });
  }

  async getRecruitArchiveId(): Promise<void> {
    try {
      const archiveResponse = await this.ArchiveApi.getArchiveIdByRecruitIdV1({
        recruitId: this.recruitId,
      });

      if (archiveResponse.status === 200 && archiveResponse.data.archiveId) {
        this.$router.push({
          name: 'archive-record',
          params: {
            id: archiveResponse.data.archiveId,
          },
        });
      } else {
        throw new Error('Архивная запись гражданина не найдена');
      }
    } catch (error) {
      this.$q.notify({
        message: 'Информация по гражданину не найдена',
      });
      this.$router.push('/');
    }
  }

  sendConfirmData(data: PutUpdatedRequest): void {
    this.UpdateApi.putUpdateData(this.recruitId, data)
      .then(() => {
        notifySuccess('Изменения успешно записаны');
        this.fetch();
      })
      .catch(() => {
        notifyError('Во время выполнения операции произошла ошибка');
      });
  }

  async fetch(): Promise<void> {
    this.data = this.getInitialData();

    try {
      this.getRecruitVersions();
      await this.fetchRecruitData();
    } catch (error) {
      await this.getRecruitArchiveId();
      return;
    } finally {
      this.loading = false;
    }
  }

  async fetchRecruitData(): Promise<void> {
    this.loading = true;
    try {
      const recruitResponse = await this.RecruitApi.getOneRecruitV4(
        this.recruitId
      );

      if (recruitResponse.status === 200) {
        this.data = { ...this.data, ...recruitResponse.data };
      }
    } catch (error) {
      throw new Error('Рекрут не найден');
    }

    const [
      recruitSubpoenas,
      updateData,
      recruitApplications,
      recruitIncidents,
      decisions,
    ] = await Promise.all([
      this.SubpoenaApi.getSubpoenaByRecruitV6(this.recruitId, this.pagination)
        .then((response) => response.data)
        .catch((error) => {
          console.error(
            `Ошибка получения данных о повестках по гражданину ${this.recruitId}`,
            error
          );
          return {
            isThereActiveSubpoena: false,
            subpoenas: [],
            restrictions: [],
            subpoenaSystemInfo: {},
          };
        }),
      this.UpdateApi.getUpdateData(this.recruitId)
        .then((response) => response.data)
        .catch((error) => {
          console.log(
            `Ошибка получения данных об изменениях по гражданину ${this.recruitId}`,
            error.message
          );
          return {
            presenceChanges: false,
            sourceChange: '',
            added: [],
            deleted: [],
            updated: [],
          };
        }),
      this.RecruitApi.getApplicationsForRecruitV2(this.recruitId)
        .then((response) => response.data)
        .catch((error) => {
          console.error(
            `Ошибка получения данных о заявлениям по гражданину ${this.recruitId}`,
            error
          );
          return {
            data: [],
          };
        }),
      this.IncidentsService.getIncidentsByRecruitV1(
        this.recruitId,
        this.pagination
      )
        .then((response) => response)
        .catch((error) => {
          console.error(
            `Ошибка получения инцидентов по гражданину ${this.recruitId}`,
            error
          );
          return {
            data: [],
          };
        }),
      this.DecisionsService.getDecisionV1(this.recruitId)
        .then((response) => response)
        .catch((error) => {
          console.error(
            `Ошибка получения инцидентов по гражданину ${this.recruitId}`,
            error
          );
          return {
            data: {},
          };
        }),
    ]);

    this.data = {
      ...this.data,
      subpoenas: [...(recruitSubpoenas.subpoenas || [])],
      restrictions: [...(recruitSubpoenas.restrictions || [])],
      subpoenaSystemInfo: recruitSubpoenas.subpoenaSystemInfo || {},
      application: recruitApplications.data,
      updateInfo: updateData,
      incidentsByRecruit: [...(recruitIncidents.data || [])],
      decisions: decisions.data,
      isThereActiveSubpoena: recruitSubpoenas.isThereActiveSubpoena,
    };
    this.loading = false;
    await this.requestProcessData();
  }

  getRecruitVersions(): void {
    // Вкладка версии сама запрашивает данные и обновляет их, поэтому делаем исключение.
    if (this.$route.name !== 'recruit-versions') {
      JOURNAL_SERVICE_API.getObjectHistoryV1({
        search: {
          objectId: this.recruitId,
        },
        pagination: {
          page: INITIAL_PAGINATION.page,
          sortBy: INITIAL_PAGINATION.sortBy,
          descending: INITIAL_PAGINATION.descending,
          rowsPerPage: INITIAL_PAGINATION.rowsPerPage,
        },
      })
        .then(({ data }) => {
          this.data = { ...this.data, versions: data };
        })
        .catch((error) => {
          console.error(
            `Ошибка получения данных о гражданине ${this.recruitId}`,
            error
          );
        });
    }
  }

  destroyed(): void {
    this.$store.dispatch('wfActions/userTasks/resetUserData');
  }
}
</script>

<style lang="scss">
.RecruitCard {
  position: relative;

  &-Header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: #edf3f7;
  }

  &-Record {
    height: 100px;
  }

  &-Tabs {
    border-top: 1px solid rgba(1, 72, 116, 0.11);
    border-bottom: 1px solid rgba(1, 72, 116, 0.11);
  }
}
</style>
