<template>
  <div v-if="common.active === 'roles'" class="q-pb-md">
    <q-card v-if="!loading" class="no-shadow q-pb-md q-gutter-y-md q-mx-md">
      <div class="q-py-md q-mx-md">
        <div
          class="q-mt-lg q-pl-md q-pr-xs"
          style="border: 1px solid #ebebeb; border-radius: 3px"
        >
          <div class="q-gutter-y-md q-py-md full-width">
            <div class="row flex justify-between">
              <div class="text-h6 text-grey-9">
                {{ $t('departments.RolesCard.chosenRoles') }}
              </div>
            </div>
            <q-tree
              ref="tree"
              class="col-12 col-sm-6"
              :nodes="rolesFormatted"
              node-key="id"
              :ticked.sync="rolesList"
              :filter="rolesList.toString()"
              :filter-method="filterSelected"
              default-expand-all
              no-results-label="Ни одной роли не выбрано"
            />
            <q-btn
              class="q-mt-md"
              unelevated
              color="primary"
              :label="$t('departments.RolesCard.edit')"
              type="button"
              @click="editRoles"
            />
          </div>
        </div>
      </div>
    </q-card>
    <div v-if="loading" style="padding: 200px">
      <q-inner-loading :showing="loading">
        <q-spinner-gears color="primary" size="50px" />
      </q-inner-loading>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { BaseCardCommon } from '@interfaces/components';
import { Role, DomainApi, LinksApi } from '@openapi/idm';
import { QTree } from 'quasar';
import get from 'lodash/get';
import { ERVU_SCOPES } from '@constants/entities/Scope';
import { DepartmentWithParent } from '@models/DepartmentWithParent';

const domainApi = new DomainApi();
const linksApi = new LinksApi();

declare interface IQTree {
  label: string;
  id: string;
  disabled?: boolean;
  children?: Array<QTree>;
}

@Component({})
export default class DepartmentCardRoles extends Vue {
  @Prop({}) private common?: BaseCardCommon;
  @Prop({}) private model: DepartmentWithParent;

  private loading = false;
  private rolesFormatted: Array<Role> = [];
  private rolesList: Array<Role> = [];
  private solutions: Array<any> = [];
  private organisationId = '';

  private isErvuMode = this.$AC.haveOneOfScope(Object.values(ERVU_SCOPES));

  @Watch('model', {
    immediate: true,
  })
  modelWatcher(val: DepartmentWithParent) {
    if (val?.parent) {
      this.organisationId = val.parent.id ?? '';
      this.initSolutions();
    }
  }

  private async initSolutions(): Promise<void> {
    this.loading = true;

    linksApi
      .pagingLinks(
        'Organization',
        this.model.parent.id,
        'Solution',
        undefined,
        undefined,
        undefined,
        undefined,
        'roles'
      )
      .then(({ data }) => {
        this.solutions = data.records || [];

        domainApi
          .getDomain(get(this.model, 'id', ''), 'roles')
          .then(({ data }) => {
            const roles = get(data, 'roles', []);

            this.rolesFormatted = this.changeProperties(this.solutions);

            if (this.isErvuMode) {
              this.rolesFormatted = this.filterNonErvuRoles(this.rolesFormatted);
            }

            if (roles) {
              this.rolesList = roles.map((itemRole: Role) => itemRole.id);
            }
            this.loading = false;
            this.$nextTick().then(() => {
              // @ts-ignore
              this.$refs.tree?.expandAll();
              this.rolesFormatted = this.rolesFormatted.map((item) => {
                return { ...item };
              });
            });
          })
          .catch(() => {
            throw new Error(
              '[components][cards][departments][Roles][domainApi]'
            );
          });
      })
      .catch(() => {
        throw new Error('[components][cards][departments][Roles][linksApi]');
      });
  }

  private filterSelected(node: IQTree, filter: string): boolean {
    const checkArray = filter.split(',');
    return checkArray.includes(node.id);
  }

  private changeProperties(arr: Array<any>): Array<any> {
    if (arr && arr instanceof Array) {
      return arr
        .filter((item) => item.roles)
        .map(function changeList(item) {
          const returnObj = {
            id: item.id,
            label: item.name,
            ...item,
          };

          if (item.roles && item.roles instanceof Array) {
            returnObj.children = item.roles.map(changeList);
          }
          return returnObj;
        });
    }
    return [];
  }

  // фильтруем все ветки у которых нет ролей с флажком ervuRole == true
  private filterNonErvuRoles(nodes: Array<any>) {
    return nodes.map(node => {
      return {
        ...node,
        children: node.children.filter((role: Role) => role.ervuRole).map((r: Role) => ({
          ...r,
          label: r.displayName,
        })),
      }
    }).filter(node => node.children && node.children.length);    
  }

  private editRoles(): void {
    this.$store.dispatch('wf/processes/dispatchProcess', {
      processKey: 'AssignRolesToOrganizationProcess',
      data: {
        organizationId: this.model?.parent?.id,
        domain: this.model?.id,
        departmentId: this.model?.id,
        isErvu: this.isErvuMode ? true : undefined,
      },
    });
    this.loading = true;
  }
}
</script>
