import dayjs from 'dayjs';
import timezonePlugin from 'dayjs/plugin/timezone';
import utcPlugin from 'dayjs/plugin/utc';
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 { getChartDataAction, setFieldAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';

dayjs.extend(utcPlugin);
dayjs.extend(timezonePlugin);

const query = `
  query adPerformanceHistogram(
    $countries: [String],
    $devices: [String],
    $domains: [String],
    $demandSources: [String],
    $widgetIds: [String],
    $adFormat: String,
    $ranges: [AnalyticsDateRangeInputType],
    $interval: AnalyticsIntervalInputType,
    $timezone: String
  ) {
    adPerformanceHistogram(
      countries: $countries,
      devices: $devices,
      domains: $domains,
      demandSources: $demandSources,
      widgetIds: $widgetIds,
      adFormat: $adFormat,
      ranges: $ranges,
      interval: $interval,
      timezone: $timezone
    ) {
      rid
      data {
        name
        buckets {
          time
          externalRevenues
          platformFee
          adImpressions
          viewableImpressions
          viewability
          fillRate
          adRequests
          cpm
          rpm
          playerLoads
          lreOpportunities
          lreImpressions
          netRevenue
          ctr
          adClicks
        }
      }
    }
  }
`;

const prepareChartData = (data, timezone, calendar, calendarCustom) =>
  data.map((item) => {
    const calendarConfig = calendar === CALENDAR_FILTER_VALUE.custom ? calendarCustom : calendar;
    if (item?.buckets?.length) {
      const chipTimeFirtsItem = dayjs(item?.buckets[0]?.time).tz(timezone);
      const chipTimeLastItem = dayjs(item?.buckets?.at(-1)?.time).tz(timezone);
      const buckets = item?.buckets?.map((bucket) => {
        const time = dayjs(bucket.time).tz(timezone);

        return {
          ...bucket,
          xTick: calendarConfig.xTickFormatter(time),
        };
      });

      return {
        ...item,
        chip: chipTimeFirtsItem ? calendarConfig.chipFormatter(chipTimeFirtsItem, chipTimeLastItem) : item.name,
        buckets,
      };
    }

    return item;
  });

export default (action$, state$) =>
  action$.pipe(
    ofType(getChartDataAction.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 timezone = getUserTimezoneSelector(state$.value);

      let requestParams = {};

      if (calendar === CALENDAR_FILTER_VALUE.custom) {
        const { ranges, interval } = calendarCustom;
        requestParams = {
          ranges: ranges?.map((item) => ({ ...item, timezone })),
          interval,
        };
      } else if (calendar.dateRange) {
        const { ranges, interval } = calendar;
        requestParams = {
          ranges: ranges?.map((item) => ({ ...item, timezone })),
          interval,
        };
      }

      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 chartData = {
              ...data.adPerformanceHistogram,
            };

            actions.push(
              of(
                setFieldAction({
                  chartData: prepareChartData(chartData?.data ?? [], timezone, calendar, calendarCustom),
                }),
              ),
            );
          }

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

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