/* eslint-disable @typescript-eslint/ban-ts-comment */
import { Component, Mixins, Watch, Vue, Prop } from 'vue-property-decorator';
import { oidcClientComputed } from '@state/modules/oidc-client';
import { saveAs } from 'file-saver';
import QColumn from '@/types/QColumn';
import { convertDateFormatWithoutLocale } from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';
import ReportCreate from './create/index.vue';
import ReportsSearchBar from './components/search-bar.vue';
import S3UrlSignerFilesService from '@services/s3urlsigner/files';
import { notifyError } from '@utils/notify';
import get from 'lodash/get';
import { DocumentApi } from '@openapi/document-registry';
import {
  fetchAttachmentReport,
  fetchBaseReport,
  fetchReportsByParams,
  ReportsList
} from '@services/document-registry';
import { DocumentModel } from '@interfaces/base/DocumentModel';

const documentApi = new DocumentApi();

const reports = Vue.extend({
  computed: {
    ...oidcClientComputed,
  },
});

@Component({
  components: { ReportsSearchBar, ReportCreate },
})
export default class Reports extends Mixins(reports) {
  @Prop() searchQuery: ReportsSearchQuery | undefined;

  get title() {
    return this.baseReport?.name || '';
  }

  get visibleColumns() {
    const { reportsAuto = [], reports = [] } = this.baseReport?.columns || {};

    return (this.model.auto ? reportsAuto : reports).map((col: string | any) =>
      typeof col === 'string' ? col : col.name
    );
  }

  protected async download(results?: any[]) {
    if (!results || !results.length) {
      return;
    }
    const { name, file }: any = await this.fetchAttachment(results[0]);
    saveAs(file, name);
  }

  protected create = false;

  protected model: ReportsModel = {
    loading: false,
    auto: false,
    pagination: {
      descending: true,
      rowsPerPage: 10,
      sortBy: 'modified',
      rowsNumber: 0,
      page: 1,
    },
    records: [],
  };

  @Watch('reportsRowsNumber', {
    immediate: true,
  })
  protected reportsRowsNumberHandler(val: number): void {
    this.model.pagination.rowsNumber = val;
  }

  protected get isProd(): boolean {
    return process.env.NODE_ENV === 'production';
  }

  protected goToCard(uuid: string) {
    this.$router.push({
      name: 'cards',
      params: {
        id: uuid,
        path: 'reports',
        parent: this.baseReport,
      },
      query: {
        components: 'index',
      },
    });
  }

  protected goToReports(): void {
    this.$router.push({
      path: `/reports`,
      query: {
        from: this.parentId,
      },
    });
  }

  protected get columns(): QColumn[] {
    const columns = [
      {
        align: 'left',
        field: (v: any) => v,
        format: (v: any) => v.number || '-',
        handler: this.goToCard,
        handlerField: 'id',
        label: this.$t('reports.columns.number'),
        name: 'id',
        required: true,
      },
      {
        align: 'left',
        field: 'params.regions',
        formatField: 'name',
        label: this.$t('reports.columns.region'),
        name: 'regions',
        required: true,
      },
      {
        align: 'left',
        field: 'params.organizations',
        label: this.$t('reports.columns.organization'),
        name: 'organizations',
        formatField: 'shortname',
      },
      {
        align: 'left',
        field: 'params.accounts',
        label: this.$t('reports.columns.accounts'),
        name: 'accounts',
        formatField: 'shortname',
      },
      {
        align: 'left',
        field: 'params.services',
        label: this.$t('reports.columns.serviceName'),
        name: 'services',
        formatField: 'shortName',
      },
      {
        align: 'left',
        field: 'params.range',
        label: this.$t('reports.columns.range'),
        style: 'white-space: nowrap',
        name: 'range',
        format: (range: { from: string; to: string }) => {
          if (!range) {
            return '';
          }
          const { from, to } = range;
          const convert = convertDateFormatWithoutLocale;
          const toFormat = DateFormat.date;

          if (from && to) {
            return `${convert(from, toFormat)} - ${convert(to, toFormat)}`;
          } else if (from) {
            return `${this.$t('base.dateRange.from')} ${convert(
              from,
              toFormat
            )}`;
          } else if (to) {
            return `${this.$t('base.dateRange.to')} ${convert(to, toFormat)}`;
          }

          return '';
        },
      },
      {
        align: 'left',
        field: 'startDate',
        format: (val: any) => (val ? convertDateFormatWithoutLocale(val) : ''),
        label: this.$t('reports.columns.startDate'),
        name: 'startDate',
      },
      {
        align: 'left',
        field: 'auto.every',
        label: this.$t('reports.columns.period'),
        name: 'every',
        format: (every: string) =>
          every ? this.$t(`reports.every.${every}`) : '',
      },
      {
        align: 'left',
        field: 'comment',
        label: this.$t('reports.columns.comment'),
        name: 'comment',
      },
      {
        align: 'left',
        field: 'name',
        label: this.$t('reports.columns.name'),
        name: 'name',
      },
      {
        align: 'left',
        field: 'results',
        label: this.$t('reports.columns.action'),
        style: 'text-align: center; width: 4em',
        name: 'download',
      },
    ];

    return columns;
  }

