<i18n>
{
  "en": {
    "DirectoriesCard": {
      "type": "Type",
      "code": "Code",
      "goal": "Goal",
      "DirectoriesTitle": "Directories",
      "tableRejectSeviceTitle": "Reject Sevice",
      "tableRejectDocTitle": "eject Document",
      "name": "Name",
      "noProcessesResult": "No Processes directories",
      "confirmationMessage": "Are you sure you want to delete the directory?",
      "rejectDirectoriesTitle": "Reject directories",
      "createReject": "New reject",
      "documentChoose": "Choose directory",
      "upload": "Upload",
      "uploadTooltip": "Upload new dictionary from csv-file"
    }
  },
  "ru": {
    "DirectoriesCard": {
      "type": "Тип",
      "code": "Код",
      "goal": "Цели",
      "DirectoriesTitle": "Справочники",
      "tableRejectSeviceTitle": "Отказы в предоставлении услуги",
      "tableRejectDocTitle": "Отказы в приеме документов",
      "name": "Наименование",
      "noProcessesResult": "Справочники не найдены",
      "create": "Создать",
      "confirmationMessage": "Вы уверены, что хотите удалить справочник?",
      "rejectDirectoriesTitle": "Справочники отказов",
      "createReject": "Новый отказ",
      "documentChoose": "Выбрать",
      "upload": "Загрузить",
      "uploadTooltip": "Загрузка нового справочника из csv-файла"
    }
  }
}
</i18n>

