<template>
  <div>
    <div class="bg-white rounded-borders q-pa-md">
      <q-btn-toggle
        class="q-pb-md"
        name="year"
        v-model="year"
        flat
        unelevated
        toggle-color="grey-8"
        color="grey-6"
        :options="[
          {label: '2022', value: '2022'},
          {label: '2023', value: '2023'},
        ]"
      />
      <div class="row ">
        <q-range
          class="col-6 q-mt-xl"
          v-model="range"
          markers
          :min="0"
          :max="11"
          drag-range
          color="grey-8"
          label-always
          switch-label-side
          :left-label-value="monthLabels[range.min]"
          :right-label-value="monthLabels[range.max]"
        />
        <div class="col-2">
          <q-btn outline class="q-ml-xl" v-if="showAcept" @click="setPeriod"> Сформировать </q-btn>
        </div>
      </div>
    </div>
    <div class="layout">
      <div class="q-pa-sm">
        <div class="list ">
          <div v-for="region, index in regions" :key="region.id">
            <q-btn
              :ref="region.id"
              :data-key="index"
              class="list_btn q-mb-xs full-width"
              text-color="grey-8"
              color="white"
              size="sm"
              @click="() => setRegion(region, index)"
            >
              {{
                region.fullname.length > 50
                  ? region.fullname.slice(0, 50) + '…'
                  : region.fullname
              }}
            </q-btn>
          </div>
        </div>
      </div>
      <div
        v-if="panels.length"
        :class="panels.length > 1 ? 'cards-grid-2' : 'cards-grid-1'"
      >
        <div
          v-for="card in panels"
          :key="card.instanceId"
          class="q-pa-sm "
          style="position: relative"
        >
          <q-card class="full-height column no-shadow">
            <q-card-section class="card-header" v-if="card.title">
              <div class="title text-center">
                {{ card.title }}
              </div>
              <div v-if="card.range">
                <div v-if="card.range" class="card-details"> 
                  {{ card.range }} 
                </div>
              </div>
            </q-card-section>
            <q-card-section class="col relative-position">
              <vue-friendly-iframe
                v-if="card.type === 'iframe'"
                class="iframe"
                class-name="iframe"
                :src="card.src"
                name="panel"
              />
            </q-card-section>
          </q-card>
        </div>
      </div>
      <div class="q-pa-sm">
        <div class="list">
          <div v-for="service, index in services" :key="service.targetId">
            <q-btn
              :ref="service.id"
              :data-key="index"
              class="list_btn q-mb-xs full-width"
              color="white"
              text-color="grey-8"
              size="sm"
              @click="() => setService(service, index)"
            >
              {{
                service.shortNameStat.length
                  ? service.shortNameStat.slice(0, 50) + '…'
                  : service.shortNameStat
              }}
            </q-btn>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { RegionApi, Region } from '@/openapi/idm/api';
import { Component, Vue, Watch } from 'vue-property-decorator';
import { notifyError } from '@utils/notify';
import sortBy from 'lodash/sortBy';
import { ServiceApi, ServiceForStats } from '@openapi/registry-service';
import { PanelOptions, Panel } from './InfoPanel.vue';
import {
  convertDateFromBackendFormat,
  convertDateFormatWithoutLocale,
  DateFormat,
  convertDateFormat,
  getCurrentValueFromDate,
} from '@utils/format-date';
import { v4 } from 'uuid';
import { isEmpty } from 'lodash';
import { QBtn } from 'quasar';

const regionApi = new RegionApi();
const serviceApi = new ServiceApi();

const paramsToUrl = (params: any) => {
  let url = '';
  for (const prop in params) {
    if (params[prop]?.length) {
      const pathParts = url.split('/');
      const lastPathPart = pathParts[pathParts.length - 1];
      const nextSymbol = lastPathPart.includes('?') || lastPathPart.includes('#') ? '&' : '?';
      const newParam = `${nextSymbol}${prop}=${params[prop]}`;
      url += newParam;
    }
  }
  return url;
};

