<template>
  <div class="manual">
    <a ref="downloadBpmn" />
    <div
      class="flex justify-start items-center bg-white q-pa-md q-mt-md q-mx-md rounded-borders"
      v-if="$AC.haveScope(USER_SCOPES.SOCIAL_DICTIONARY_ADMIN)"
    >
      <q-btn
        padding="xs"
        class="text-grey-7 q-mr-md"
        color="grey-3"
        icon="arrow_back"
        @click="goToCriteriaList()"
      />
      <span class="text-h5">{{ $t('criteriaDirectory.editCriterion') }}</span>
    </div>
    <div
      class="q-gutter-y-md row bg-white q-px-lg q-pb-md q-pt-sm q-mt-md q-mx-md rounded-borders"
    >
      <div class="col text-primary q-pa-sm">
        <div class="q-gutter-y-md" :persistent="saving">
          <q-card class="full-width no-shadow">
            <q-form class="full-width no-shadow q-py-md" @submit="submit">
              <div class="row q-qutter-x-md">
                <div class="col">
                  <q-input
                    :disable="model.status === 'ACTIVATED'"
                    v-model="model.name"
                    filled
                    :label="$t('criteriaDirectory.name')"
                    :rules="['requred']"
                  />
                </div>
              </div>

              <div class="row q-qutter-x-md">
                <div class="col">
                  <q-input
                    :disable="model.status === 'ACTIVATED'"
                    v-model="model.description"
                    filled
                    :label="$t('criteriaDirectory.description')"
                  />
                </div>
              </div>

              <q-card :bordered="criteriaTypeIsList" class="no-shadow q-my-md">
                <q-card-section
                  :class="[
                    {
                      'q-pa-none': !criteriaTypeIsList,
                      'q-pb-none': criteriaTypeIsList,
                    },
                  ]"
                >
                  <q-select
                    :disable="model.status === 'ACTIVATED'"
                    filled
                    v-model="model.type"
                    :options="criteriaTypes"
                    :label="$t('criteriaDirectory.type')"
                    emit-value
                    map-options
                    stack-label
                  />
                </q-card-section>
                <q-slide-transition>
                  <q-card-section v-if="criteriaTypeIsList">
                    <q-select
                      :disable="model.status === 'ACTIVATED'"
                      class="q-pb-none"
                      :label="$t('criteriaDirectory.value')"
                      filled
                      v-model="model.values"
                      :rules="[noEmptyValueRule, amountValuesCheck]"
                      use-input
                      use-chips
                      multiple
                      hide-dropdown-icon
                      input-debounce="0"
                      new-value-mode="add"
                    />
                  </q-card-section>
                </q-slide-transition>
              </q-card>

              <div class="q-mt-sm q-mb-sm">
                <base-label-value class="base-label q-gutter-x-md">
                  <template #label>
                    {{ $t('criteriaDirectory.activity') }}
                  </template>
                  <template #value>
                    {{ getStatusLabel(model.status) }}
                  </template>
                </base-label-value>
              </div>

              <q-card
                v-if="model.status === 'DRAFT'"
                bordered
                class="no-shadow q-my-lg"
              >
                <q-card-section
                  class="row justify-between items-center no-wrap"
                >
                  <div class="text-h6">
                    {{ model.processName || 'Процесс' }}
                  </div>
                  <div class="row no-wrap text-no-wrap float-right">
                    <q-btn
                      v-if="!model.processId"
                      flat
                      dense
                      size="16"
                      class="q-ml-sm"
                      text-color="primary"
                      color="white"
                      icon="attach_file"
                      @click="openDownloadDialog()"
                    >
                      <q-tooltip> Загрузить процесс </q-tooltip>
                    </q-btn>
                    <div v-else>
                      <q-btn
                        flat
                        dense
                        size="16"
                        class="q-ml-sm"
                        color="white"
                        text-color="primary"
                        @click="goToBpmnSchema()"
                        unelevated
                        icon="search"
                      >
                        <q-tooltip :delay="500">
                          Открыть в редакторе BPMN
                        </q-tooltip>
                      </q-btn>
                      <q-btn
                        flat
                        dense
                        size="16"
                        class="q-ml-sm"
                        color="white"
                        text-color="primary"
                        unelevated
                        icon="arrow_downward"
                        @click="downloadBpmnSchema"
                      >
                        <q-tooltip> Скачать </q-tooltip>
                      </q-btn>
                      <q-btn
                        flat
                        dense
                        icon="delete"
                        size="16"
                        color="white"
                        text-color="negative"
                        class="q-ml-sm"
                        unelevated
                        @click="toggleDeleteConfim"
                      >
                        <q-tooltip> Удалить </q-tooltip>
                      </q-btn>
                    </div>
                  </div>
                </q-card-section>
              </q-card>
              <div v-else class="q-mt-sm q-mb-sm">
                <base-label-value class="base-label q-gutter-x-md">
                  <template #label>
                    {{ $t('task.process') }}
                  </template>
                  <template #value>
                    <div class="row items-center">
                      <span>{{ model.processName }}</span>
                      <div>
                        <q-btn
                          dense
                          color="white"
                          text-color="primary"
                          icon="arrow_downward"
                          @click="downloadBpmnSchema"
                        >
                          <q-tooltip> Скачать </q-tooltip>
                        </q-btn>
                        <q-btn
                          dense
                          color="white"
                          text-color="primary"
                          @click="goToBpmnSchema()"
                          icon="search"
                        >
                          <q-tooltip :delay="500">
                            Открыть в редакторе BPMN
                          </q-tooltip>
                        </q-btn>
                      </div>
                    </div>
                  </template>
                </base-label-value>
              </div>

              <filters
                :readOnly="model.status === 'ACTIVATED'"
                :value.sync="initialData.filters"
                class="q-mb-lg"
                @changeFilter="changeFilter"
              />

              <changed-fields
                :value.sync="model.changedFields"
                :readOnly="model.status === 'ACTIVATED'"
                :key="model.id"
                class="q-mb-lg"
              />

              <div class="row q-qutter-a-md">
                <div class="col q-qutter-y-md">
                  <q-btn
                    v-if="model.status !== 'ACTIVATED'"
                    class="q-my-md q-mr-md"
                    color="primary"
                    :label="$t('criteriaDirectory.save')"
                    type="submit"
                  />
                  <q-btn
                    v-if="
                      (model.status === 'DRAFT' ||
                        model.status === 'DEACTIVATED') &&
                      model.processId
                    "
                    class="q-my-md q-mr-md"
                    color="primary"
                    label="Сохранить и активировать"
                    @click="changeStatus(true)"
                  />
                  <q-btn
                    v-if="model.status === 'ACTIVATED'"
                    class="q-my-md q-mr-md"
                    color="primary"
                    label="Деактивировать"
                    @click="changeStatus(false)"
                  />
                  <q-btn
                    class="q-my-md"
                    :label="$t('criteriaDirectory.cancel')"
                    color="grey-3"
                    text-color="black"
                    @click="$router.push({ name: 'criteria-directory' })"
                  />
                </div>
              </div>
            </q-form>
          </q-card>
        </div>
      </div>
    </div>

    <q-dialog class="full-width" v-model="deleteConfim">
      <q-card class="no-shadow full-width">
        <q-card-section>
          <div class="text-h6">Вы уверены, что хотите удалить процесс?</div>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn
            @click="
              toggleDeleteConfim();
              unlinkProcess();
            "
            color="primary"
            :label="$t('base.delete')"
          />

          <q-btn
            color="white"
            text-color="primary"
            outline
            @click="toggleDeleteConfim"
            :label="$t('base.undo')"
          />
        </q-card-actions>
      </q-card>
    </q-dialog>
    <DownloadDialog
      :openFormDialog.sync="startDownloadDialog"
      @createData="addFile"
    />
  </div>