<template>
  <div v-if="common.active === 'directories' && !loadingCard" class="q-pb-md">
    <q-card class="no-shadow q-gutter-y-md q-mx-md no-border-radius">
      <div
        class="q-gutter-y-md bg-white q-px-lg q-pb-md q-pt-sm q-mt-md q-mx-md rounded-borders"
      >
        <div class="flex justify-end q-my-md row" style="width: 100%">
          <div v-if="canEdit">
            <q-btn
              v-if="state === 'inProgress'"
              color="primary"
              icon="search"
              :label="$t('DirectoriesCard.documentChoose')"
              class="q-mr-md"
              @click="changelist"
            />
            <q-btn
              v-if="state === 'inProgress'"
              color="primary"
              icon="add_box"
              :label="$t('DirectoriesCard.create')"
              class="q-mr-md"
              @click="viewDictionary({}, 'create')"
            />
            <q-btn
              v-if="state === 'inProgress'"
              color="primary"
              icon="attach_file"
              :label="$t('DirectoriesCard.upload')"
              @click="uploadDictionary"
            >
              <q-tooltip>
                {{ $t('DirectoriesCard.uploadTooltip') }}
              </q-tooltip>
            </q-btn>
          </div>
        </div>
        <q-expansion-item v-if="dictionaries.length" default-opened>
          <template #header>
            <q-item-section>
              <div class="text-h6">
                {{ $t('DirectoriesCard.DirectoriesTitle') }}
              </div>
            </q-item-section>
          </template>
          <q-table
            v-if="dictionaries.length"
            :columns="directoriesColumns"
            :data="dictionaries"
            :pagination.sync="pagination"
            hide-bottom
          >
            <template #header="props">
              <q-tr :props="props">
                <q-th v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.label }}
                </q-th>
                <q-th />
              </q-tr>
            </template>
            <template #body="props">
              <q-tr :props="props">
                <q-td v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.value }}
                </q-td>
                <q-td
                  v-if="state === 'inProgress' && !props.row.nsiDictionaryId"
                  auto-width
                >
                  <q-btn
                    v-if="canEdit"
                    text-color="primary"
                    icon="edit"
                    flat
                    @click="viewDictionary(props.row, 'edit')"
                  />

                  <q-btn
                    v-if="canEdit"
                    text-color="negative"
                    icon="delete"
                    flat
                    @click="toggleDeleteConfim(props.row)"
                  />
                </q-td>
                <q-td
                  v-else-if="
                    state === 'readyToPublish' ||
                    state === 'published' ||
                    props.row.nsiDictionaryId
                  "
                  auto-width
                >
                  <q-btn
                    text-color="primary"
                    icon="search"
                    flat
                    @click="viewDictionary(props.row, 'view')"
                  />
                </q-td>
              </q-tr>
            </template>
          </q-table>
        </q-expansion-item>
        <div class="flex justify-end q-my-md q-pt-md row" style="width: 100%" v-if="canEdit">
          <q-btn
            v-if="state === 'inProgress'"
            color="primary"
            icon="add_box"
            :label="$t('DirectoriesCard.createReject')"
            @click="editReject({}, 'create')"
          />
        </div>
        <div
          v-if="
            directoriesRejectServis.length || directoriesRejectDocument.length
          "
        >
          <q-expansion-item
            v-if="directoriesRejectServis.length"
            default-opened
          >
            <template #header>
              <q-item-section>
                <div class="text-h6">
                  {{ $t('DirectoriesCard.tableRejectSeviceTitle') }}
                </div>
              </q-item-section>
            </template>
            <q-table
              :columns="columns"
              :data="directoriesRejectServis"
              :pagination.sync="pagination"
              hide-bottom
            >
              <template #header="props">
                <q-tr :props="props">
                  <q-th
                    v-for="col in props.cols"
                    :key="col.name"
                    :props="props"
                  >
                    {{ col.label }}
                  </q-th>
                  <q-th>
                    {{ $t('DirectoriesCard.goal') }}
                  </q-th>
                  <q-th />
                </q-tr>
              </template>

              <template #body="props">
                <q-tr :props="props">
                  <q-td
                    v-for="col in props.cols"
                    :key="col.name"
                    :props="props"
                  >
                    {{ col.value }}
                  </q-td>
                  <q-td>
                    <span
                      v-for="item in props.row.goal"
                      :key="item"
                      style="display: inline-block; margin: 5px"
                    >
                      <q-badge :color="goalColorMap[item]" :label="item" />
                    </span>
                  </q-td>
                  <q-td v-if="state === 'inProgress'" auto-width>
                    <q-btn
                      v-if="canEdit"
                      text-color="primary"
                      icon="edit"
                      flat
                      @click="editReject(props.row, 'edit')"
                    />

                    <q-btn
                      v-if="canEdit"
                      text-color="negative"
                      icon="delete"
                      flat
                      @click="deleteReject(props.row)"
                    />
                  </q-td>
                  <q-td v-else auto-width>
                    <q-btn
                      v-if="canEdit"
                      text-color="primary"
                      icon="search"
                      flat
                      @click="editReject(props.row, 'view')"
                    />
                  </q-td>
                </q-tr>
              </template>
            </q-table>
          </q-expansion-item>
          <q-expansion-item
            v-if="directoriesRejectDocument.length"
            default-opened
          >
            <template #header>
              <q-item-section>
                <div class="text-h6">
                  {{ $t('DirectoriesCard.tableRejectDocTitle') }}
                </div>
              </q-item-section>
            </template>
            <q-table
              :columns="columns"
              :data="directoriesRejectDocument"
              :pagination.sync="pagination"
              hide-bottom
            >
              <template #header="props">
                <q-tr :props="props">
                  <q-th
                    v-for="col in props.cols"
                    :key="col.name"
                    :props="props"
                  >
                    {{ col.label }}
                  </q-th>
                  <q-th>
                    {{ $t('DirectoriesCard.goal') }}
                  </q-th>
                  <q-th />
                </q-tr>
              </template>
              <template #body="props">
                <q-tr :props="props">
                  <q-td
                    v-for="col in props.cols"
                    :key="col.name"
                    :props="props"
                  >
                    {{ col.value }}
                  </q-td>
                  <q-td>
                    <span
                      v-for="item in props.row.goal"
                      :key="item"
                      style="display: inline-block; margin: 5px"
                    >
                      <q-badge :color="goalColorMap[item]" :label="item" />
                    </span>
                  </q-td>
                  <q-td v-if="state === 'inProgress'" auto-width>
                    <q-btn
                      v-if="canEdit"
                      text-color="primary"
                      icon="edit"
                      flat
                      @click="editReject(props.row, 'edit')"
                    />

                    <q-btn
                      v-if="canEdit"
                      text-color="negative"
                      icon="delete"
                      flat
                      @click="deleteReject(props.row)"
                    />
                  </q-td>
                  <q-td
                    v-else-if="
                      state === 'readyToPublish' || state === 'published'
                    "
                    auto-width
                  >
                    <q-btn
                      v-if="canEdit"
                      text-color="primary"
                      icon="search"
                      flat
                      @click="editReject(props.row, 'view')"
                    />
                  </q-td>
                </q-tr>
              </template>
            </q-table>
          </q-expansion-item>
        </div>
        <div
          v-if="
            !directoriesRejectServis.length &&
            !directoriesRejectDocument.length &&
            !dictionaries.length
          "
          class="full-width text-center"
        >
          {{ $t('DirectoriesCard.noProcessesResult') }}
        </div>
      </div>
    </q-card>
    <RejectDialog
      :model="currentReject"
      :mode="rejectDialogMode"
      :open-dialog.sync="rejectDialog"
    />
    <DictionaryDialog
      :common="common"
      :model="model"
      :dialog-data="formModel"
      @commonModels="commonModels"
    />
    <ListDialog
      :common="common"
      :model="model"
      :dialog-data="listModel"
      @commonModels="commonModels"
    />
    <q-dialog v-model="deleteConfim" class="full-width">
      <q-card class="no-shadow full-width">
        <q-card-section>
          <div class="text-h6">
            {{ $t('DirectoriesCard.confirmationMessage') }}
          </div>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn color="primary" label="Удалить" @click="deleteDictionary" />

          <q-btn
            color="white"
            text-color="primary"
            outline
            label="Отменить"
            @click="toggleDeleteConfim"
          />
        </q-card-actions>
      </q-card>
    </q-dialog>
    <q-dialog
      class="full-width"
      @hide="$emit('hide')"
      v-model="isUploadDictionaryOpen"
    >
      <q-card class="no-shadow full-width">
        <q-card-section>
          <div class="text-h6">
            {{ $t('file.actions.attach') }}
          </div>
        </q-card-section>
        <q-card-section>
          <q-file
            filled
            :accept="'.txt,.csv'"
            v-model="uploadedCsv"
            :label="$t('file.actions.upload')"
          />
        </q-card-section>
        <q-card-actions align="right">
          <q-btn
            @click="createUploadedDictionary"
            color="primary"
            :label="$t('base.actions.upload')"
          />

          <q-btn
            color="white"
            text-color="primary"
            outline
            @click="isUploadDictionaryOpen = false"
            :label="$t('base.actions.cancel')"
          />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