function generateUrl(params: PanelOptions): string {
  const url = `/stat-chart-component/${params.report.id}`;
  const dateStringTo = convertDateFromBackendFormat(
    params.to,
    DateFormat.invertedDate
  );
  const urlParams = {
    updateInterval: '3600000000000',
    from: convertDateFromBackendFormat(
      params.from,
      DateFormat.invertedDatetime
    ).replace(' ', '%20'),
    to: convertDateFromBackendFormat(
      dateStringTo + ' 23:59:59.999',
      DateFormat.invertedDatetime
    ).replace(' ', '%20'),
    organizations: params.organisation?.length
      ? params.organisation.map((d: Record<string, unknown>) => d.id)
      : 'empty',
    services: params.service?.length
      ? params.service
          ?.filter((el: { targetId: string }) => el.targetId)
          .map((d: { targetId: string }) => d.targetId)
      : params.service?.targetId || 'empty',
    showTitle: 'false',
    allRegions: params.allRegions,
    excludeSubordinates: params.excludeSubordinates ? 'true' : 'false',
    regions: (params.region?.length && params.region[0]?.code) || 'empty',
  };
  return url + paramsToUrl(urlParams);
}

@Component({})
export default class InteractivePanel extends Vue {
  loading = false;
  showAcept = false;
  year = '2023';
  from = '';
  to = '';
  range: Range = {
    min: 0,
    max: 2,
  };

  currentRegion = {};
  currentService = {};

  get serviceParams(): PanelOptions {
    return {
      region: [],
      from: this.from,
      to: this.to,
      report: {
        value: 'serviceRating',
        fullTitle: '',
        label: 'Рейтинг услуг',
        id: '3e951f89-d67c-448a-a281-ab77f2205bc8',
      },
      excludeSubordinates: false,
      service: [],
    };
  }

  get regionParams(): PanelOptions {
    return {
      region: [],
      from: this.from,
      to: this.to,
      report: {
        value: 'regionRating',
        fullTitle: '',
        label: 'Рейтинг субъектов РФ',
        id: '842549e0-0855-424f-90a3-aca9a9a121f5',
      },
      excludeSubordinates: false,
      service: [],
    };
  }

  monthLabels = {
    0: 'Январь',
    1: 'Февраль',
    2: 'Март',
    3: 'Апрель',
    4: 'Май',
    5: 'Июнь',
    6: 'Июль',
    7: 'Август',
    8: 'Сентябрь',
    9: 'Октябрь',
    10: 'Ноябрь',
    11: 'Декабрь',
  };

  regions: Region[] = [];
  services: ServiceForStats[] = [];
  allServices: ServiceForStats[] = [];

  private panels: Panel[] = []

  @Watch('currentRegion')
  setCurrentRegion(region: Region) {
    if (!isEmpty(region)) {
      this.serviceParams.service = [];
      this.panels = [];
      this.serviceParams.region = [{ code: region.code }];
      this.createPanel(this.serviceParams);
    }
  }

  @Watch('currentService')
  setCurrentService(service: ServiceForStats) {
    if (!isEmpty(service)) {
      this.regionParams.region = [];
      this.panels = [];
      this.regionParams.service = service;
      this.createPanel(this.regionParams);
    }
  }

  @Watch('range', { deep: true })
  setRange(range: Range, previousRange: Range): void {
    if (!isEmpty(range)) {
      this.setDate(this.year, range);
      this.showAcept = true;
    }
  }

  @Watch('year', { deep: true })
  setYear(year: string, previousYear: string): void {
    if (!isEmpty(year) && year !== previousYear) {
      this.setDate(year, this.range);
      this.showAcept = true;
    }
  }

