<template>
  <q-form class="q-gutter-y-md text-right" @submit.prevent="createPanel">
    <div class="row items-start">
      <q-select
        class="height-limit col-3 q-px-sm"
        v-model="form.report"
        filled
        flat
        dense
        :label="$t('performancePanel.panelForm')"
        borderless
        :options="reportOptions"
      />
      <template v-if="form.report.value">
        <SelectRegions
          v-if="$AC.haveOneOfScope([USER_SCOPES.RF_OBSERVER_SCOPE, USER_SCOPES.FED_STAT_OBSERVER])"
          v-model="form.region"
          :label="$t('performancePanel.region')"
          label-value="fullname"
          class="height-limit col-3 q-px-sm"
          :map-options="true"
          :emit-value="true"
          :isSpecialReport="isSpecialReport"
          :reducedServices="!!rfObserverServices.length"
          @allRegions="e => setAllRegions(e)"
          dense
        />
        <SelectOrganizations
          v-if="$AC.haveOneOfScope([
            USER_SCOPES.REGION_OBSERVER, 
            USER_SCOPES.RF_OBSERVER_SCOPE, 
            USER_SCOPES.REGION_ADMIN,
            USER_SCOPES.FED_STAT_OBSERVER,
            USER_SCOPES.REG_STAT_OBSERVER
          ])"
          class="height-limit col-3 q-px-sm"
          v-model="form.organisation"
          filled
          flat
          dense
          options-dense
          :label="$t('performancePanel.organisation')"
          :isSpecialReport="isSpecialReport"
          @allOrganisations="(value, options) => setAllOrganisations(value, options)"
          borderless
          :emit-value="false"
          :regions="form.region"
          @departmentConditions="(v) => setDepartment(v)"
        />
        <SelectServices
          v-if="form.report.selectServices"
          class="height-limit col-3 q-px-sm"
          v-model="form.service"
          filled
          flat
          dense
          options-dense
          :label="$t('performancePanel.service')"
          borderless
          :emit-value="false"
          :disable="!form.organisation[0]"
          :organisation="orgForServices"
        />
      </template>
    </div>
    <div class="row justify-between q-mt-sm q-px-sm" v-if="form.report.value">
      <div class="col-auto">
        <x-date-range
          class="height-limit col-6"
          :from.sync="form.from"
          :to.sync="form.to"
          :listStyle="{ display: 'flex' }"
          :fromDefaultView="form.report.fromDefaultView"
          :toDefaultView="form.report.toDefaultView"
        />
      </div>
      <div class="col-auto">
        <q-btn type="submit" color="primary" :disable="!isFormFilled">
          {{ $t('performancePanel.form') }}
        </q-btn>
      </div>
    </div>
  </q-form>
</template>

<script lang="ts">
import { Component, Watch, Vue } from 'vue-property-decorator';
import { USER_SCOPES } from '@constants/entities/Scope';
import SelectOrganizations from './select-organizations.vue';
import SelectServices from './select-services.vue';
import SelectRegions from './select-regions.vue';
import SelectBase from './select-base.vue';
import XDateRange from './x-date-range.vue';
import clone from 'lodash/clone';
import { getAuthorizationType, AUTH_LOCAL } from '@/utils/save-profile-info';
import { emptyReport, reports, Report } from '../config';
import { notifyInfo, notifyError } from '@utils/notify';
import { doMathWithDate, convertDateFormat } from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';
import {
  CollapsedProfileApi,
  Region,
  RegionApi,
  GraphApi,
  DepartmentApi,
  DomainForStats,
} from '@openapi/idm';
import {
  Service,
  ServiceForStats,
  ServiceApi,
  OrganizationApi,
  Organization,
  Department,
} from '@openapi/registry-service';
import { cloneDeep } from 'lodash';

const departmentApi = new DepartmentApi();
const graphApi = new GraphApi();
const collapsedProfileApi = new CollapsedProfileApi();
const serviceApi = new ServiceApi();
const organizationApi = new OrganizationApi();

interface DepartmentWithParent extends Department {
  parent: Organization;
}

type Form = {
  region: Region[];
  from: string;
  to: string;
  report: Report;
  service?: Service | null;
  organisation: any[] | [];
  departments?: DomainForStats[];
  excludeSubordinates?: boolean;
}