</template>

<script lang="ts">
import ReturnToParentView from '@mixins/ReturnToParentView';
import { mixins } from 'vue-class-component';
import { Component, Vue, Watch } from 'vue-property-decorator';
import {
  CriteriaApi,
  CriteriaTypeEnum,
  Criteria,
  CriteriaFilter,
  CriteriaFilterGlobalOperatorEnum,
  CriteriaFilterOperatorEnum,
  CriteriaStatusEnum,
} from '@/openapi/personal-accounts';
import { notifyError, notifySuccess } from '@/utils/notify';
import { noEmptyValueRule } from '@utils/field-validation/basic';
import { USER_SCOPES } from '@/constants/entities/Scope';
import DownloadDialog from '@components/criteria-directory/download_dialog.vue';
import Filters from './components/Filters.vue';
import ChangedFields from '@components/criteria-directory/components/ChangedFields.vue';
import { fetchAttachment } from '@services/registry-service';
import { saveFileViaLink } from '@utils/files';
import {
  DocumentApi,
  Response as ProccesDeleteResponce,
} from '@/openapi/registry-service';
import { cloneDeep, isEqual } from 'lodash';

const criteriaApi = new CriteriaApi();

@Component({
  components: {
    Filters,
    DownloadDialog,
    ChangedFields,
  },
  methods: {
    noEmptyValueRule,
  },
})
export default class createCriteriaCategoryDialog extends mixins(
  ReturnToParentView
) {
  USER_SCOPES = USER_SCOPES;
  startDownloadDialog = false;
  loading = false;
  statusList = true;
  statusFilterValueBoollean = false;
  statusFilterValueData = false;
  deleteConfim = false;
  model: Criteria = {
    schema: 'Criteria',
    name: '',
    description: '',
    type: CriteriaTypeEnum.List,
    values: [],
    status: CriteriaStatusEnum.Draft,
    processId: '',
    processName: '',
    filters: [],
    changedFields: [],
  };

  initialData = this.model;

  dataFilter: CriteriaFilter = {
    filterId: 0,
    guidFilter: '',
    value: '',
    operator: CriteriaFilterOperatorEnum.Equal,
  };

  showAddedFilters = false;
  showFilter = false;
  saving = false;
  filter: Array<any> = [];
  optionsGlobalOperator: CriteriaFilterGlobalOperatorEnum[] = Object.values(
    CriteriaFilterGlobalOperatorEnum
  );

  statusLabels: Record<string, string> = {
    DRAFT: 'Черновик',
    ACTIVATED: 'Активен',
    DEACTIVATED: 'Деактивирован',
  };

  optionsOperator: CriteriaFilterOperatorEnum[] = Object.values(
    CriteriaFilterOperatorEnum
  );

  criteriaTypes: any = [
    { value: 'BOOLEAN', label: 'Флаг' },
    { value: 'NUMBER', label: 'Числовой ' },
    { value: 'TEXT', label: 'Текстовый' },
    { value: 'LIST', label: 'Список значений' },
  ];

  getStatusLabel(status: string): string {
    return this.statusLabels[status];
  }

  get criteriaTypeIsList(): boolean {
    return this.model.type === CriteriaTypeEnum.List;
  }

  amountValuesCheck(values: string[]): true | string {
    if (values !== undefined && values.length > 30) {
      return 'Нельзя вносить больше 30ти';
    }
    return true;
  }

  @Watch('dataCreate.values')
  onDataValuesChange(values: string[]): void {
    if (values !== undefined && values.length > 30) {
      values?.pop();
    }
  }

  clearModel(): void {
    this.model = {
      schema: 'Criteria',
      name: '',
      description: '',
      type: CriteriaTypeEnum.List,
      values: [],
      status: CriteriaStatusEnum.Draft,
      processId: '',
      processName: '',
      changedFields: [],
    };
    this.statusList = false;
    this.showAddedFilters = false;
  }

  created(): void {
    this.init(this.$route.params.id);
  }

  changeStatus(active: boolean): void {
    if (!this.model.name) {
      this.$q.notify({
        color: 'negative',
        icon: 'error',
        message: 'Все поля должны быть заполнены',
      });
      return;
    }
    if (
      this.model.type === 'LIST' &&
      typeof this.model.values === 'undefined'
    ) {
      this.$q.notify({
        color: 'negative',
        icon: 'error',
        message: 'Список значени не заполнен',
      });
      return;
    }
    const activate = {
      status: active ? 'ACTIVATED' : 'DEACTIVATED',
      reqCalculation: active,
    };
    this.submit(activate);
  }

  async submit(activate: any): Promise<void> {
    if (activate.status) {
      this.model = { ...this.model, ...activate };
    } else {
      delete this.model.reqCalculation;
      this.model.status = 'DRAFT';
    }
    this.saving = true;
    this.loading = true;
    try {
      const {
        data: { success },
      } = await criteriaApi.updateCriteria([this.model], {});
      if (success) {
        notifySuccess('Успешно изменено.');
        this.clearModel();
        this.saving = false;
        if (this.initialData?.processId && !this.model.processId) {
          this.deleteProcess(this.initialData.processId);
        }
      }
    } catch (error) {
      if (error instanceof Error) notifyError(error.message);
    }
    this.loading = false;
    this.$router.push({ name: 'criteria-directory' });
  }

  async downloadBpmnSchema(): Promise<void> {
    if (!this.model.processId) {
      console.warn('[Servise][Processes][goToBpmnSchema] Missing schema name');
      return;
    }
    try {
      const xml = await fetchAttachment(
        'Process',
        this.model.processId,
        `${this.model.processName}.bpmn`,
        false
      );
      saveFileViaLink({
        anchor: this.$refs.downloadBpmn as HTMLAnchorElement,
        hrefData:
          'data:application/bpmn20-xml;charset=UTF-8,' +
          encodeURIComponent(xml),
        fileName: `${this.model.processName}.bpmn`,
      });
    } catch (e) {
      if (e instanceof Error) notifyError(e.message.toString());
    }
  }

  addFile(val?: Criteria): void {
    this.startDownloadDialog = false;
    if (val) {
      this.model.processId = val.id;
      this.model.processName = val.name;
    }
  }

  changeFilter(filters: []) {
    this.model.filters = filters;
  }

  toggleDeleteConfim(): void {
    this.deleteConfim = !this.deleteConfim;
  }

  async deleteProcess(id: string): Promise<ProccesDeleteResponce> {
    const { data } = await new DocumentApi().deleteDocument('Process', [id]);
    return data;
  }

  async unlinkProcess(): Promise<void> {
    this.model.processId = '';
    this.model.processName = '';
  }

  async init(id: string): Promise<void> {
    if (!id) return;
    return criteriaApi
      .getCriteria(id, '', {})
      .then((data) => {
        this.initialData = data.data;
        this.model = cloneDeep(this.initialData);
      })
      .catch((error: Error) => {
        notifyError(error.message);
      });
  }

  goToBpmnSchema(): void {
    if (!this.model.processId) {
      console.warn('[Servise][Processes][goToBpmnSchema] Missing schema name');
      return;
    }
    this.$router.push({
      name: 'cards',
      params: {
        id: this.model.processId,
        path: 'processes',
      },
      query: {
        active: 'IndexCriteriaProcess',
        components: 'IndexCriteriaProcess',
        criteria: this.initialData?.id || '',
      },
    });
  }

  openDownloadDialog(): void {
    this.startDownloadDialog = true;
  }

  goToCriteriaList() {
    if (!isEqual(this.model, this.initialData)) {
      this.$q
        .dialog({
          message: 'На странице есть несохраненные изменения. Продолжить?',
          cancel: {
            push: true,
            label: 'Отмена',
          },
          ok: 'ОК',
        })
        .onOk(() => {
          this.returnToParentView('/criteria-directory');
        });
    } else {
      this.returnToParentView('/criteria-directory');
    }
  }
}
</script>

<style lang="scss">
.file-cell {
  white-space: pre-line;
}
.document-card {
  width: 100%;
  max-width: 350px;
}

.grid-item-value {
  overflow: hidden;
  text-overflow: ellipsis;
}
</style>
