<template>
  <q-card class="no-shadow">
    <q-form @submit="handleSave">
      <q-card-section>
        <div class="text-h6">
          {{ cardTitle }}
        </div>
        <div class="row q-mt-md">
          <q-input
            class="col-8"
            v-model="outerStatementId"
            :loading="loading"
            filled
            dense
            placeholder="Введите id заявления донора"
          >
            <template v-slot:append>
              <q-icon name="check" color="positive" v-if="isOuterStatement" />
              <q-icon
                name="error"
                color="negative"
                v-if="outerStatementError"
              />
            </template>
          </q-input>
        </div>
      </q-card-section>
      <q-card-section>
        <table class="q-table--horizontal-separator q-table">
          <thead>
            <tr>
              <th class="text-left">Тип</th>
              <th class="text-left">Наименование</th>
              <th class="text-left">Значение</th>
              <th class="text-left" />
              <th class="text-left" />
            </tr>
          </thead>

          <tbody>
            <tr class="q-tr" v-for="(item, idx) in items" :key="item.id">
              <td class="q-td vertical-top">
                <q-select
                  v-model="item.type"
                  :options="types"
                  emit-value
                  :rules="[requiredHandler]"
                  map-options
                  filled
                  dense
                  class="q-p-none"
                />
              </td>
              <td class="q-td vertical-top">
                <q-input v-model="item.name" filled dense />
              </td>
              <td class="q-td vertical-top">
                <NodeTreeStatementSelect
                  v-model="item.value"
                  :statement="outerStatement"
                  :wrapped-in-curly-braces="false"
                />
              </td>
              <td class="q-td vertical-top">
                <div v-if="item.type === FieldType.Dictionary">
                  <span>
                    {{ item.dictionary ? item.dictionary.name : '' }}
                  </span>
                  <q-btn
                    class="table-button"
                    color="primary"
                    icon="search"
                    :label="$t('services.export.select')"
                    @commonModels="commonModels"
                    @click="onOpenDictDialog(idx)"
                  />
                </div>
              </td>
              <td class="q-td text-right vertical-top">
                <q-btn
                  class="table-button"
                  type="button"
                  color="red"
                  :label="$t('registries.objectCard.delete')"
                  @click="removeItem(item.id)"
                />
              </td>
            </tr>
          </tbody>
        </table>
      </q-card-section>

      <q-card-actions align="right">
        <q-btn
          type="button"
          icon="add"
          color="primary"
          :label="$t('registries.table.addRow')"
          @click="pushItem"
        />

        <q-btn
          type="submit"
          icon="create"
          :loading="saving"
          :label="$t('registries.objectCard.save')"
          color="primary"
        >
          <template #loading>
            <q-spinner-gears />
          </template>
        </q-btn>
      </q-card-actions>
    </q-form>
    <q-dialog
      class="full-width"
      v-model="isDictSelectorOpen"
      @close="() => (dictSelectingItemIndex = -1)"
    >
      <DictSelector @select="onDictSelected" />
    </q-dialog>
  </q-card>
</template>

<script lang="ts">
import { Component, Vue, Watch, Prop } from 'vue-property-decorator';
import { v4 as getUUID } from 'uuid';
import cloneDeep from 'lodash/cloneDeep';
import { DocumentApi } from '@openapi/document-registry';
import NodeTreeStatementSelect from './NodeTreeStatementSelect.vue';
import isEmpty from 'lodash/isEmpty';
import { notifyError } from '@/utils/notify';
import isEqual from 'lodash/isEqual';
import DictSelector from './DictSelector.vue';
import { FieldType } from './types';

const documentApi = new DocumentApi();

@Component({
  components: {
    NodeTreeStatementSelect,
    DictSelector,
  },
})
export default class StatementsExportMapping extends Vue {
  @Prop({ required: true }) value: any;
  @Prop({ default: 'Маппинг межведов' }) cardTitle: string;

  FieldType = FieldType;
  dialogOpen = false;
  saving = false;
  outerStatementId = '';
  outerStatementError = false;
  outerStatement: {} = {};
  isDictSelectorOpen = false;
  loading = false;
  items: MappingTableColumn[] = [];
  types = [
    { label: 'Строка', value: FieldType.String },
    { label: 'Да/нет', value: FieldType.Boolean },
    { label: 'Словарь', value: FieldType.Dictionary },
    { label: 'Дата', value: FieldType.Date },
  ];
  dictSelectingItemIndex = -1;

  @Watch('value', { deep: true, immediate: true })
  onMappingChange(value: any[]) {
    if (!isEqual(this.items, value)) {
      this.setItems();
    }
    if (!value.length) {
      this.pushItem();
    }
  }

  get isOuterStatement() {
    return !isEmpty(this.outerStatement);
  }

  @Watch('outerStatementId', { immediate: true })
  setOuterStatementId() {
    this.outerStatementError = false;
    this.outerStatement = {};
    if (this.outerStatementId.trim().length === 36) {
      this.loading = true;
      documentApi
        .getDocument(
          'Applications',
          this.outerStatementId,
          'applicant, delegate, interDepartmentReq, payments, relatives'
        )
        .then(({ data: statement }) => {
          this.outerStatement = statement;
          this.loading = false;
          this.items.forEach((i) => i);
        })
        .catch(() => {
          this.outerStatementError = true;
          notifyError('Заявление не найдено');
        })
        .finally(() => (this.loading = false));
    }
  }

  @Watch('items', { deep: true })
  setEmptyItem() {
    this.$emit('input', this.items);
  }

  requiredHandler(val: string): boolean | string {
    return (!!val && val.length > 0) || 'Поле обязательно для заполнения';
  }

  setItems() {
    this.items = cloneDeep(this.value);
  }

  pushItem() {
    this.items.push({
      id: getUUID(),
      type: FieldType.String,
      name: '',
      value: '',
      dictionary: {
        id: '',
        name: '',
      },
    });
  }

  removeItem(id: string) {
    this.items = this.items.filter((item) => item.id !== id);
  }

  setValue(val: string, item: MappingTableColumn) {
    const currentItemIndex = this.items.findIndex((el) => el.id === item.id);
    this.items[currentItemIndex].value = val;
  }

  handleSave(): void {
    const noEmptyItems = this.items.filter((item) => item.name && item.value);
    this.$emit('input', noEmptyItems);
    this.$emit('save');
  }

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

  onInputValue(v: string, idx: number) {
    console.log(v, idx);
    this.$set(this.items, idx, v);
  }

  onDictSelected(dict: any) {
    if (this.dictSelectingItemIndex !== -1) {
      this.items[this.dictSelectingItemIndex].dictionary = {
        id: dict.id,
        name: dict.name,
      };
      this.isDictSelectorOpen = false;
      this.dictSelectingItemIndex = -1;
    }
  }

  onOpenDictDialog(idx: number) {
    this.dictSelectingItemIndex = idx;
    this.isDictSelectorOpen = true;
  }
}

export interface MappingTableColumn {
  id: string;
  type: string;
  name: string;
  value: string;
  dictionary?: {
    id: string;
    name: string;
  };
}
</script>

<style lang="scss" scoped>
.table-button {
  height: 40px;
}
</style>