// @ts-nocheck
import RejectDialog from '@components/cards/services/RejectDialog.vue';
import { MetaClassSchemaRaw } from '@devsun/eva-models/dist/models/Schema';
import { fetchDocument, unlinkService } from '@services/registry-service';
import { DictionaryApi, FormApi } from '@openapi/registry-service';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import { Component, Prop, Vue } from 'vue-property-decorator';
import { BaseCardCommon } from '@/interfaces';
import { notifyError } from '@utils/notify';
import DictionaryDialog from '@components/cards/services/DictionaryDialog.vue';
import ListDialog from '@components/cards/services/ListDialog.vue';

const dictionaryApi = new DictionaryApi();
const formApi = new FormApi();
@Component({
  components: {
    RejectDialog,
    DictionaryDialog,
    ListDialog,
  },
})
export default class Directories extends Vue {
  @Prop() common?: BaseCardCommon;
  @Prop() model?: any;

  private isUploadDictionaryOpen = false;
  private uploadedCsv = null;
  private rejectDialogMode = 'edit';
  private deleteConfim = false;
  private currentReject = null;
  private rejectDialog = false;
  private deleteItem = null;
  private formModel = {};
  private listModel = {};
  private pagination = {
    rowsPerPage: 0,
  };

  get loadingCard() {
    return (
      this.$store.getters['registryService/services/servicesLoading'] || false
    );
  }

  get goalColorMap() {
    return this.$store.getters['registryService/services/goalColorMap'];
  }

  get directoriesColumns() {
    const headerStyle = 'font-size: 16px; font-weight: 600';
    return [
      {
        align: 'left',
        field: 'id',
        label: this.$t('DirectoriesCard.code'),
        name: 'id',
        sortable: false,
        headerStyle,
      },
      {
        align: 'left',
        field: 'name',
        label: this.$t('DirectoriesCard.name'),
        name: 'name',
        sortable: true,
        style: 'white-space: pre-wrap',
        headerStyle,
      },
    ];
  }

  get columns() {
    const headerStyle = 'font-size: 16px; font-weight: 600';
    return [
      {
        align: 'left',
        field: 'code',
        label: this.$t('DirectoriesCard.code'),
        name: 'code',
        sortable: false,
        headerStyle,
      },
      {
        align: 'left',
        field: 'name',
        label: this.$t('DirectoriesCard.name'),
        name: 'name',
        sortable: true,
        style: 'white-space: pre-wrap',
        headerStyle,
      },
    ];
  }

  get card() {
    return cloneDeep(
      this.$store.getters['registryService/services/servicesCard']
    );
  }

  get directoriesRejectServis() {
    return get(this.card, 'rejects', []).filter((i) => i.type === 'service');
  }

  get directoriesRejectDocument() {
    return get(this.card, 'rejects', []).filter((i) => i.type === 'document');
  }

  get dictionaries() {
    return get(this.card, 'dictionaries', []);
  }

  get state() {
    return get(this.card, 'state', 'inProgress');
  }

  get canEdit(): boolean {
    return this.$store.getters['registryService/services/canEdit'];
  }

  private changelist() {
    this.commonModels({
      ListDialog: {
        data: {
          collection: 'dictionaries',
        },
      },
    });
  }