@Component({
  components: {
    SelectOrganizations,
    SelectServices,
    SelectRegions,
    XDateRange,
    SelectBase,
  },
})
export default class performancePanel extends Vue {
  USER_SCOPES = USER_SCOPES;
  currentUserRegion = '';
  protected allServices: ServiceForStats[] | [] = [];
  protected rfObserverServicesId: string[] | [] = [];
  protected rfObserverServices: ServiceForStats[] | [] = [];

  private reportOptions = reports;
  currentRegion: Region[] = [];

  private allRegions = false;
  private allOrganisations = false;

  protected form: Form = {
    region: this.currentRegion,
    from: '',
    to: '',
    report: clone(emptyReport),
    service: null,
    organisation: [],
    departments: [],
    excludeSubordinates: false,
  };

  protected parentOrganization: Organization | null = null;

  get isFormFilled(): boolean {
    if (this.allRegions) {
      return (
        !!this.rfObserverServices.length && !!this.form.from && !!this.form.to
      );
    }
    if (this.allOrganisations) {
      return !!this.form.from && !!this.form.to;
    }
    let report = true;
    if (this.form.report.selectServices) {
      report = false;
      if (this.form.service?.id) {
        report = true;
      }
    }
    return (
      !!this.form.report &&
      !!this.form.region[0] &&
      !!this.form.organisation[0] &&
      !!this.form.from &&
      !!this.form.to &&
      report
    );
  }

  get isSpecialReport(): boolean {
    return (
      this.form.report.id === '933d2404-cd4e-4ee1-9bbc-c9335a1b6225' ||
      this.form.report.id === '293afd56-7722-431a-af70-1f9d851e4bc7' ||
      this.form.report.id === '265ba172-ad08-45ab-b76c-dde0dda31adc' ||
      this.form.report.id === '4d817091-96a5-4528-8fc8-d3c9af6a197d'
    );
  }

  get orgForServices() {
    if (this.parentOrganization) {
      return this.parentOrganization;
    } else {
      return this.form.organisation[0];
    }
  }

  created(): void {
    const myDate = new Date();
    const subtractOneWeek = doMathWithDate('subHours', myDate, 168);

    const convertTo = convertDateFormat(
      myDate,
      DateFormat.date,
      DateFormat.invertedDate
    );
    const convertFrom = convertDateFormat(
      subtractOneWeek,
      DateFormat.date,
      DateFormat.invertedDate
    );

    this.form.from = convertFrom;
    this.form.to = convertTo;

    this.setDefaultValues();
  }

  @Watch('isSpecialReport', { immediate: true })
  async setServisesFromAccount(): Promise<void> {
    if (
      this.isSpecialReport &&
      this.$AC.haveOneOfScope([
        USER_SCOPES.RF_OBSERVER_SCOPE,
        USER_SCOPES.FED_STAT_OBSERVER,
        USER_SCOPES.REGION_OBSERVER,
        USER_SCOPES.REGION_ADMIN,
        USER_SCOPES.REG_STAT_OBSERVER,
      ])
    ) {
      const currentUserId = this.$store.getters['oidcClient/currentUser'].sub;
      const { data } = await collapsedProfileApi.getCollapsedProfileByAccountId(
        currentUserId || ''
      );
      this.rfObserverServicesId = data.sectionFilters?.services || [];
      await this.fetchAllServices();
      this.rfObserverServices = this.allServices.filter((e: ServiceForStats) =>
        this.rfObserverServicesId.includes(e.id as never)
      );
    }
  }

  @Watch('form.report.selectServices', { immediate: true })
  clearService(value: boolean): void {
    if (!value) {
      this.form.service = null;
    }
  }

