<template>
  <div class="AccountOrganizationsForm">
    <template v-if="haveScopeToChangeOrg">
      <div class="AccountOrganizationsForm__Field">
        <span
          class="AccountOrganizationsForm__FieldLabel"
          :class="{
            AccountOrganizationsForm__FieldLabel_Error: orgRegionIsError,
          }"
        >
          Поиск региона*
        </span>
        <BaseAutocompleteSelect
          :model.sync="regions"
          :async-getter="getRegions"
          label-value="fullname"
          :disable="Boolean(organizations.selected)"
          customPopupContentClass="AccountOrganizationsForm__BaseAutocompleteSelect"
          @value="setRegion"
        />
        <span
          v-if="orgRegionIsError"
          class="AccountOrganizationsForm__ErrorNotifi"
        >
          Выберите регион
        </span>
      </div>
      <div
        class="AccountOrganizationsForm__Field AccountOrganizationsForm__Field_Text"
      >
        ИЛИ
      </div>
      <div class="AccountOrganizationsForm__Field">
        <span
          class="AccountOrganizationsForm__FieldLabel"
          :class="{
            AccountOrganizationsForm__FieldLabel_Error: orgRegionIsError,
          }"
        >
          Поиск организации*
        </span>
        <BaseAutocompleteSelect
          :model.sync="organizations"
          :async-getter="getOrganizations"
          label-value="fullname"
          :disable="Boolean(regions.selected)"
          customPopupContentClass="AccountOrganizationsForm__BaseAutocompleteSelect"
          @value="setOrganization"
        />
        <span
          v-if="orgRegionIsError"
          class="AccountOrganizationsForm__ErrorNotifi"
        >
          Выберите организацию
        </span>
      </div>
    </template>
    <div v-else class="AccountOrganizationsForm__Field">
      <div class="AccountOrganizationsForm__FieldLabel">Организация*</div>
      <div>{{ organizationName }}</div>
    </div>
    <r-select
      class="AccountOrganizationsForm__Field"
      label="Подразделение"
      :options="departments"
      v-model="selectDepartment"
      :disable="!departments.length"
      clearable
      emit-value
      map-options
    />
    <r-input
      class="AccountOrganizationsForm__Field"
      label="Должность"
      v-model="position"
    />
    <div class="AccountOrganizationsForm__Field">
      <span class="AccountOrganizationsForm__FieldLabel">
        Дата и время активации доступа сотрудника
      </span>
      <q-input
        v-model="startDateTime"
        filled
        :mask="inputMask"
        :class="{
          AccountOrganizationsForm__FieldInput_Error: !validDatestring(
            startDateTime
          ),
        }"
        :rules="[rulesDatestring]"
      >
        <template #prepend>
          <q-icon name="event" class="AccountOrganizationsForm__FieldIcon">
            <q-popup-proxy transition-show="scale" transition-hide="scale">
              <q-date v-model="startDateTime" :mask="dateMask" />
            </q-popup-proxy>
          </q-icon>
        </template>

        <template #append>
          <q-icon
            name="access_time"
            class="AccountOrganizationsForm__FieldIcon"
          >
            <q-popup-proxy transition-show="scale" transition-hide="scale">
              <q-time v-model="startDateTime" :mask="dateMask" format24h />
            </q-popup-proxy>
          </q-icon>
        </template>
      </q-input>
    </div>
    <div class="AccountOrganizationsForm__Field">
      <span class="AccountOrganizationsForm__FieldLabel">
        Дата и время отключения доступа сотрудника
      </span>
      <q-input
        v-model="endDateTime"
        filled
        :mask="inputMask"
        :class="{
          AccountOrganizationsForm__FieldInput_Error: !validDatestring(
            endDateTime
          ),
        }"
        :rules="[rulesDatestring]"
      >
        <template #prepend>
          <q-icon name="event" class="AccountOrganizationsForm__FieldIcon">
            <q-popup-proxy transition-show="scale" transition-hide="scale">
              <q-date v-model="endDateTime" :mask="dateMask" />
            </q-popup-proxy>
          </q-icon>
        </template>

        <template #append>
          <q-icon
            name="access_time"
            class="AccountOrganizationsForm__FieldIcon"
          >
            <q-popup-proxy transition-show="scale" transition-hide="scale">
              <q-time v-model="endDateTime" :mask="dateMask" format24h />
            </q-popup-proxy>
          </q-icon>
        </template>
      </q-input>
    </div>
    <div v-if="!isMyAccount">
      <q-toggle v-model="enabledAccount" :label="enabledAccountLabel" />
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import RInput from '@/recruits/components/common/r-input/index.vue';
import RSelect from '@/recruits/components/common/r-select.vue';
import {
  convertDateFromBackendFormat,
  convertDateToBackendFormat,
} from '@utils/format-date';
import { Account } from '@interfaces/entities/Account';
import {
  ListToSelect,
  DepartmentWithLabel,
  AccountOrganizationsData,
} from '@/recruits/components/accounts/utils/types';
import { notifyError } from '@utils/notify';
import get from 'lodash/get';
import BaseAutocompleteSelect from '@components/common/base-autocomplete-select/index.vue';
import {
  LinksApi,
  DepartmentApi,
  RegionApi,
  Region,
  Organization,
} from '@openapi/idm';
import isString from 'lodash/isString';
import {
  VALIDATION_CHECKS,
  VALIDATION_RULES,
} from '@/recruits/utils/validation-rules';

