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

import { parseComparisonHistograms } from '../../../common/helpers/histogram';
import * as selectors from '../selectors';
import {
  getComparisonHistogramAction,
  setComparisonFilterAction,
  setComparisonHistogramAction,
  setDeviceAction,
  setFilterFormatAction,
  setGeoAction,
} from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';

const query = `
  query SupplyAccountHistogramQuery(
    $fields: [String],
    $interval: String,
    $timezone: String,
    $filters: [MarketplaceFiltersInputType]
  ) {
    supplyAccountHistogram(
      fields: $fields,
      interval: $interval,
      timezone: $timezone,
      filters: $filters
    ) {
      totalCount
      data {
        name
        buckets {
          time
          fields {
            PAGE_VIEWS {
              value
              change
            }
            PLAYER_LOADS {
              value
              change
            }
            SUPPLY_REQUESTS {
              value
              change
            }
            IMPRESSIONS {
              value
              change
            }
            REVENUE {
              value
              change
            }
            GROSS_REVENUE {
              value
              change
            }
            OVERALL_FILL {
              value
              change
            }
            GROSS_RPM {
              value
              change
            }
            PUB_PLAYER_ERPM {
              value
              change
            }
            PLAYER_ERPM {
              value
              change
            }
            AC_AD_RPM {
              value
              change
            }
            GROSS_PLAYER_ERPM {
              value
              change
            }
          }
        }
      }
    }
  }
`;

export default (action$, state$) =>
  action$.pipe(
    ofType(
      getComparisonHistogramAction.type,
      setComparisonFilterAction.type,
      setFilterFormatAction.type,
      setDeviceAction.type,
      setGeoAction.type,
    ),
    filter(() => {
      const state = state$.value;

      const pageConfig = selectors.pageConfigSelector(state);

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

      const comparisonFilter = selectors.comparisonFilterSelector(state);
      const formatFilter = selectors.formatFilterSelector(state);
      const device = selectors.deviceSelector(state);
      const geo = selectors.geoSelector(state);

      const timezone = getUserTimezoneSelector(state$.value);

      let filters = {};

      if (formatFilter) {
        filters = { ...formatFilter };
      }

      if (device) {
        filters = {
          ...filters,
          device,
        };
      }

      if (geo) {
        filters = {
          ...filters,
          geo,
        };
      }

      const params = {
        timezone,
        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 },
        ],
      };

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

          if (!errors.length) {
            const histograms = parseComparisonHistograms({
              histograms: supplyAccountHistogram.data,
              timezone,
              allowableFields: [comparisonFilter],
            });

            actions = [of(setComparisonHistogramAction(histograms))];
          }

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

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