import {
  Component,
  Prop,
  Vue,
  ModelSync,
  Emit,
  Watch,
} from 'vue-property-decorator';
import { AccountsSearchFilter } from './accounts-search-filter';
import {
  OrganizationApi,
  RoleApi,
  Role,
  Organization,
  Department,
  DomainApi,
} from '@openapi/idm';

const organizationApi = new OrganizationApi();
const roleApi = new RoleApi();
const domainApi = new DomainApi();

@Component({})
export default class AccountsSearchBar extends Vue {
  @Prop({
    type: Boolean,
    default: false,
  })
  public readonly loading: boolean;

  @Prop({
    type: Boolean,
    default: false,
  })
  public readonly isAdmin: boolean;

  @Watch('filter', { deep: true })
  private filterChange(filter: AccountsSearchFilter) {
    this.filterCount = filter.countFilters();
  }

  @ModelSync('data', 'change', { type: Object })
  public filter: AccountsSearchFilter;

  @Emit('search')
  public executeSearch(): void {
    //
  }

  public resetFilter(): void {
    this.filter = new AccountsSearchFilter();
  }

  public filterVisible = false;
  public filterCount = 0;

  public toggleFilter(): void {
    this.filterVisible = !this.filterVisible;
  }

  loadingRoles = false;
  optionsRoles: Role[] = [];
  optionsOrg: Organization[] = [];
  loadingOrg = false;
  optionsDepart: Department[] = [];

  firstLoad = true;

  /**
   * Функция получения списка организаций
   * @param {string} findOrgString строка из поля ввода поиска в селекте организаций
   */
  async getOrganizations(findOrgString?: string): Promise<void> {
    if (!this.loadingOrg && this.isAdmin) {
      this.loadingOrg = true;
      const query = findOrgString
        ? `fullname=like='%${findOrgString}%' or name=like='%${findOrgString}%'`
        : '';
      await organizationApi
        .searchOrganizations(undefined, query)
        .then((response) => {
          this.optionsOrg = response.data || [];
        })
        .finally(() => {
          this.loadingOrg = false;
        });
    }
  }

  /**
   * Функция получения списка ролей
   * @param {string} findRolesString строка из поля ввода поиска в селекте ролей
   */
  async getRoles(findRolesString?: string): Promise<void> {
    if (!this.loadingRoles && this.isAdmin) {
      this.loadingRoles = true;
      const query = findRolesString
        ? `displayName=like='%${findRolesString}%'`
        : '';
      await roleApi
        .getAllRoles(query)
        .then((response) => {
          this.optionsRoles =
            response.data?.filter((role) => role.ervuRole) || [];
        })
        .finally(() => {
          this.loadingRoles = false;
        });
    }
  }

  /**
   * Функция фильтрации в поле выбора ролей
   * @param {string} val
   * @param {function} update
   */
  async filterRoles(val: string, update: () => void): Promise<void> {
    if (val.length > 1 || val === '') {
      await this.getRoles(val);
      update();
    }
  }

  /**
   * Функция фильтрации в поле выбора ролей
   * @param {string} val
   * @param {function} update
   */
  async filterOrg(val: string, update: () => void): Promise<void> {
    if (val.length > 1 || val === '') {
      await this.getOrganizations(val);
      update();
    }
  }

  /**
   * После выбора организации и не при первом открытии страницы ищем ее департаменты
   */
  @Watch('filter.organizationId')
  private filterOrgHandler(): void {
    if (this.firstLoad) {
      return;
    }
    this.filter.departmentId = '';
    this.loadOptionsDepart();
  }

  async loadOptionsDepart(): Promise<void> {
    this.optionsDepart.splice(0, this.optionsDepart.length);
    if (this.filter.organizationId) {
      const { data } = await domainApi.getDomainChildrenTreeV1(
        this.filter.organizationId,
        1,
        ['Department']
      );
      if (data.leafs) {
        data.leafs.forEach((leaf) => {
          if (leaf.value) {
            // @ts-expect-error: с запроса возвращается NodeTO а ожидается Department
            // такое поведение запроса связано с тем что запрос возвращает любую Ноду из базы
            this.optionsDepart.push(leaf.value);
          }
        });
      }
    }
  }

  async mounted(): Promise<void> {
    if (this.isAdmin) {
      await this.getRoles();
      await this.getOrganizations();
      await this.loadOptionsDepart();
      this.firstLoad = false;
    }
  }
}