const linksApiIdm = new LinksApi();
const departmentApi = new DepartmentApi();
const regionApi = new RegionApi();

const DEPARTMENT = 'Department';
const ORGANIZATION = 'Organization';
const REGION = 'Region';

@Component({
  components: {
    RInput,
    RSelect,
    BaseAutocompleteSelect,
  },
})
export default class AccountOrganizationsForm extends Vue {
  @Prop({ default: null })
  accountData: Account | null;

  @Prop({ default: false }) isMyAccount: boolean;

  @Prop({}) submitFunction: (accountData: AccountOrganizationsData) => void;

  @Prop({ default: 0 }) triggerSubmit: number;

  regions: ListToSelect<Region> = {
    search: null,
    records: [],
    selected: null,
  };

  organizations: ListToSelect<Organization> = {
    search: null,
    records: [],
    selected: null,
  };

  departments: DepartmentWithLabel[] = [];
  selectDepartment: DepartmentWithLabel | null = null;

  position = '';
  startDateTime = '';
  endDateTime = '';
  enabledAccount = true;

  @Watch('accountData', { immediate: true, deep: true })
  private async accountDataHandler(): Promise<void> {
    if (this.accountData) {
      this.position = this.accountData.position || '';
      this.enabledAccount =
        this.accountData.enabled === undefined
          ? true
          : this.accountData.enabled;

      if (this.accountData.userDomain?.schema === REGION) {
        this.regions.search = '';
        this.regions.selected = this.accountData.userDomain;
      }

      if (this.accountData.userDomain?.schema === ORGANIZATION) {
        this.organizations.search = '';
        this.organizations.selected = this.accountData.userDomain;
      }

      if (this.accountData.userDomain?.schema === DEPARTMENT) {
        try {
          const { data } = await departmentApi.getDepartment(
            this.accountData.userDomain.id,
            'parent'
          );
          // запрос возвращает Department с еще полем parent, но согласно апи возвращается только Department
          // это особенность хранения данных, поэтому используем lodash/get
          this.organizations.selected = get(data, 'parent');
          this.$nextTick(() => {
            this.selectDepartment = this.accountData?.userDomain
              ? {
                  ...this.accountData.userDomain,
                  label: this.accountData.userDomain.fullname,
                }
              : null;
          });
        } catch (e) {
          console.log(e);
        }
      }

      if (this.accountData.start) {
        this.startDateTime = convertDateFromBackendFormat(
          this.accountData.start,
          this.dateMask
        );
      }
      if (this.accountData.finish) {
        this.endDateTime = convertDateFromBackendFormat(
          this.accountData.finish,
          this.dateMask
        );
      }
    } else {
      this.regions.selected = null;
      this.regions.records = [];
      this.regions.search = null;
      this.organizations.selected = null;
      this.organizations.records = [];
      this.organizations.search = null;
      this.selectDepartment = null;
      this.position = '';
      this.startDateTime = '';
      this.endDateTime = '';
      this.enabledAccount = true;
    }
  }

