<i18n>
{
  "ru": {
    "ServicesSelect": {
      "cancel": "Отмена",
      "save": "Сохранить",
      "select": "Выбрать услугу",
      "selectAnother": "Выбрать другую услугу",
      "impossibleToChange": "Невозможно поменять услугу в сохраненном расписании",
      "columns": {
        "name": "Название услуги"
      },
      "selected": "Услуга не выбрана | Услуга выбрана | Выбрано {n} услуги | Выбрано {n} услуг",
      "repreatsNTimes": "Не повторяестся ни разу | Не повторяестся | TargetId повторяестся {n} раза | TargetId повторяестся {n} раз",
      "impossibleToSelect": "Нельзя выбрать услугу с повторяющимся targetId"
    }
  },
  "en": {
    "ServicesSelect": {
      "cancel": "Cancel",
      "save": "Save",
      "select": "Select service",
      "selectAnother": "Select another service",
      "impossibleToChange": "Impossible to change service in saved schedule",
      "columns":  {
        "name": "Service name"
      },
      "selected": "No swerice selected | Service is selected | {n} services are selected",
      "repreatsNTimes": "Doesn't repeat | Doesn't repeat | TargetId repeats {n} times",
      "impossibleToSelect": "Impossible to select service with reapitting targetId"
    }
  }
}
</i18n>
<template>
  <div class="service-select">
    <q-skeleton v-if="loading" animation="pulse-y" width="100%" type="QBtn" />
    <template v-else-if="selected.length">
      <q-card
        bordered
        flat
        v-for="service in selected"
        :key="service.id"
        @click="(!isScheduleSaved || !disable) && openPopup()"
        :class="[
          'service-select__card',
          {
            'cursor-pointer': !isScheduleSaved,
          },
        ]"
        :title="
          isScheduleSaved
            ? $t('ServicesSelect.impossibleToChange')
            : $t('ServicesSelect.selectAnother')
        "
      >
        <q-card-section class="q-pa-sm">
          <div class="service-select__name">{{ service.shortName }}</div>
          <div style="font-size: 0.8em">{{ service.targetId }}</div>
        </q-card-section>
      </q-card>
    </template>
    <q-btn
      outline
      color="grey-6"
      text-color="black"
      v-else
      class="full-width"
      :disable="disable"
      @click="openPopup"
    >
      {{ $t('ServicesSelect.select') }}
    </q-btn>
    <q-dialog v-model="popup" persistent>
      <q-card
        :style="{
          maxWidth: '80vw',
          width: '700px',
        }"
      >
        <q-card-section>
          <div class="select-table">
            <q-tabs
              align="right"
              dense
              active-color="green"
              v-model="tab"
              mobile-arrows
            >
              <q-tab name="all" icon="add_circle_outline"></q-tab>
              <q-tab name="selected" icon="task_alt"></q-tab>
            </q-tabs>
            <q-separator />
            <q-tab-panels :value="tab">
              <q-tab-panel name="all">
                <q-table
                  dense
                  class="no-shadow text-grey-9"
                  row-key="id"
                  :selected-rows-label="
                    (number) => $tc('ServicesSelect.selected', number)
                  "
                  :rows-per-page-options="[5, 10, 15]"
                  :columns="columns"
                  :grid="$q.screen.xs"
                  :loading="loading"
                  :data="model"
                  :selection="selection"
                  :selected.sync="selected"
                  @selection="touch"
                >
                  <template v-slot:body-selection="scope">
                    <q-checkbox v-model="scope.selected" />
                  </template>
                  <template v-slot:body-cell-shortName="scope">
                    <q-td :props="scope">
                      <div>
                        {{ scope.row.shortName }}
                      </div>
                      <div class="text-caption">
                        {{ scope.row.targetId }}
                      </div>
                    </q-td>
                  </template>
                </q-table>
              </q-tab-panel>
              <q-tab-panel name="selected">
                <q-table
                  dense
                  class="no-shadow text-grey-9"
                  row-key="id"
                  :selected-rows-label="
                    (number) => $tc('ServicesSelect.selected', number)
                  "
                  :rows-per-page-options="[5, 10, 15]"
                  :columns="columns"
                  :grid="$q.screen.xs"
                  :loading="loading"
                  :data="selected"
                  :selection="selection"
                  :selected.sync="selected"
                  @selection="touch"
                >
                  <template v-slot:body-selection="scope">
                    <q-checkbox v-model="scope.selected" />
                  </template>
                  <template v-slot:body-cell-shortName="scope">
                    <div>
                      {{ scope.row.shortName }}
                    </div>
                    <div class="text-caption">
                      {{ scope.row.targetId }}
                    </div>
                  </template>
                </q-table>
              </q-tab-panel>
            </q-tab-panels>
          </div>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn
            dense
            text-color="primary"
            color="white"
            flat
            :label="$t('ServicesSelect.cancel')"
            @click="clear"
            v-close-popup
          />
          <q-btn
            dense
            text-color="primary"
            color="white"
            :disable="!dirty"
            @click="save"
          >
            {{ $t('ServicesSelect.save') }}
          </q-btn>
        </q-card-actions>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import WeekSchedule from '@components/tickets/components/WeekSchedule.vue';
