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

import { CALENDAR_FILTER_VALUE } from '../../constants';

import * as selectors from '../selectors';
import { getTotalsAction, setFieldAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';

const query = `
  query adPerformanceTotals(
    $countries: [String],
    $devices: [String],
    $domains: [String],
    $demandSources: [String],
    $widgetIds: [String],
    $adFormat: String,
    $dateRange: AnalyticsDateRangeInputType,
    $dateRangeComparison: AnalyticsDateRangeInputType
  ) {
    adPerformanceTotals(
      countries: $countries,
      devices: $devices,
      domains: $domains,
      demandSources: $demandSources,
      widgetIds: $widgetIds,
      adFormat: $adFormat,
      dateRange: $dateRange,
      dateRangeComparison: $dateRangeComparison
    ) {
      total {
        externalRevenues
        platformFee
        adImpressions
        viewableImpressions
        viewability
        fillRate
        adRequests
        cpm
        rpm
        playerLoads
        lreOpportunities
        lreImpressions
        netRevenue
        devicesExternalRevenues {
          device
          value
          valuePct
        }
        ctr
        adClicks
      }
      comparisonPct {
        externalRevenuesPct
        platformFeePct
        adImpressionsPct
        viewableImpressionsPct
        viewabilityPct
        fillRatePct
        adRequestsPct
        cpmPct
        rpmPct
        playerLoadsPct
        lreOpportunitiesPct
        lreImpressionsPct
        netRevenuePct
        devicesExternalRevenues {
          device
          value
          valuePct
        }
      }
      countries {
        code
        value
        valuePct
      }
      hideComparisonNumbers
    }
  }
`;

export default (action$, state$) =>
  action$.pipe(
    ofType(getTotalsAction.type),
    switchMap(() => {
      const state = state$.value;

      const calendar = selectors.calendarSelector(state);
      const calendarCustom = selectors.calendarCustomSelector(state);
      const demandSources = selectors.demandSourcesSelector(state);
      const players = selectors.playersSelector(state);
      const domains = selectors.domainsSelector(state);
      const countries = selectors.countriesSelector(state);
      const devices = selectors.devicesSelector(state);
      const adFormat = selectors.adFormatSelector(state);
      const countriesFullList = selectors.countriesFullListSelector(state);

      const timezone = getUserTimezoneSelector(state$.value);

      let requestParams = {};

      if (calendar === CALENDAR_FILTER_VALUE.custom) {
        const { dateRange } = calendarCustom;
        requestParams = {
          dateRange: { ...dateRange, timezone },
        };
      } else if (calendar.dateRange) {
        const { dateRange, dateRangeComparison } = calendar;

        if (dateRangeComparison) {
          requestParams = {
            ...requestParams,
            dateRange: { ...dateRange, timezone },
            dateRangeComparison: { ...dateRangeComparison, timezone },
          };
        } else {
          requestParams = {
            ...requestParams,
            dateRange: { ...dateRange, timezone },
          };
        }
      }

      if (demandSources?.length) {
        requestParams = {
          ...requestParams,
          demandSources: demandSources.map((item) => item.value),
        };
      }

      if (domains?.length) {
        requestParams = {
          ...requestParams,
          domains: domains.map((item) => item.value),
        };
      }

      if (countries?.length) {
        requestParams = {
          ...requestParams,
          countries: countries.map((item) => item.value),
        };
      }

      if (devices?.length) {
        requestParams = {
          ...requestParams,
          devices: devices.map((item) => item.value),
        };
      }

      if (players?.length) {
        requestParams = {
          ...requestParams,
          widgetIds: players.map((item) => item.value),
        };
      }

      if (adFormat) {
        requestParams = {
          ...requestParams,
          adFormat,
        };
      }

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

          if (!errors.length) {
            const {
              total = {},
              comparisonPct = {},
              countries: countriesResponse,
              hideComparisonNumbers,
            } = data.adPerformanceTotals;

            actions.push(
              of(
                setFieldAction({
                  totals: {
                    total,
                    comparisonPct,
                    countries:
                      countriesResponse?.map((country) => ({
                        ...country,
                        name: countriesFullList?.find((item) => item.uiKey === country.code)?.name ?? country.code,
                      })) ?? [],
                    devices: total?.devicesExternalRevenues ?? [],
                    hideComparisonNumbers,
                  },
                }),
              ),
            );
          }
          return concat(...actions);
        }),
      );

      return concat(
        of(setFieldAction({ isTotalsLoading: true })),
        stream$,
        of(setFieldAction({ isTotalsLoading: false })),
      );
    }),
  );