  protected async created(): Promise<void> {
    this.loading = true;

    const today = new Date();
    const firstDayOfYear = new Date(today.getFullYear(), 0, 1);
    const lastDayOfMonth = new Date(
      today.getFullYear(),
      today.getMonth() + 1,
      0
    );
    this.from = convertDateFormat(
      firstDayOfYear,
      DateFormat.invertedDate,
      DateFormat.invertedDate
    )
    this.to = convertDateFormat(
      lastDayOfMonth,
      DateFormat.invertedDate,
      DateFormat.invertedDate
    );

    const regions = await (regionApi
      .searchRegions()
      .then(({ data }) => data)
      .catch((e) => {
        notifyError(e.message.toString());

        return [];
      }) as unknown) as Region[];
    await this.fetchAllServices();

    this.range.max = getCurrentValueFromDate('month', today);

    this.services = this.filterService(this.allServices);
    this.regions = sortBy(regions, (el: { fullname?: string }) =>
      el.fullname?.toLowerCase().trim()
    );

    this.createPanel(this.regionParams);
    this.createPanel(this.serviceParams);
    this.loading = false;
  }

  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;
    }
  }

  protected filterService(services: ServiceForStats[]): ServiceForStats[] {
    const filterServices = services.reduce(
      (acc: ServiceForStats[], service: ServiceForStats) => {
        if (acc.find((el) => el.targetId === service.targetId)) return acc;
        if (service.targetId && service.shortNameStat) {
          return [...acc, service];
        }
        return acc;
      },
      []
    );
    return sortBy(filterServices, (el) =>
      el.shortNameStat?.toLowerCase().trim()
    );
  }

  createPanel(params: any): void {
    const url = generateUrl(params);
    const panel = {
      type: 'iframe',
      src: url,
      ...(params.report.selectServices
        ? { title: `${params.report.label} "${params.service?.shortName}" ` }
        : { title: params.report.label }),
      fullTitle: params.report.fullTitle,
      range: `${convertDateFormatWithoutLocale(
        params.from,
        DateFormat.date
      )} - ${convertDateFormatWithoutLocale(params.to, DateFormat.date)}`,
      organisationName:
        params.organisation?.length && params.organisation[0].fullname,
      instanceId: v4(),
      queryDefinition: params.report.id,
    };
    console.log('params.report.id >>> ', params.report.id);
    this.panels.push(panel);
  }

  prevActiveService = ''; // todo refactor
  prevActiveRegion = ''; // todo refactor

  setService(service: ServiceForStats): void {
    this.currentService = service;

    if (this.prevActiveRegion) {
      const prevBtn = this.$refs[this.prevActiveRegion] as QBtn[];
      prevBtn[0]?.$el.classList.remove('active_btn');
    }
    this.prevActiveRegion = '';
    if (this.prevActiveService) {
      const prevBtn = this.$refs[this.prevActiveService] as QBtn[];
      prevBtn[0]?.$el.classList.remove('active_btn');
    }

    const serviceBtn = this.$refs[service.id] as QBtn[];
    serviceBtn[0]?.$el.classList.add('active_btn');

    this.prevActiveService = service.id;
  }

  setRegion(region: Region): void {
    this.currentRegion = region;

    if (this.prevActiveService) {
      const prevBtn = this.$refs[this.prevActiveService] as QBtn[];
      prevBtn[0]?.$el.classList.remove('active_btn');
    }
    this.prevActiveService = '';
    if (this.prevActiveRegion) {
      const prevBtn = this.$refs[this.prevActiveRegion] as QBtn[];
      prevBtn[0]?.$el.classList.remove('active_btn');
    }

    const regionBtn = this.$refs[region.id] as QBtn[];
    regionBtn[0]?.$el.classList.add('active_btn');

    this.prevActiveRegion = region.id;
  }

  setDate(year: string, range: Range): void {
    const monthFrom = Number(range.min);
    const monthTo = Number(range.max);
    const startDate = new Date(Number(year), monthFrom, 1);
    const endDate = new Date(Number(year), monthTo + 1, 0);

    this.from = convertDateFormat(startDate, DateFormat.invertedDate, DateFormat.invertedDate);
    this.to = convertDateFormat(endDate, DateFormat.invertedDate, DateFormat.invertedDate);
  }

  setPeriod(): void {
    if (this.panels.length > 1) {
      this.panels = [];
      this.createPanel(this.regionParams);
      this.createPanel(this.serviceParams);
    } else {
      if (
        this.panels[0].queryDefinition ===
        '3e951f89-d67c-448a-a281-ab77f2205bc8'
      ) {
        this.panels = [];
        this.createPanel(this.serviceParams);
      } else {
        this.panels = [];
        this.createPanel(this.regionParams);
      }
    }
    this.showAcept = false;
  }
}

type Range = {
  min: number;
  max: number;
};
</script>

<style lang="sass" scoped>
.layout
  display: grid
  grid-template-columns: 250px 1fr 250px
  height: 65vh
.cards-grid-2
  display: grid
  grid-template-columns: repeat(2, 2fr)
.cards-grid-1
  display: grid
  grid-template-columns: repeat(1, 1fr)
.title
  font-size: 1rem
  text-transform: none
.active_btn
  border: 2px solid #426b8c
</style>
