<template>
  <div>
    <div class="bg-white rounded-borders">
      <div class="q-pa-sm">
        <PanelFilter @createPanel="createPanel" />
      </div>
    </div>
    <div class="cards-grid">
      <div
        v-for="card in panels"
        :key="card.instanceId"
        class="q-pa-sm gridElement"
        style="position: relative"
      >
        <q-card class="full-height column no-shadow" :style="card.style">
          {{ card.style }}
          <div v-if="card.fullTitle" class="help-tooltip">
            <q-icon name="help" flat size="17px" color="blue-grey-3" />
            <q-tooltip>
              {{ card.fullTitle }}
            </q-tooltip>
          </div>
          <q-icon
            class="close-btn" 
            name="close" 
            size="17px" 
            color="blue-grey-3" 
            @click="closePanel(card.instanceId)"
          />
          <q-card-section class="card-header" v-if="card.title">
            <div class="title text-center">
              {{ card.title }}
            </div>
            <div v-if="card.range || card.organisationName ">
              <div v-if="card.organisationName" class="card-details">
                {{ card.organisationName }}
              </div>
              <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="render(card.src)"
              name="panel"
            />
          </q-card-section>
        </q-card>
      </div>
    </div>
    <DateEditDialog
      :open="showDateDialog"
      @newRange ="updatePanelDate"
      @close="closeDialog"
    />
    <DetailedListDialog
      :name="serviceName"
      :statements="detailedStatementsList"
      :byRegions="byRegionDetailed"
      :byOrganisations="byOrganisationDetailed"
      @row-handler="(data) => fetchVerbose(data)"
      @close="closeDetailedModal"
    />
  </div>
</template>

<script lang="ts">
import PanelFilter from './PanelFilter.vue';
import { Component, Vue, Watch, Prop } from 'vue-property-decorator';
import {
  convertDateFromBackendFormat,
  convertDateFormatWithoutLocale,
  DateFormat,
} from '@utils/format-date';
import { v4 } from 'uuid';
import DateEditDialog from './date-edit-dialog.vue';
import DetailedListDialog from './detailed-list-dialog.vue';
import get from 'lodash/get';
import axios from 'axios';
import { auth } from '@services/AuthService';
import { reports as reportData } from '../config';

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

@Component({
  components: {
    PanelFilter,
    DetailedListDialog,
    DateEditDialog,
  }
})
export default class InfoPanel extends Vue {
  @Prop() showDateDialog: boolean;
  @Prop() needToReset: boolean;

  private panels: Panel[] = [];
  private loading = false;
  private serviceName = '';
  private panelOptions: PanelOptions | Record<string, unknown>;
  private byRegionDetailed = [];
  private byOrganisationDetailed = [];
  private targetId = '';
  private detailedStatementsList = [];
  private panelQueries: string[] = [];

  @Watch('panels')
  setData(newData: Panel[]): void {
    if (newData?.length) {
      localStorage.setItem('myInfoPanel', JSON.stringify(this.panels));
      this.$emit('hasPanels', true);
    } else {
      localStorage.removeItem('myInfoPanel');
      this.$emit('hasPanels', false);
    }
  }

  @Watch('needToReset')
  resetPanels(value: boolean): void {
    if (value) {
      this.panels = [];
    }
  }

  mounted(): void {
    const storedPanels = JSON.parse(
      localStorage.getItem('myInfoPanel') || '{}'
    );
    if (storedPanels?.length) {
      this.panels.push(...storedPanels);
    }
    window.addEventListener('message', this.panelListener);
  }

