<template>
  <div class="q-gutter-y-md">
    <q-input
      v-model="filter.search"
      dense
      filled
      debounce="1000"
      placeholder="Наименование объекта"
      @input="startSearch"
      @keydown.enter="startSearch"
      @keydown.esc="filter.search = ''"
    >
      <template #prepend>
        <q-icon name="search" />
      </template>
      <template #append>
        <q-btn dense flat icon="settings" round @click="toggleFilter" />
      </template>
    </q-input>

    <q-slide-transition>
      <q-card v-show="filter.visible" bordered flat>
        <div class="row q-pa-md q-gutter-x-md" style="margin-bottom: -16px">
          <div class="q-mb-md row q-gutter-x-sm items-center">
            <p class="q-ma-none">
              {{ $t('registries.status') }}
            </p>
            <q-select
              v-model="filter.status"
              filled
              stretch
              flat
              dense
              borderless
              multiple
              style="min-width: 20em"
              :emit-value="true"
              option-value="label"
              :options="statusOptions"
              @input="handleStatusChange"
            >
              <template #option="scope">
                <q-item v-bind="scope.itemProps" v-on="scope.itemEvents">
                  <q-item-section side>
                    <q-checkbox
                      :value="scope.selected"
                      @input="scope.itemEvents.click"
                    />
                  </q-item-section>
                  <q-item-section>
                    <q-item-label v-html="scope.opt.label" />
                  </q-item-section>
                </q-item>
              </template>
            </q-select>
          </div>

          <div class="q-mb-md row q-gutter-x-sm items-center">
            <p class="q-ma-none">
              {{ $t('registries.dates') }}
            </p>
            <q-field borderless dense style="min-width: 20em">
              <x-date-range
                :from.sync="filter.from"
                :to.sync="filter.to"
                @input="handleRangeChange"
              />
            </q-field>
          </div>

          <div
            v-if="$listeners['save-data']"
            class="q-mb-md row q-gutter-x-sm items-center"
          >
            <q-btn
              color="primary"
              label="Сформировать выгрузку"
              @click="saveData"
            />
          </div>
        </div>
      </q-card>
    </q-slide-transition>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import {
  EmployeeOption,
  Filter,
  Option,
} from '@components/statements/components/search-bar.vue';
import map from 'lodash/map';
import { oidcClientComputed } from '@state/modules/oidc-client';
import XDateRange from '@components/statements/components/x-date-range.vue';
import {
  convertDateFormat,
  convertDateFormatWithoutLocale,
} from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';
import { SearchBarRefs } from '@components/common/base-search-bar/index';
import { REG_ORDER_ID } from '@components/registries/search-bars/search-bar.vue';

class AccountsCreateInjection extends Vue.extend({
  computed: {
    ...oidcClientComputed,
  },
}) {}

@Component({
  components: {
    XDateRange,
  },
})
export default class AccreditationSearchBar extends AccountsCreateInjection {
  $refs!: SearchBarRefs;
  protected filter: Filter = {
    search: '',
    status: [],
    employee: [],
    from: '',
    to: '',
    fromDecision: '',
    toDecision: '',
    visible: false,
  };

  protected startSearch(): void {
    const fulltext: string[] = [];
    const query: string[] = [];
    let { search } = this.filter;
    const { status, from, to, employee } = this.filter;

    if (search) {
      search = search.replace(/\\/g, '');
      if (REG_ORDER_ID.test(search)) {
        const q = [];
        q.push(`document.resRegNumber=like=*${search}*`);
        q.push(`applicant.inn=='${search}'`);
        q.push(`applicant.ogrn=='${search}'`);
        query.push(q.join(' or '));
      } else {
        fulltext.push(`document.resNumber=search='${search}'`);
        fulltext.push(`document.resNumber=searchprefix='${search}'`);
        fulltext.push(`document.resApplicant=search='${search}'`);
        fulltext.push(`document.resApplicant=searchprefix='${search}'`);
      }
    }
    if (status.length) {
      query.push(
        status.map((value) => `document.resRegStatus==${value}`).join(' or ')
      );
    }
    if (employee.length) {
      query.push(employee.map((e) => `assigneeId==${e.value}`).join(' or '));
    }
    if (from) {
      query.push(
        `finishDate>=${convertDateFormat(from, '', DateFormat.invertedDate)}`
      );
    }
    if (to) {
      const toPlus = new Date(to as any);
      toPlus.setDate(toPlus.getDate() + 1);
      query.push(
        `finishDate<${convertDateFormat(toPlus, '', DateFormat.invertedDate)}`
      );
    }

    const qObj = {
      query: query.join(' and '),
      fulltext: fulltext.join(' or '),
    };
    this.$emit('query', qObj);
  }

