<template>
  <div class="q-pa-md q-gutter-y-md">
    <div
      class="flex justify-between items-center bg-white q-pa-md rounded-borders"
    >
      <div class="column full-width">
        <div>
          <div
            class="text-h6 flex items-center q-gutter-y-md text-grey-9 col q-pr-md"
          >
            <q-btn
              :loading="loading"
              padding="xs"
              class="text-grey-7 q-mr-md"
              color="grey-3"
              icon="arrow_back"
              @click="returnToParentView(parentRoute)"
            />
            <div>
              <div class="text-h5">{{
                title
              }}</div>
              <div class="text-caption">{{ $t('registries.registryPayment.subtitle') }}</div>
            </div>
            <q-space />
            <div class="row items-center q-gutter-x-md q-gutter-y-sm">
              <q-btn
                v-if="$AC.haveScope(USER_SCOPES.PAYMENTS_ADMIN)"
                color="primary"
                label="Импорт из УФК"
                :loading="loading"
                @click="importUFK"
              />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="bg-white rounded-borders">
      <BaseTable
        :columns="columns"
        :data="data"
        :selected.sync="selected"
        :pagination.sync="pagination"
        :loading="tableLoading"
        @update="updateTableData"
        @requestTable="updateTableData"
      >
        <template #search>
          <SearchBar
            :loading="loading"
            :show-search-button="true"
            :status-options="statusOptions"
            @query="search"
          />
        </template>
        <template v-slot:body-item-selection="scope">
          <q-checkbox
            :disable="!scope.props.row.signed && !scope.props.row.cancelDate"
            v-model="scope.props.selected"
          />
        </template>
        <template v-slot:body-item-sign="props">
          <div class="row no-wrap text-no-wrap float-right">
            <q-btn
              flat
              dense
              icon="info"
              size="16"
              style="color: rgba(0, 0, 0, 0.54)"
              color="primary"
              @click="showInfo(props.row)"
            >
              <q-tooltip>
                {{ $t('registries.objectCard.annulInfo') }}
              </q-tooltip>
            </q-btn>
          </div>
        </template>
      </BaseTable>
      <UploadPayments
        v-if="registry"
        process-key="ImportPayments"
        :registry-payment-code="registry.code"
        :open.sync="uploadModal"
        :title="registry.description"
        @upload="updateTableData"
      />
      <InfoDialog
        :openDialog.sync="infoModal"
        :model="currentItem"
        :hide-nulls="true"
        :padded-groups="true"
        form-key="PaymentInfo"
      />
    </div>
  </div>
</template>

<script lang="ts">
import { Component } from 'vue-property-decorator';
import { mixins } from 'vue-class-component';
import ReturnToParentView from '@mixins/ReturnToParentView';
import {
  RegistryApi
} from '@openapi/registry-data/api';
import { convertDateFromBackendFormat, convertDateFromTimestamp } from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';
import QColumn from '@/types/QColumn';
import { Route } from 'vue-router/types';
import { TablePagination } from '@models/base/TablePagination';
import S3UrlSignerFilesService from '@services/s3urlsigner/files';
import { saveAs } from 'file-saver';
import SearchBar from '@components/registries/base-search-bar.vue';
import UploadPayments from '@components/registries/upload_payments.vue';
import InfoDialog from '@components/registries//info_dialog.vue';
import { USER_SCOPES } from '@constants/entities/Scope';
import get from 'lodash/get';
import axios from 'axios';
import { notifyError } from '@utils/notify';
import {
  DocumentApi,
} from '@openapi/registry-data'
import {
  RegistryOrder,
  RegistryPaymentApi,
  Page,
} from '@/openapi/registry-service';
import { searchByField } from '@/utils/query';

import type SearchQuery from '@interfaces/entities/SearchQuery';
import type { Payment } from '@interfaces/entities/PaymentRegistry'

const REGISTRIES_LIST_URL = '/registries/payments';

@Component({
  components: {
    SearchBar,
    UploadPayments,
    InfoDialog,
  },
  methods: {
    get,
  },
})
export default class PaymentList extends mixins(ReturnToParentView) {
  selected: Array<Payment> = [];
  data: Array<Payment> = [];
  searchQuery: SearchQuery;
  queryString = '';
  fulltextString = '';
  currentProcess: Prosess | null = null;
  tableLoading = false;
  currentItem: Payment | null = null;
  loading = false;
  uploadModal = false;
  signModal = false;
  signInfoModal = false;
  infoModal = false;
  sortByDefault = 'created';
  pagination = new TablePagination({
    rowsPerPage: 100,
    descending: true,
    sortBy: 'created',
  });

  title = '';
  code = '';
  registry: RegistryOrder | null = null;

  USER_SCOPES = USER_SCOPES;

  get parentRoute(): { name: string } | string {
    const registryRoutes = this.$router.$history.filter(
      (route: Route) => {
        if (!route.name || route.name === 'registry-payment') return false;
        return /(registr(y|ies)|personal-accounts)/.test(route.name);
      }
    );
    
    if (registryRoutes.length) {
      return registryRoutes[0].path;
    }
    return REGISTRIES_LIST_URL;
  }