  createPanel(params: any): void {
    const url = this.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(),
      allRegions: params.allRegions,
    };
    this.panels.push(panel);
    window.addEventListener('message', this.panelListener);
  }

  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',
      region: params.region?.length && params.region[0]?.code,
    };
    return url + paramsToUrl(urlParams);
  }

  closePanel(index: string): void {
    this.panels = this.panels.filter((item) => {
      return item.instanceId !== index;
    });
  }

  async panelListener({ data }: { data: any }): Promise<void> {
    if (Array.isArray(data?.value) && data.value.length) {
      if (this.loading) {
        return;
      }
      this.panelQueries = reportData.flatMap((report) => {
        if (report.id === data.options.panelType) {
          return report.requests || [];
        }
        return [];
      });
      if (!this.panelQueries?.length) return;
      this.loading = true;
      this.targetId = data.value[0][1];
      this.serviceName = data.name;
      this.panelOptions = data.options;
      if (data.isAllRegions) {
        await this.getDataFromQueryRest();
        this.loading = false;
      } else {
        this.serviceName = data.name;
        this.detailedStatementsList = data.value;
        this.loading = false;
      }
    }
  }

  async getDataFromQueryRest(): Promise<void> {
    let config: Config = {
      headers: {},
      params: {
        dataRequest: {
          queryParams: {
            from: '',
            to: '',
          },
        },
      },
    };
    if (this.targetId.length) {
      // const currentUserId = this.$store.getters['oidcClient/currentUser'].sub;
      // const { data } = await collapsedProfileApi.getCollapsedProfileByAccountId(
      //   currentUserId || ''
      // );
      // const regions = data.sectionFilters?.regions || [];
      // Здесь uuid-ы, в clickhouse хранятся только regionCode

      config = {
        params: {
          dataRequest: {
            queryParams: {
              from: this.panelOptions.from,
              to: this.panelOptions.to,
              regions: ['empty'],
              organizations: ['empty'],
              services: this.targetId,
            },
          },
        },
      };
    }
    if (auth) {
      const Authorization = await auth.getAccessToken();
      config.headers = { common: { Authorization: `Bearer ${Authorization}` } };
      const url = `/stat-query-rest/data/${this.panelQueries[0]}`;
      const { data } = await axios
        .create({ withCredentials: true })
        .get(url, config);
      this.byRegionDetailed = { ...data.data, color: this.panelOptions.color };
    }
  }

  async fetchVerbose({
    regionCode,
    orgId,
  }: {
    regionCode?: string;
    orgId?: string;
  }): Promise<void> {
    const config: Config = {
      params: {
        dataRequest: {
          queryParams: {
            from: this.panelOptions.from,
            to: this.panelOptions.to,
            services: this.targetId,
          },
        },
      },
    };
    let url = '/stat-query-rest/data';

    if (auth) {
      const Authorization = await auth.getAccessToken();
      config.headers = { common: { Authorization: `Bearer ${Authorization}` } };
    }

    if (regionCode) {
      config.params.dataRequest.queryParams.regions = regionCode;
      url += `/${this.panelQueries[1]}`;
      const { data } = await axios
        .create({ withCredentials: true })
        .get(url, config);
      this.byOrganisationDetailed = data.data;
    }

    if (orgId) {
      config.params.dataRequest.queryParams.organizations = orgId;
      url += `/${this.panelQueries[2]}`;
      const { data } = await axios
        .create({ withCredentials: true })
        .get(url, config);
      this.detailedStatementsList = get(data, 'data.values.0.values.1.0');
    }
  }

  closeDetailedModal(): void {
    this.detailedStatementsList = [];
    this.byRegionDetailed = [];
    this.panelOptions = {};
    this.serviceName = '';
    this.targetId = '';
  }

  closeDialog(): void {
    this.$emit('closeDateDialog');
  }

  updatePanelDate(newRange: string): void {
    this.panels = this.panels.map((panel) => ({ ...panel, range: newRange }));
    this.refreshPanel();
  }

  refreshPanel(): void {
    const prevData = [...this.panels];
    this.panels = [];
    prevData.forEach((panel, index) => {
      setTimeout(() => {
        this.panels.push(panel);
      }, index * 300);
    });
  }

  render = (val: any): any => {
    if (Array.isArray(val)) return val.map(this.render);
    val = location.origin + val;
    return val;
  };

  beforeDestroy(): void {
    window.removeEventListener('message', this.panelListener);
  }
}

export type PanelOptions = {
  region: Record<string, unknown>[],
  allRegions?: boolean;
  excludeSubordinates?: boolean;
  from: string;
  to: string;
  report: {
    value: string;
    label: string;
    fullTitle: string;
    id: string;
  },
  service: any;
  color?: string[];
  organisation?: Record<string, string>[];
  department?: Record<string, string>[];
};

export type Panel = {
  allRegions?: boolean;
  fullTitle?: string;
  instanceId?: string;
  organisationName?: string;
  range?: string;
  src?: string;
  title?: string;
  type?: string;
  queryDefinition?: string;
};

type Config = {
  headers?: Record<string, unknown>;
  params: {
    dataRequest: {
      queryParams: {
        from: string | unknown;
        to: string | unknown;
        regions?: string | string[];
        services?: string | string[];
        organizations?: string | string[];
      };
    };
  };
};

</script>

<style lang="sass" scoped>
.aspect-ratio--16x9
  padding-bottom: 46.25%
  & .iframe
    position: absolute
    top: 0
    bottom: 0
    left: 0px
    right: 0

.grid
  display: grid

  &-table
    .q-table__middle
      display: none

.iframe
  display: block
  height: 100%
  width: 100%
.close-btn
  position: absolute
  right: 2px
  top: 2px
  z-index: 2
  padding: 2px
  border-radius: 10px
  &:hover 
    cursor: pointer
    background-color: rgba(156, 183, 197, 0.1)
.edit-btn
  position: absolute
  right: 22px
  top: 2px
  z-index: 2  
  padding: 2px
  border-radius: 10px
  &:hover 
    cursor: pointer
    background-color: rgba(156, 183, 197, 0.1)
.gridElement
  height: 70vh
.help-tooltip
  position: absolute
  right: 25px
  top: 1px
  z-index: 2
.title
  font-size: 16px
.cards-grid
  display: grid
  grid-template-columns: repeat(2, 2fr)
.card-header 
  padding-bottom: 0
.card-details
  text-align: center
  color: #b0bec5
  font-size: 11px
.title
  font-size: 1.5rem
  text-transform: none
</style>