  protected isCreating = false;

  protected creating(promise: Promise<any>) {
    this.isCreating = true;
    let go = true;
    window.setTimeout(() => (go = false), 2000); // если ждём меньше пары секунд
    promise
      .then((report) => {
        if (go && report.id) {
          return this.goToCard(report.id);
        }

        const auto = !!report.auto?.enabled;
        auto !== this.model.auto ? (this.model.auto = auto) : this.fetch();
      })
      .finally(() => (this.isCreating = false));
  }

  created() {
    this.init();
  }

  @Watch('model.auto')
  protected updateAuto() {
    this.fetch();
  }

  protected queryString = '';

  protected pending = 0;

  protected async fetch(q?: string) {
    const { currentUser } = this

    if (typeof q !== 'undefined') {
      this.queryString = q;
    }
    if (this.pending) {
      this.pending++;
      return;
    }
    this.pending = 1;

    this.model.loading = true;

    try {
      const { data: responce } = await fetchReportsByParams({
        autoEnabled: this.model.auto,
        creatorId: currentUser.sub, // todo переписать на авторизацию через токен
        parentIds_in: this.parentId,
        number_like: this.queryString,
        page: this.model.pagination?.page,
        perPage: this.model.pagination?.rowsPerPage,
      })
      if (responce) {
        this.model.pagination.rowsNumber = responce?.totalRows || undefined;
        this.model.records = responce?.records?.map((report: StatReport) => ({
          ...report.StatReport,
          id: report.StatReport?._key,
          results: report.DocumentAttachmentFileDescriptor
            ? [
                {
                  ...report.DocumentAttachmentFileDescriptor,
                  id: report.StatReportResult?._key,
                },
              ]
            : report.StatReport.s3uri
            ? [
                {
                  s3uri: report.StatReport.s3uri,
                  s3filename: report.StatReport.s3filename,
                },
              ]
            : [],
        }));
      }
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.model.loading = false;
    }

    if (this.pending > 1) {
      this.pending = 0;
      await this.fetch();

      return;
    }
    this.pending = 0;
  }

  protected baseReport: any = null;
  @Prop() protected parentId: string;

  protected initBaseReport() {
    if (this.$route.params.parent) {
      return (this.baseReport = this.$route.params.parent);
    }
    fetchBaseReport(this.parentId).then(
      (baseReport) => (this.baseReport = baseReport)
    );
  }

  protected async init(val: any = null) {
    await this.initBaseReport();
    if (val?.pagination) {
      this.model.pagination.descending = val.pagination.descending;
      this.model.pagination.rowsPerPage = val.pagination.rowsPerPage;
      this.model.pagination.sortBy = val.pagination.sortBy;
      this.model.pagination.page = val.pagination.page;
    }

    return this.fetch();
  }

  fetchAttachment(document: any) {
    const attachment = { ...document };
    const file = attachment.s3uri && attachment;
    if (file) {
      return S3UrlSignerFilesService.fetchFileFromS3ByUrl({
        url: file.s3uri,
      }).then((result) => ({
        ...result,
        name: file.s3filename,
      }));
    } else if (attachment) {
      return fetchAttachmentReport(
        'StatReportResult',
        document.id,
        attachment.fileName
      ).then((result) => ({
        ...result,
        name: attachment.fileName,
      }));
    } else {
      notifyError(this.$t('DocumentsCard.documentFileUrlIsEmpty').toString());
    }
  }
}

export interface ReportsSearchQuery {
  auto: boolean;
  statuses: string;
  daterange: string;
  employees: string;
}

interface ReportsModel extends DocumentModel {
  auto: boolean;
}

export type StatReport = {
  DocumentAttachmentFileDescriptor: {[key: string]: [value: string]}
  StatReport: {
    _key: string;
    creator: Record<string, unknown>;
    modified: number;
    name: string;
    number: number;
    s3uri: string;
    s3filename: string;
  }

  StatReportResult: {
    "_key": string;
    "date": string;
    "modified": number;
    "params": Record<string, unknown>;
  }
}