  get dateMask(): string {
    return this.$store.getters['i18N/localeMask'].datetime;
  }

  get inputMask(): string {
    return this.$store.getters['i18N/localeMask'].inputDatetime;
  }

  /**
   * Свойство для проверки наличия scope CLOUD_ADMIN или SECURITY_ADMINISTRATOR
   * @return {boolean}
   */
  get haveScopeToChangeOrg(): boolean {
    return this.$AC.haveOneOfScope([
      this.$AC.scopes.CLOUD_ADMIN,
      this.$AC.scopes.SECURITY_ADMINISTRATOR,
    ]);
  }

  get enabledAccountLabel(): string {
    return this.enabledAccount
      ? 'Доступ сотруднику разблокирован'
      : 'Доступ сотруднику заблокирован';
  }

  get organizationName(): string {
    return (
      this.regions.selected?.fullname ||
      this.organizations.selected?.fullname ||
      this.selectDepartment?.fullname ||
      '-'
    );
  }

  get orgRegionIsError(): boolean {
    return (
      !this.regions.selected &&
      !this.organizations.selected &&
      (isString(this.regions.selected) ||
        isString(this.organizations.selected) ||
        isString(this.regions.search) ||
        isString(this.organizations.search))
    );
  }

  @Watch('organizations.selected', { immediate: true })
  private async organizationsSelectedHandler(): Promise<void> {
    if (this.organizations.selected) {
      this.getDepartments(this.organizations.selected.id);
    } else {
      this.selectDepartment = null;
      this.departments = [];
    }
  }

  get validateForm(): boolean {
    return (
      (!!this.selectDepartment ||
        !!this.regions.selected ||
        !!this.organizations.selected) &&
      (!this.startDateTime?.length ||
        this.validDatestring(this.startDateTime)) &&
      (!this.endDateTime?.length || this.validDatestring(this.endDateTime))
    );
  }

  @Watch('validateForm', { immediate: true })
  private validateFormHandler(val: boolean): void {
    this.$emit('validateForm', val);
  }

  @Watch('triggerSubmit')
  private triggerSubmitHandler(): void {
    let tempUserDomain;
    if (this.selectDepartment?.id) {
      tempUserDomain = {
        id: this.selectDepartment.id,
        schema: DEPARTMENT,
        fullname: this.selectDepartment.fullname,
      };
    } else if (this.organizations?.selected?.id) {
      tempUserDomain = {
        id: this.organizations.selected.id,
        schema: ORGANIZATION,
        fullname: this.organizations.selected.fullname,
      };
    } else if (this.regions?.selected?.id) {
      tempUserDomain = {
        id: this.regions.selected.id,
        schema: REGION,
        fullname: this.regions.selected.fullname,
      };
    }

    this.submitFunction({
      start: this.startDateTime
        ? convertDateToBackendFormat(this.startDateTime) ||
          new Date().toISOString()
        : new Date().toISOString(),
      enabled: this.enabledAccount,
      schema: 'Account',
      'user-domain': tempUserDomain?.id || '',
      userDomain: tempUserDomain,
      position: this.position,
      finish: this.endDateTime
        ? convertDateToBackendFormat(this.endDateTime) || ''
        : 'emptyValue',
    });
  }

  // функция проверки корректности ввода даты в строке формата boolean | string
  rulesDatestring(datestring: string): boolean | string {
    return datestring.length ? VALIDATION_RULES.datestring(datestring) : true;
  }

  // функция проверки корректности ввода даты в строке формата boolean
  validDatestring(datestring: string): boolean {
    return datestring.length ? VALIDATION_CHECKS.datestring(datestring) : true;
  }