  get columns(): Array<QColumn> {
    return [
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.created'),
        field: 'created',
        format: (val: any) =>
          val ? convertDateFromTimestamp(val, DateFormat.date) : '',
        name: 'created',
        required: true,
        sortable: true,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.paymentdate'),
        field: 'paymentdate',
        format: (val: any) =>
          val ? convertDateFromBackendFormat(val, DateFormat.date) : '',
        name: 'paymentdate',
        required: true,
        sortable: true,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.departmentName'),
        field: 'departmentName',
        name: 'departmentName',
        required: true,
        sortable: true,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.state'),
        field: 'state',
        name: 'state',
        required: true,
        sortable: false,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.sum'),
        field: 'sum',
        name: 'sum',
        format: (val: any) =>
          val ? `${val} ₽` : '',
        required: true,
        sortable: false,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.regNumber'),
        field: 'regNumber',
        name: 'regNumber',
        required: true,
        sortable: false,
      },
      {
        align: 'left',
        label: this.$t('registries.registryPayment.columns.info'),
        field: 'sign',
        name: 'sign',
        required: true,
        sortable: false,
      },
    ];
  }

  statusOptions = [
    {
      label: 'Выплата невозможна',
      value: 'Выплата невозможна',
    },
    {
      label: 'Выплата произведена',
      value: 'Выплата произведена',
    },
  ];

  created(): void {
    this.updateTableData();
  }

  async fetchData(): Promise<Page | undefined> {
    const query = this.searchQuery?.query || '';
    const fulltextString = this.searchQuery?.fulltext || '';
    const sortString = (this.pagination.sortBy && `${this.pagination.descending
      ? '-'
      : '+'
      }${this.pagination.sortBy}`) || '';

    const codeOrId = (Array.isArray(this.$route.params.id) ? this.$route.params.id[0] : this.$route.params.id) || '';

    const [, id] = codeOrId.match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/) || [];

    if (id) {
      // Получаем реестр по id
      const { data } = await new RegistryPaymentApi().getRegistryPayment(id);
      this.registry = data;
      this.code = this.registry.code;
    } else if (/^[a-zA-Z0-9]+$/.test(codeOrId)) {
      // Получаем реестр по code
      try {
        const { data } = await new RegistryPaymentApi().searchRegistryPayment(searchByField('code', codeOrId));
        this.registry = data[0];
        this.code = codeOrId;
      } catch (e) {
        notifyError('Не удалось найти реестр');
        return;
      }
    }

    // Тайтл как название реестра
    this.title = this.registry?.name || 'Реестр не найден';

    return new DocumentApi().pagingDocuments(
      this.code,
      this.pagination.page,
      this.pagination.rowsPerPage,
      query,
      fulltextString,
      sortString
    ).then(it => it.data);
  }

  search(query: SearchQuery): void {
    this.searchQuery = query;
    this.updateTableData();
  }

  async updateTableData(val?: any): Promise<void> {
    this.tableLoading = true;
    this.updatePagination(val?.pagination);

    try {
      const data = await this.fetchData()

      if (!data) {
        this.tableLoading = false;
        return;
      }

      this.pagination.rowsNumber = data.totalRows || 0;
      this.pagination.page = data.page;
      this.pagination.rowsPerPage = data.perPage;

      this.data = data.records || [];
    } catch (e) {
      notifyError(
        this.$t('registries.unloadingList.noRecordsFound').toString()
      );
      console.warn(`failed count ${e}`);
    } finally {
      this.tableLoading = false;
    }
  }

  updatePagination(pagination: TablePagination): void {
    if (pagination) {
      this.pagination.descending = pagination.descending;
      this.pagination.page = pagination.page;
      this.pagination.rowsPerPage = pagination.rowsPerPage;
      this.pagination.sortBy =
        pagination.sortBy === null ? this.sortByDefault : pagination.sortBy;
    }
  }

  async exportRecords(): Promise<void> {
    this.loading = true;

    if (!this.selected.length) {
      notifyError('Нет выбранных объектов для скачивания');
      this.loading = false;
      return;
    }

    const records = this.selected;
    const registryApi = new RegistryApi();

    try {
      for (const record of records) {
        const { request } = await registryApi.getRegistry(record.id);
        const archiveUrl = request.responseURL;
        const response = await axios.get(archiveUrl, {
          responseType: 'arraybuffer',
        });
        const blob = new Blob([response.data], { type: 'octet/stream' });
        saveAs(blob, `${record.title}.zip`);
      }
    } catch (err: any) {
      notifyError(err?.response?.data || err?.message)
    } finally {
      this.loading = false;
    }
  }

  async fetchDocumentAttachment(document: any) {
    const fileName =
      document?.title ?? this.$t('registries.unnamed').toString();
    const url = document?.reportLink;

    if (url) {
      try {
        const { file } = await S3UrlSignerFilesService.fetchFileFromS3ByUrl({
          url: url,
        });

        saveAs(file, `${fileName}.pdf`);
      } catch (e) {
        if(e instanceof Error) notifyError(e.message.toString());
      }
    }
  }

  importUFK(): void {
    this.uploadModal = true;
  }

  showInfo(item: Payment) {
    this.currentItem = item;
    this.infoModal = true;
  }
}

declare interface Prosess {
  taskId: string;
  traceId: string;
  success: boolean;
}
</script>