  private toggleDeleteConfim(item = null) {
    this.deleteConfim = !this.deleteConfim;
    this.deleteItem = item;
  }

  private async deleteDictionary() {
    const dictionaries = [get(this.deleteItem, 'id')];
    try {
      const { data: result } = await unlinkService({
        id: get(this.card, 'id'),
        dictionaries,
        modified: get(this.card, 'modified'),
      });
      const card = cloneDeep(
        this.$store.getters['registryService/services/servicesCard']
      );
      card.dictionaries = this.dictionaries.filter(
        (i) => i.id !== this.deleteItem.id
      );
      this.card.modified = result?.modified;
      // todo logically - unlinkDictionary here
      await dictionaryApi.deleteDictionary(dictionaries);
      await this.$store.dispatch(
        'registryService/services/setCardForJson',
        card
      );
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.toggleDeleteConfim();
    }
  }

  private uploadDictionary() {
    this.isUploadDictionaryOpen = true;
  }

  private createUploadedDictionary() {
    if (!this.uploadedCsv) {
      return;
    }
    this.isUploadDictionaryOpen = false;
    const fileNameWithoutExtension = this.uploadedCsv.name.replace(
      /\.[^/.]+$/,
      ''
    );
    const reader = new FileReader();
    reader.readAsText(this.uploadedCsv, 'UTF-8');
    reader.onload = (evt) => {
      const csvText = evt.target.result;
      const csv = this.readCsv(csvText);
      this.openCreateDialog(fileNameWithoutExtension, csv);
    };
    reader.onerror = () => {
      notifyError('Не удалось загрузить файл');
    };
  }

  private openCreateDialog(name, csv) {
    const headers = csv[0];
    const csvBody = csv.slice(1);
    const items = csvBody.map((ln) => {
      const item = {};
      for (let i = 0; i < ln.length; i++) {
        item[headers[i]] = ln[i];
      }
      return item;
    });
    const userMeta = headers
      .filter((h) => h !== 'code' && h !== 'value')
      .map((h) => ({ code: h, name: h }));
    const data = {
      schema: 'Dictionary',
      name,
      id: name,
      documents: items,
      userMeta,
    };
    this.viewDictionary(data, 'create');
  }

  private readCsv(csv) {
    return csv
      .split(/\r\n|\n/)
      .filter((ln) => ln.length > 0)
      .map((line) =>
        line
          .split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/) // Значения могут быть в кавычках
          .map((s) => s.replaceAll('"', ''))
      );
  }

  private viewDictionary(row, mode) {
    this.commonModels({
      DictionaryDialog: {
        data: row,
        mode: mode,
      },
    });
  }

  private commonModels(val) {
    this.$emit('commonModels', val);
  }

  private editReject(reject, mode) {
    this.currentReject = reject;
    this.rejectDialog = true;
    this.rejectDialogMode = mode;
  }

  private deleteReject(reject) {
    const card = cloneDeep(
      this.$store.getters['registryService/services/servicesCard']
    );
    card.rejects = get(this.card, 'rejects', []).filter(
      (i) => i.code !== reject.code
    );
    this.$store.dispatch('registryService/services/setCardForJson', card);
    this.deleteFromDocumentViews(card, reject);
  }

  private deleteFromDocumentViews(card, reject) {
    if (reject.type) {
      card.documents
        .filter(
          (item: { source: string; resultType: string }) =>
            item.source === 'result' &&
            ((reject.type === 'service' &&
              item.resultType === 'rejectService') ||
              (reject.type === 'document' && item.resultType === 'rejectDoc'))
        )
        .forEach((document: { code: string; id: string }) => {
          fetchDocument('ServiceDocument', document.id, 'form').then(
            ({ data: response }) => {
              const forms = response.form || [];
              forms.forEach((form: MetaClassSchemaRaw) => {
                if (Array.isArray(get(form, 'attrList'))) {
                  const existedAttr = form.attrList.find(
                    (item) => item.name === reject.code
                  );
                  if (existedAttr) {
                    form.attrList = form.attrList.filter(
                      (attr) => attr.name !== reject.code
                    );
                    const rejectGroup = form.groupList?.find(
                      (item) => item.name === 'rejects'
                    );
                    if (rejectGroup) {
                      if (!rejectGroup.hasOwnProperty('attrList')) {
                        rejectGroup.attrList = [];
                      }
                      rejectGroup.attrList = rejectGroup.attrList.filter(
                        (attr) => attr !== reject.code
                      );
                    }
                    formApi.updateForm([form]);
                  }
                }
              });
            }
          );
        });
    }
  }
}
</script>
