import { Component, Prop } from 'vue-property-decorator';
import Vue from 'vue';
import { i18n } from '@plugins/i18n';
import isEmpty from 'lodash/isEmpty';
import get from 'lodash/get';

@Component
export default class BaseDecisionTable extends Vue {
  @Prop({
    default: i18n.t('base.decisionTable.checkTitle'),
  })
  private checkTitle?: string;

  @Prop({
    default: i18n.t('base.decisionTable.columnsTitle'),
  })
  private columnsTitle?: string;

  @Prop({
    default: () => {
      return {
        recomendation: [],
        results: [],
        subjects: [],
      };
    },
  })
  private checkList?: any;

  @Prop({
    default: () => {
      return {};
    },
  })
  private corrections?: any;

  private icons = {
    ok: {
      color: 'positive',
      name: 'check_circle_outline',
      // tooltip: 'Ответ получен'
    },
    error: {
      color: 'negative',
      name: 'remove_circle_outline',
      // tooltip: 'Ошибка'
    },
    pending: {
      color: 'warning',
      name: 'update',
      // tooltip: 'Ожидание ответа'
    },
  };

  private expands: any[] = [];

  private pagination: any = {
    rowsPerPage: 0,
  };

  private get columns(): any[] {
    return this.checksColumns(this.checkList);
  }

  private get dataCast(): any[] {
    return this.checksRows(this.checkList);
  }

  private get fullColumns(): any {
    const defaultColumns = {
      align: 'left', // Куда прижат текст в колонке
      name: 'title', // Используется в части представления в качестве :key;
      field: 'title', // Свойство, которое будет взято из объекта массива data для формирования результата проверки;
      i: -1, // порядковый номер колонки, используется в выделении ячейки;
      sortable: true, // Свойство колонки как и у компонента quasar'а. Участвует ли в сортировке колонка;
      // Свойство, содержащее кастомный метод сортировки (В данном случае с сохранением подзаголовков таблицы)
      sort: (next: any, prev: any, nextRow: any, prevRow: any) => {
        if (
          this.formatSortValue(prevRow.type) ===
          this.formatSortValue(nextRow.type)
        ) {
          return this.formatSortValue(prev) > this.formatSortValue(next)
            ? 1
            : this.formatSortValue(prev) < this.formatSortValue(next)
            ? -1
            : 0;
        }
      },
    };

    return [defaultColumns, ...this.columns!];
  }

  private formatSortValue(value: any): string {
    return String(value).toLowerCase();
  }

  private checksColumns(checkList: any) {
    const { subjects, results } = checkList;
    const columns: any[] = [];

    if (!isEmpty(subjects) && !isEmpty(results)) {
      subjects.forEach((subject: any, i: number) => {
        const { name, type } =
          typeof subject === 'object'
            ? subject
            : {
                name: subject,
                type: 'null',
              };
        let error = -1;
        for (let j = results.length; j--; )
          if (results[j].values?.[i] === -1) {
            error = j;
            break;
          }

        columns.push({
          align: 'center', // Куда прижат текст в колонке
          field: 'relative' + i, // Свойство, которое будет взято из объекта массива data для формирования результата проверки;
          name: 'relative' + i, // Если name === title, то выведется значение для данной ячейки;
          i, // Порядковый номер колонки, используется в выделении ошибок как целой строки (если i < error для объекта из массива data, то ячейка будет выделена цветом)
          sortable: false,
          label: name, // Заголовок таблицы проверяемой сущности;
          error, // Если отлично от -1, то будет выделено как ошибка (сам заголовок);
          type, // Заголовок над названием колонки проверяемого объекта, в данном случае это заголовок над Иванов И. И.
        });
      });
    }

    return columns;
  }

  private checksRows(checkList: any) {
    const { results } = checkList;
    let manual: any[] = [];
    let auto: any[] = [];

    if (Array.isArray(results)) {
      manual = results.filter((result: ResultCheck) => {
        return get(result, 'type') === 'manual';
      });
      auto = results.filter((result: ResultCheck) => {
        return get(result, 'type') !== 'manual';
      });
      manual = this.prepareRows(manual, 'manual');
      auto = this.prepareRows(auto, 'auto');
    }

    if (Array.isArray(manual) && manual.length) {
      manual.unshift({
        type: 'header',
        title: i18n.t('base.checkboxTable.manualTitle'),
        isTitle: true,
      });
    }
    if (Array.isArray(auto) && auto.length) {
      auto.unshift({
        type: 'header',
        title: i18n.t('base.checkboxTable.autoTitle'),
        isTitle: true,
      });
    }

    const rows = [...manual, ...auto];

    rows.forEach(() => {
      this.expands.push({
        val: false,
      });
    });

    return rows;
  }

  private prepareRows(arr: ResultCheck[], type: string): any[] {
    const status = {
      OK: 'ok',
      ERROR: 'error',
      PENDING: 'pending',
    };
    const map: any = {
      '0': '',
      undefined: '',
      '': '',
      '-1': status.ERROR,
      '-2': status.PENDING,
      '1': status.OK,
    };

    return arr.map(({ name, baseDocument, code, values }: any) =>
      (values || []).reduce(
        (obj: any, value: any, i: number) => {
          value = value.value in map ? map[value.value] : value.value;
          if (value === status.ERROR && this.checkCorrection(code)) {
            obj.correction = this.corrections[code];
            obj['relative' + i] = status.OK;
          } else {
            obj['relative' + i] = value; // Может быть ещё 'error', 'pending' - управляет иконкой для проверяемой сущности с индексом 0;
            if (value === status.ERROR) obj.error = i; // Выделяет  строку, если отлично от 0, при этом происходит сравнение, если i (порядковый номер колонки) меньше, чем error, то ячейка выделяется цветом;
          }
          return obj;
        },
        {
          type: type, // Тип строки для сортировки
          error: -1,
          title: name, // Заголовок наименования проверки;
          baseDocument: baseDocument || 'Базовый тип документа',
          expand: false,
        }
      )
    );
  }

  private checkCorrection(code: string): boolean {
    if (!isEmpty(this.corrections)) {
      return Object.keys(this.corrections).some(
        (key) => key.toLowerCase() === code.toLowerCase()
      );
    }
    return false;
  }

  private goToDocument(docId: string): void {
    const route = this.$route;
    this.$router.push({
      name: route.name || '',
      params: route.params || {},
      query: {
        ...route.query,
        active: 'documents',
        markeredDocuments: docId,
      },
    });
  }
}

declare interface ResultCheck {
  code?: string;
  name: string;
  baseDocument?: string;
  type?: string;
  values: any[];
}