import { ServiceDTO } from '@openapi/preorder-pgs';
import get from 'lodash/get';
import { OrganizationApi } from '@openapi/registry-service';
import type { Service } from '@openapi/registry-service/api';
import { notifyError } from '@utils/notify';
import { TableColumn } from '@/interfaces';
const organizationApi = new OrganizationApi();

interface Pagination {
  page?: number;
  rowsPerPage?: number;
  descending?: boolean;
  sortBy?: string;
  rowsNumber?: number;
}
interface TableContext {
  pagination: Pagination;
}
interface ServiceShort {
  id: string;
  shortName: string;
  targetId: string;
}
type ServiceValue = Omit<ServiceDTO, 'filter'>;

function hasTargetId<T extends { targetId?: string }>(t: T): boolean {
  return !!t.targetId;
}

@Component({
  components: {
    WeekSchedule,
  },
})
export default class ServicesSelect extends Vue {
  @Prop({ default: false }) isScheduleSaved: boolean;
  @Prop({ default: false }) disable: boolean;
  @Prop({ default: () => [] }) unavelible: string[];
  @Prop({ default: () => [] }) value: ServiceValue[];
  @Prop({ default: 'serviceId' }) valueIdKey: keyof ServiceValue;
  @Prop({ default: 'single' }) selection: 'multiple' | 'single';

  loading = false;
  dirty = false;

  touch(): void {
    this.dirty = true;
  }

  clear(): void {
    this.fetchValues(this.value);
    this.dirty = false;
  }

  tab = 'all';
  popup = false;

  public openPopup(): void {
    this.popup = true;
  }

  public closePopup(): void {
    this.popup = false;
    this.tab = 'all';
  }

  model: ServiceShort[] = [];
  selected: ServiceShort[] = [];
  pagination: Pagination = {
    page: 1,
    rowsPerPage: 5,
    descending: false,
    sortBy: 'name',
    rowsNumber: 0,
  };

  queryString = '';
  fulltextString = '';

  get columns(): TableColumn<ServiceShort>[] {
    return [
      {
        align: 'left',
        field: (val) => get(val, 'shortName', ''),
        label: this.$t('ServicesSelect.columns.name'),
        name: 'shortName',
        sortable: true,
        handlerField: 'id',
        icon: 'people_outline',
      },
    ];
  }

  get userDomainId(): string {
    return get(this.$store.getters['oidcClient/currentUser'], 'domain_id', '');
  }

  get repeatsIndex(): Record<string, number> {
    return this.model.reduce((index, itm) => {
      if (!index[itm.targetId]) {
        index[itm.targetId] = 1;
      } else {
        index[itm.targetId]++;
      }
      return index;
    }, {} as Record<string, number>);
  }

  isServiceUnavelible(targetId: string): boolean {
    return this.unavelible.includes(targetId);
  }

  isServiceDuplicated(targetId: string): boolean {
    return this.repeatsIndex[targetId] > 1;
  }

  @Watch('value', { immediate: true })
  onValueChange(value: ServiceValue[]): void {
    this.fetchValues(value);
  }

  fetchValues(value: ServiceValue[]): void {
    const index = value.reduce((index, itm) => {
      if (itm.serviceId) {
        index[String(itm.serviceId)] = true;
      }
      return index;
    }, {} as Record<string, boolean>);
    this.selected = this.model.filter((itm) => {
      return index[itm.targetId];
    });
  }

  save(): void {
    const values = this.selected.map((itm) => {
      return {
        [this.valueIdKey]: itm.targetId,
      };
    });
    this.$emit('input', values);
    this.closePopup();
  }

  created(): void {
    this.fetch();
  }

  async fetch(): Promise<void> {
    this.loading = true;
    try {
      const { data } = await organizationApi.getOrganization(
        this.userDomainId,
        'services'
      );

      const services: Service[] = get(data, 'services');
      this.model = Object.values(
        services.reduce((model, itm) => {
          if (itm.targetId) {
            model[itm.targetId] = {
              id: itm.id,
              shortName: itm.shortName?.replace(/_[a-z0-9_]+$/i, '') || '',
              targetId: itm.targetId,
            };
          }
          return model;
        }, {} as Record<string, ServiceShort>)
      );
    } catch (error) {
      if (error instanceof Error) notifyError(error.message);
    }
    this.onValueChange(this.value);
    this.loading = false;
  }
}
</script>

<style lang="scss" scoped>
.service-select {
  &__name {
    text-transform: uppercase;
  }
  &__floating-badge {
    position: absolute;
    top: 6px;
    right: 5px;
  }
}
.select-table {
  &__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-left: 1rem;
    padding-right: 1rem;
  }
  &__title {
    font-size: 1.25rem;
  }
}
</style>