  protected async setDefaultValues() {
    if (
      this.$AC.haveOneOfScope([
        USER_SCOPES.RF_OBSERVER_SCOPE,
        USER_SCOPES.FED_STAT_OBSERVER,
      ])
    ) {
      return;
    }

    let currentUserOrganization: Organization | null = null;
    let currentUserDepartment: Department | null = null;

    if (
      this.$AC.haveOneOfScope([
        USER_SCOPES.SIGNED_SPECIALIST,
        USER_SCOPES.ORG_STAT_OBSERVER,
        USER_SCOPES.REGION_OBSERVER,
        USER_SCOPES.REGION_ADMIN,
        USER_SCOPES.REG_STAT_OBSERVER,
      ])
    ) {
      const currentUser = this.$store.getters['oidcClient/currentUser'] || null;
      let currentUserRegionId;
      const authType = getAuthorizationType(currentUser);
      if (authType === AUTH_LOCAL || !!currentUser.ogrn) {
        try {
          currentUserOrganization = await organizationApi
            .getOrganization(currentUser.domain_id)
            .then(({ data }) => data);
          currentUserRegionId = currentUserOrganization?.regionId;
        } catch (e) {
          currentUserDepartment = await departmentApi
            .getDepartment(currentUser.domain_id, 'parent')
            .then(({ data }) => data);

          this.parentOrganization = await organizationApi
            .getOrganization(
              (currentUserDepartment as DepartmentWithParent)?.parent.id
            )
            .then(({ data }) => data);
          currentUserRegionId = this.parentOrganization?.regionId;
        }
      } else {
        currentUserRegionId = currentUser.domain_id;
      }

      const currentUserRegion: Region = await new RegionApi()
        .getRegion(currentUserRegionId)
        .then(({ data }) => data);

      if (currentUserRegion) {
        this.form.region.push(currentUserRegion);
        this.currentUserRegion = currentUserRegion.code;
      }

      if (
        this.$AC.haveOneOfScope([
          USER_SCOPES.SIGNED_SPECIALIST,
          USER_SCOPES.ORG_STAT_OBSERVER,
        ])
      ) {
        this.form.organisation = currentUserOrganization
          ? [{ ...currentUserOrganization }]
          : [{ ...currentUserDepartment }];
      }
    }
  }

  setDepartment(conditions: {
    excludeDepartments: boolean;
    departments: DomainForStats[];
  }): void {
    if (conditions.excludeDepartments) {
      this.form.excludeSubordinates = true;
      this.form.departments = [];
    } else {
      this.form.excludeSubordinates = false;
      this.form.departments = conditions.departments;
    }
  }

  createPanel(): void {
    const form = cloneDeep(this.form);
    if (form.departments?.length) {
      form.organisation = [...form.departments];
      delete form.departments;
    }

    if (
      this.isSpecialReport &&
      this.rfObserverServices.length &&
      this.allRegions
    ) {
      const fedObserverForm = {
        region: '',
        from: form.from,
        to: form.to,
        report: form.report,
        service: [...this.rfObserverServices],
        organisation: [],
        allRegions: 'true',
        excludeSubordinates: this.form?.excludeSubordinates,
      };
      this.$emit('createPanel', fedObserverForm);
    } else if (this.isSpecialReport && this.allOrganisations) {
      const regionObserverForm = {
        // region: form.region,
        from: form.from,
        to: form.to,
        report: form.report,
        organisation: this.form.organisation,
        excludeSubordinates: this.form?.excludeSubordinates,
      };
      this.$emit('createPanel', regionObserverForm);
    } else {
      this.$emit('createPanel', form);
    }
    // this.clearForm();
    setTimeout(() => {
      notifyInfo(this.$t('performancePanel.panelAppended').toString());
    }, 2000);
  }

  clearForm(): void {
    this.form = {
      region: [],
      from: '',
      to: '',
      report: clone(emptyReport),
      service: undefined,
      organisation: [],
      departments: [],
    };
  }

  protected async fetchAllServices(): Promise<ServiceForStats[]> {
    if (this.allServices.length) {
      return this.allServices;
    } else {
      const fetchOptions = await serviceApi
        .searchServiceForStats()
        .then(({ data }) => {
          return data || [];
        })
        .catch((e) => {
          notifyError(e.message.toString());
          return [];
        });
      this.allServices = fetchOptions;
      return this.allServices;
    }
  }

  setAllRegions(value: boolean): void {
    if (value) {
      this.form.region = [];
      this.allRegions = true;
    } else {
      this.allRegions = false;
    }
  }

  setAllOrganisations(value: boolean, options: DomainForStats[]): void {
    if (value) {
      this.form.organisation = options;
      this.allOrganisations = true;
    } else {
      this.form.organisation = [];
      this.allOrganisations = false;
    }
  }
}
</script>

<style lang="sass">
.info-filter
  display: flex
.height-limit .q-field__native span
  white-space: nowrap
  max-width: 900px
  overflow: hidden
  text-overflow: ellipsis
  max-height: 27px
.clear-btn
  position: absolute
  right: -12px
  top: -12px
  margin-top: 0
</style>