  getRegions(): Promise<Region[] | undefined> {
    return new Promise((resolve) => {
      const arrQuery = [
        this.regions.search
          ? `(fullname=searchphrase='${this.regions.search}' or name=searchphrase='${this.regions.search}')`
          : null,
      ];
      const currentQuery = arrQuery.filter((filter) => !!filter).join(' and ');

      regionApi
        .pagingRegions(undefined, 1, 20, undefined, currentQuery)
        .then(({ data }) => resolve(data.records))
        .catch(() => {
          throw new Error('[components][forms][EmployeesCreateAccountForm]');
        });
    });
  }

  getOrganizations(): Promise<Organization[] | undefined> {
    return new Promise((resolve) => {
      const arrQuery = [
        this.organizations.search
          ? `(fullname=searchphrase='${this.organizations.search}' or inn=searchphrase='${this.organizations.search}' or ogrn=searchphrase='${this.organizations.search}')`
          : null,
      ];
      const currentQuery = arrQuery.filter((filter) => !!filter).join(' and ');

      this.$store
        .dispatch('idm/organizations/dispatchOrganizations', {
          page: 1,
          perPage: 20,
          fulltext: currentQuery,
        })
        .then((data) => {
          resolve(data);
        });
    });
  }

  setOrganization(val: Organization): void {
    if (val) {
      this.regions.selected = null;
    }
  }

  setRegion(val: Region): void {
    if (val) {
      this.organizations.selected = null;
    }
  }

  async getDepartments(parentId: string): Promise<void> {
    if (parentId) {
      const response = await linksApiIdm
        .searchLinks(ORGANIZATION, parentId, DEPARTMENT)
        .catch((e) => {
          notifyError(e.toString());
        });
      // запрос возвращает Department[], но согласно апи возвращается Document[]
      // это особенность хранения данных, поэтому используем lodash/get
      this.departments = get(response, 'data', []).map(
        (el: DepartmentWithLabel) => {
          return { ...el, label: el.fullname };
        }
      );
    }
  }
}
</script>

<style lang="scss" scoped>
.AccountOrganizationsForm {
  &__FieldLabel {
    font-family: 'Golos Text', sans-serif;
    font-style: normal;
    display: inline-block;
    cursor: pointer;
    font-size: 12px;
    line-height: 16px;
    margin-bottom: 4px;
    font-weight: 600;
    color: rgba(2, 12, 18, 0.58);
    transition: 0.3s;

    &_Error {
      color: #c10525;
    }
  }

  &__FieldInput {
    &_Error {
      border-color: #c10525;
    }
  }

  &__Field {
    margin-bottom: 15px;
    position: relative;

    &_Text {
      color: #020c12ba;
    }
    &::v-deep {
      .q-field--with-bottom {
        padding-bottom: 0;
      }

      .q-field--auto-height {
        .q-field__control {
          background: #e5edf5;
          border-bottom: 1px solid rgba(1, 72, 116, 0.18);
          overflow: hidden;
          text-overflow: ellipsis;
        }
        &.q-field--labeled .q-field__control-container {
          padding-top: 9px;
        }
        .q-field__native {
          line-height: 22px;
          span {
            text-overflow: ellipsis;
            white-space: nowrap;
            max-width: 100%;
            overflow: hidden;
          }
        }
      }

      .q-field--filled.q-field--highlighted .q-field__control:before {
        opacity: 0;
      }

      .q-field--filled .q-field__control:after {
        height: 0;
      }

      .q-field--focused {
        &.q-field--filled .q-field__control {
          background: white;
          border: 1px solid #0148742e;
        }
      }

      .q-field--filled .q-field__control {
        background: #e5edf5;
        height: 40px;
        min-height: 40px;
        .q-field__marginal {
          height: 40px;
        }
        // border-bottom: 1px solid rgba(1, 72, 116, 0.18);
      }
    }
  }

  &__FieldIcon {
    cursor: pointer;
  }

  &__TogglesBlock {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
  }
  &__ErrorNotifi {
    position: absolute;
    top: calc(100% + 16px * 0.125);
    font-size: 12px;
    color: #c10525;
  }
}
</style>

<style lang="scss">
.AccountOrganizationsForm {
  &__BaseAutocompleteSelect {
    max-width: 500px !important;
  }
}
</style>