  protected toggleFilter(): void {
    this.filter.visible = !this.filter.visible;
  }

  protected saveData(): void {
    this.$emit('save-data');
  }

  protected async created(): Promise<void> {
    await this.$store.dispatch('idm/accounts/dispatchAccounts', {
      expand: 'person',
      page: 1,
      perPage: 50,
      handler: 'my',
    });
    this.employeeOptions = this.accountsRecords.map(
      ({ id, person }: { id: any; person: any }) => {
        let label = 'Неизвестный';

        if (person && typeof person === 'object') {
          label = `${person.surname || ''} ${person.firstname || ''} ${
            person.middlename || ''
          } `;
        }

        return {
          label,
          value: id,
          checked: true,
        };
      }
    );
  }

  handleRangeChange() {
    const result = ['', ''];

    if (this.filter.from !== null) {
      result[0] = convertDateFormatWithoutLocale(this.filter.from);
    }

    if (this.filter.to !== null) {
      result[1] = convertDateFormatWithoutLocale(this.filter.to);
    }
    this.startSearch();
  }

  handleEmployeeChange() {
    this.startSearch();
  }

  handleStatusChange(): void {
    this.startSearch();
  }

  private get accountsRecords() {
    return this.$store.getters['idm/accounts/accountsRecords'];
  }

  protected get selectedDate(): string {
    const out = [
      convertDateFormat(
        this.filter.from || this.filter.to,
        '',
        DateFormat.date
      ),
    ];

    return out.length ? out.join(' - ') : '';
  }

  protected get selectedStatus(): string {
    return this.filter.status.length
      ? this.filter.status.map((e) => e.label).join(', ')
      : '';
  }

  protected get selectedEmployee(): string {
    return this.employeeFilterChecked.length
      ? this.employeeFilterChecked.map((e) => e.label).join(', ')
      : '';
  }

  protected employeeOptions = [];
  protected employeeSearch = '';

  protected async getEmployees(val: string) {
    this.employeeSearch = val;
    this.$refs.employee.refresh();
  }

  protected get employeeFilterOptionsDefault(): EmployeeOption[] {
    return [
      {
        label: 'Текущий',
        value: this.userid,
        checked: false,
      },
      {
        label: 'Не назначен',
        value: 'null',
        checked: false,
      },
    ];
  }

  protected filterOutDefault({ value }: EmployeeOption): boolean {
    return !this.employeeFilterOptionsDefault.some((d) => d.value === value);
  }

  protected get employeeFilterOptions(): EmployeeOption[] {
    const def = this.employeeFilterOptionsDefault;
    const checked = this.filter.employee.filter(this.filterOutDefault);
    const employeeSearch = this.employeeSearch
      .replace(/[^\s'`a-zа-яё-]/i, '')
      .trim();

    let employeeFilterOptions: EmployeeOption[] = [];

    if (employeeSearch) {
      const employeeSearchRegExp = new RegExp(
        employeeSearch.replace(/\s+/g, '\\S*\\s+'),
        'i'
      );

      employeeFilterOptions = this.employeeOptions.filter(
        ({ label, value }: Option) =>
          employeeSearchRegExp.test(label as string) &&
          !def.some((d) => d.value === value) &&
          !checked.some((d) => d.value === value)
      );
    }

    const result: EmployeeOption[] = [{ separator: true }];

    if (checked.length) {
      result.push(...checked);
    }
    if (employeeFilterOptions.length) {
      result.push(...employeeFilterOptions);
    }

    if (result.length === 1) {
      return def;
    }

    return def.concat(result);
  }

  protected get employeeFilterChecked(): EmployeeOption[] {
    return this.employeeFilterOptions.filter((e) => e.checked);
  }

  protected get statusOptions(): Option[] {
    return map(
      this.$store.getters['registryService/referenceBooks/referenceBooks']
        .accreditation_it_1_0_1__application_status || {},
      (label, value) => ({ value, label: label.description })
    );
  }

  protected get userid() {
    // @ts-ignore
    return this.currentUser?.sub ?? null;
  }
}
</script>
