import { ofType } from 'redux-observable';
import { concat, of } from 'rxjs';
import { filter, switchMap } from 'rxjs/operators';

import { CHART_TIME_INTERVAL_TAB, DEMAND_TAG_PAGE, SUPPLY_SITE_PAGE, SUPPLY_TAG_PAGE } from '../../constants';

import { parseComparisonHistograms, parseHistogram } from '../../../common/helpers/histogram';
import { addPageParams } from '../../helpers/filters';
import * as selectors from '../selectors';
import {
  getChartDataAction,
  refreshPageDataByIntervalAction,
  setChartTabAction,
  setComparisonFilterAction,
  setFieldAction,
  setFilterByCountryAction,
  setFilterByDeviceAction,
  setFilterByPlayerAction,
  setTimeIntervalFilterAction,
} from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';
import { formatFilterSelector } from '@/modules/marketplace/dashboard/redux/selectors';
import { setFilterFormatAction } from '@/modules/marketplace/dashboard/redux/slices';

export default (action$, state$) =>
  action$.pipe(
    ofType(
      getChartDataAction.type,
      setChartTabAction.type,
      setTimeIntervalFilterAction.type,
      setComparisonFilterAction.type,
      refreshPageDataByIntervalAction.type,
      setFilterByCountryAction.type,
      setFilterByDeviceAction.type,
      setFilterByPlayerAction.type,
      setFilterFormatAction.type,
    ),
    filter(() => {
      const state = state$.value;

      const pageConfig = selectors.pageConfigSelector(state);

      return !!pageConfig;
    }),
    switchMap(() => {
      const state = state$.value;

      const chartTab = selectors.chartTabSelector(state);
      const pageConfig = selectors.pageConfigSelector(state);
      const timeIntervalFilter = selectors.timeIntervalFilterSelector(state);
      const comparisonFilter = selectors.comparisonFilterSelector(state);
      const filterByCountry = selectors.filterByCountrySelector(state);
      const filterByDevice = selectors.filterByDeviceSelector(state);
      const filterByPlayer = selectors.filterByPlayerSelector(state);

      const formatFilter = formatFilterSelector(state);

      const timezone = getUserTimezoneSelector(state);

      let params = {
        timezone,
      };

      let filters = {};

      if (formatFilter && !(pageConfig?.type === DEMAND_TAG_PAGE || pageConfig?.type === SUPPLY_TAG_PAGE)) {
        filters = { ...formatFilter };
      }

      if (pageConfig?.type === SUPPLY_SITE_PAGE && filterByCountry) {
        filters = {
          ...filters,
          geo: filterByCountry,
        };
      }

      if (pageConfig?.type === SUPPLY_SITE_PAGE && filterByDevice) {
        filters = {
          ...filters,
          device: filterByDevice,
        };
      }

      if (pageConfig?.type === SUPPLY_SITE_PAGE && filterByPlayer?.value) {
        filters = {
          ...filters,
          widgetId: filterByPlayer.value,
        };
      }

      if (chartTab === CHART_TIME_INTERVAL_TAB) {
        const { interval, dimension, ...ranges } = timeIntervalFilter;
        const mainParams = {
          ...params,
          fields: pageConfig.timeIntervalParams.map((option) => option.value),
          interval,
          filters: [{ ranges: [ranges], dimension, ...filters }],
        };

        params = addPageParams(mainParams, pageConfig);
      } else {
        const mainParams = {
          ...params,
          fields: [comparisonFilter],
          interval: '1h',
          filters: [
            { ranges: [{ stringFrom: 'now/d', stringTo: 'now+1d/d-59m', timezone }], dimension: 'HOUR', ...filters },
            { ranges: [{ stringFrom: 'now-1d/d', stringTo: 'now/d-59m', timezone }], dimension: 'HOUR', ...filters },
            { ranges: [{ stringFrom: 'now-7d/d', stringTo: 'now-6d/d-59m', timezone }], dimension: 'HOUR', ...filters },
          ],
        };

        params = addPageParams(mainParams, pageConfig);
      }

      const stream$ = gqlRequest({
        query: pageConfig.histogramQuery,
        variables: {
          ...params,
        },
      }).pipe(
        switchMap(({ data = {}, errors }) => {
          let actions = [];

          if (!errors.length) {
            const chartData = {
              ...data.siteHistogram,
              ...data.supplyTagHistogram,
              ...data.demandTagHistogram,
              ...data.advertiserHistogram,
            };
            let parsedChartData;

            if (chartTab === CHART_TIME_INTERVAL_TAB) {
              parsedChartData = parseHistogram(chartData.data[0], timezone);
            } else {
              parsedChartData = parseComparisonHistograms({
                histograms: chartData.data,
                timezone,
                allowableFields: [comparisonFilter],
              });
            }

            actions = [of(setFieldAction({ chartData: parsedChartData }))];
          }

          return concat(...actions);
        }),
      );

      return concat(stream$);
    }),
  );
