<template>
  <div class="q-gutter-y-md">
    <q-input
      v-model="search"
      dense
      filled
      debounce="1000"
      :placeholder="$t('reports.searchPlaceholder')"
      @input="startSearch"
      @keydown.enter="startSearch"
      @keydown.esc="search = ''"
    >
      <template #prepend>
        <q-icon name="search" />
      </template>
    </q-input>

    <q-slide-transition>
      <q-card v-show="visible" bordered flat>
        <q-card-section>
          <div class="row q-gutter-x-md" style="margin-bottom: -16px">
            <div
              v-for="(option, i) in options"
              :key="i"
              class="q-mb-md row q-gutter-x-sm items-center"
            >
              <p class="q-ma-none">
                {{ $t(option.label) }}
              </p>
              <component
                v-bind="option.props"
                :is="option.component"
                v-model="filter[option.name]"
                :regions="filter.regions"
                :style="`min-width: 20em; max-width:40em; ${option.style}`"
                v-on="option.listeners"
              />
            </div>
          </div>
        </q-card-section>
        <q-btn
          dense
          flat
          class="absolute-top-right"
          color="grey-7"
          icon="close"
          size="10px"
          @click="RESetFilter"
        />
      </q-card>
    </q-slide-transition>
  </div>
</template>

<script lang="ts">
import XDateRange from '@components/statements/components/x-date-range.vue';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import map from 'lodash/map';
import reduce from 'lodash/reduce';
import isDate from 'lodash/isDate';
import { oidcClientComputed } from '@state/modules/oidc-client';
import { StatementsSearchQuery } from '@components/statements';
import { SearchBarRefs } from '@/components/common/base-search-bar';
import { flatten, mapOptionsResults } from '@components/reports/utils';
import SelectAccounts from './select-accounts.vue';
import SelectRegions from './select-regions.vue';
import SelectOrganizations from './select-organizations.vue';
import SelectBase from './select-base.vue';
import SelectEvery from './select-every.vue';

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

export interface Option {
  label?: string;
  value?: string;
}

@Component({
  components: {
    SelectAccounts,
    SelectRegions,
    SelectOrganizations,
    SelectBase,
    SelectEvery,
    XDateRange,
  },
})
export default class ReportsSearchBar extends AccountsCreateInjection {
  $refs!: SearchBarRefs;
  @Prop() protected baseReport!: any;
  @Prop({
    required: true,
  })
  query!: StatementsSearchQuery;

  protected get visibleColums() {
    return this.baseReport?.columns?.search || [];
  }

  protected visible = false;
  protected search = '';

  protected columns: Array<any> = [
    {
      field: 'params.regions',
      label: 'reports.columns.region',
      name: 'regions',
      component: 'select-regions',
      props: {
        multiple: true,
      },
      fieldMap: 'id',
    },
    {
      field: 'params.organizations',
      label: 'reports.columns.organization',
      name: 'organizations',
      component: 'select-organizations',
      props: {
        multiple: true,
      },
      fieldMap: 'id',
    },
    {
      field: 'params.accounts',
      label: 'reports.columns.accounts',
      name: 'accounts',
      component: 'select-accounts',
      props: {
        multiple: true,
      },
      fieldMap: 'id',
    },
    {
      auto: true,
      field: 'auto.startDate',
      label: 'reports.columns.startDateFirst',
      name: 'startDate',
      component: 'x-date-input',
      props: {
        dense: true,
        filled: true,
      },
    },
    {
      auto: true,
      field: 'auto.every',
      label: 'reports.columns.every',
      name: 'every',
      component: 'select-every',
    },
  ];

  protected get options() {
    return this.columns.filter(
      ({ name, required, auto }) =>
        !auto && (required || this.visibleColums.includes(name))
    );
  }

  @Watch('query', { deep: true })
  queryHandler(): void {
    this.parseQueryParams();
  }

  protected get userid() {
    // @ts-ignore
    return this.currentUser.sub;
  }

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

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

  protected RESetFilter(): void {
    this.filter = this.options.reduce((o, { name }) => {
      o[name] = null;

      return o;
    }, Object.create(null));
    this.startSearch();
  }

  protected filter = {};

  protected startSearch(): void {
    const query: string[] = [];
    let { search } = this;
    const filter = map(
      flatten(mapOptionsResults(this.options, this.filter)),
      (value: any, key) => {
        if (!value || !value.length) {
          return;
        }

        if (Array.isArray(value)) {
          return `${key}=in=(${value.join(',')})`;
        }
        if (isDate(value)) {
          if (key === 'endDate') {
            // fixme обобщить обработку
            const toPlus = new Date(value);

            toPlus.setDate(toPlus.getDate() + 1);

            return `${key}<${toPlus}`;
          }

          return `${key}>=${value}`;
        }

        return `${key}==${value}`;
      }
    )
      .filter(Boolean)
      .join(' and ');

    if (filter) {
      query.push(filter);
    }

    if (search && /^\d+$/g.test(search)) {
      query.push(search);
    }
    this.$emit('query', query.map(q => `${q}`).join(' and '));
  }

  parseQueryParams(): void {
    this.filter = this.options.reduce((o, { name }) => {
      o[name] = null;

      return o;
    }, Object.create(null));
  }

  protected async created(): Promise<void> {
    this.parseQueryParams();
  }
}
</script>

<style lang="sass">
.m-search-bar .q-field__control-container > .q-field__native.row.items-center > span
  white-space: nowrap
  text-overflow: ellipsis
  overflow: hidden

.m-search-bar
  justify-content: space-between
  background: white
  //#F2F2F2
  color: #757575
</style>
