<template>
  <div class="q-mt-md row items-center">
    <template v-if="canEdit">
      <span>{{ $t('peopleCanEditService') }}:</span>
      <select-base
        class="select-editors"
        :options="options"
        :loading="loading"
        v-bind="$attrs"
        use-input="10"
        option-value="id"
        option-label="fullname"
        v-on="$listeners"
      />
    </template>
    <template v-else>
      <span>{{ $t('youCanNotEditService') }}</span>
      <q-select
        class="select-editors"
        :options="usersCantEdit"
        option-label="fullname"
        :value="null"
      />
    </template>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { oidcClientComputed } from '@state/modules/oidc-client';
import map from 'lodash/map';
import SelectBase from './select-base.vue';
import sortBy from 'lodash/sortBy';
import { AccountApi, GraphApi } from '@openapi/idm';
import { notifyError } from '@utils/notify';
import { USER_SCOPES } from '@/constants/entities/Scope';
import cloneDeep from 'lodash/cloneDeep';

interface ReportAccount {
  firstname: string;
  middlename: string;
  surname: string;
  fullname: string;
  shortname: string;
  id: string;
}

type ReportAccountOption = ReportAccount | { separator: true };

const accountApi = new AccountApi();
const graphApi = new GraphApi();

function getNameStrings(
  firstname?: string,
  middlename?: string,
  surname?: string
) {
  const names = [surname, firstname, middlename].filter(Boolean) as string[];
  let fullname;
  let shortname;

  if (names.length) {
    fullname = names.join(' ');

    for (let i = names.length; --i > 0; ) {
      names[i] = `${names[i][0]}.`;
    }

    shortname = names.join(' ');
  } else {
    fullname = shortname = 'Неизвестный';
  }

  return {
    fullname,
    shortname,
  };
}

@Component({
  inheritAttrs: false,
  components: {
    SelectBase,
  },
})
export default class SelectUsers extends Vue.extend({
  computed: {
    ...oidcClientComputed,
  },
}) {
  @Prop({ type: Array }) selected: Object[];

  protected get userId(): string {
    return this.currentUser.sub;
  }

  public options: any[] = [];
  prevOptions: any[] = [];
  public loading = false;
  usersCantEdit: any[] = [];

  private employeeFilterOptions(options: any): any[] {
    const employees: ReportAccountOption[] = [];

    options.forEach((employee: any) => {
      const { surname, firstname, middlename } = employee.person || {};

      employee = {
        ...employee,
        ...getNameStrings(firstname, middlename, surname),
      };

      if (employee.id !== this.userId) {
        employees.push(employee);
      } else {
        employees.unshift(
          employee
          /* , { separator: true } */
        );
      }
    });

    return employees;
  }

  protected last = 0;

  created() {
    this.getAllUsers('all');
    this.prevOptions = cloneDeep(this.selected);
  }

  get canEdit(): boolean {
    return this.$store.getters['registryService/services/canEdit'];
  }

  protected async getAllUsers(organizations: any[] | 'all'): Promise<void> {
    if (organizations !== 'all') {
      if (!organizations || !organizations.length) {
        this.options = [];

        return;
      }
      if (typeof organizations[0] !== 'string') {
        organizations = map(organizations, 'id');
      }
    }
    this.loading = true;
    const last = ++this.last;

    let options = await (organizations === 'all'
      ? accountApi
          .searchAccounts(
            undefined,
            undefined,
            undefined,
            undefined,
            'person,roles'
          )
          .then(({ data }) => data)
          .catch(() => {
            throw new Error(
              '[components][reports][components][select-accounts][searchAccounts]'
            );
          })
      : graphApi
          .flatten(
            'Organization',
            'incoming',
            organizations,
            1,
            ['Account'],
            undefined,
            ['Account:person']
          )
          .then(({ data }) => data)
    )
      // @ts-ignore
      .catch((e: any) => {
        notifyError(e.message.toString());
        return [];
      });

    options = options.filter((op: any) =>
      op.roles?.some(
        (r: any) =>
          r.name === USER_SCOPES.MAIN_SERVICE_ADMIN ||
          r.name === USER_SCOPES.SERVICES_CONSTRUCT
      )
    );

    options = sortBy(options, (el: any) => {
      const { surname, firstname, middlename } = el.person || {};
      const fio = getNameStrings(firstname, middlename, surname);
      return fio.fullname.toLowerCase().trim();
    });

    options = this.employeeFilterOptions(options);
    if (!this.canEdit && this.prevOptions?.length) {
      this.usersCantEdit = options
        .filter((u: any) => this.prevOptions.includes(u.id));
    }

    if (this.selected?.length) {
      const selectedObjects = options.filter((u: any) =>
        this.selected.some((s) => s === u.id)
      );
      this.$emit('input', selectedObjects);
    }

    if (this.last === last) {
      this.options = options;
    }
    this.loading = false;
  }
}
</script>

<style lang="scss" scoped>
.select-editors {
  max-width: 400px;
}
</style>

<i18n>
{
  "ru": {
    "youCanNotEditService": "Вы не можете редактировать услугу",
    "peopleCanEditService": "Может редактировать"
  },
  "en": {
    "youCanNotEditService": "You can not edit this service",
    "peopleCanEditService": "Can edit"
  }
}
</i18n>
