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

import * as selectors from '../selectors';
import { getLivePerformanceTotalsAction, setFieldAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';

const queryGQL = `
  query livePerformanceTotals(
    $eventId: Int,
    $scheduleSessionIds: [Int],
    $inFocus: Boolean
  ) {
    livePerformanceTotals(
      eventId: $eventId,
      scheduleSessionIds: $scheduleSessionIds,
      inFocus: $inFocus
    ) {
      rid
      users
      minutesTotal
      minutesAvg
      minutesAvgPct
      devices {
        device
        value
        valuePct
      }
      resolutions {
        MOBILE {
          size
          value
          valuePct
        }
        DESKTOP {
          size
          value
          valuePct
        }
      }
      countries {
        code
        value
        valuePct
      }
      countriesTotal
    }
  }
`;

const findItems = (array, key, values) =>
  array?.reduce((acc, item) => {
    const size = values.find((value) => item[key] === value);
    if (size) {
      return acc + item.valuePct;
    }
    return acc;
  }, null);

const roundValuePct = (value) => {
  if (value) {
    return Math.round(value);
  }
  return null;
};

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

      const event = selectors.eventSelector(state);
      const sessions = selectors.sessionsSelector(state);
      const countriesFullList = selectors.countriesFullListSelector(state);

      const stream$ = gqlRequest({
        query: queryGQL,
        variables: {
          eventId: event.value,
          scheduleSessionIds: sessions?.map((session) => +session.value) ?? [],
        },
      }).pipe(
        switchMap(({ data, errors }) => {
          const actions = [];

          if (!errors.length) {
            const {
              livePerformanceTotals: {
                users,
                minutesTotal,
                minutesAvg,
                minutesAvgPct,
                devices = [],
                resolutions,
                countries = [],
                countriesTotal,
              },
            } = data;

            const desktop = findItems(devices, 'device', ['DESKTOP']);

            const desktopSizeMedium = findItems(resolutions?.DESKTOP, 'size', [
              'SIZE_LT_240P',
              'SIZE_240P',
              'SIZE_360P',
              'SIZE_480P',
              'SIZE_720P',
            ]);
            const desktopSizeLarge = findItems(resolutions?.DESKTOP, 'size', ['SIZE_1080P']);
            const desktopSizeXLarge = findItems(resolutions?.DESKTOP, 'size', ['SIZE_1440P']);

            const mobile = findItems(devices, 'device', ['MOBILE']);

            const mobileSizeMedium = findItems(resolutions?.MOBILE, 'size', [
              'SIZE_480P',
              'SIZE_720P',
              'SIZE_1080P',
              'SIZE_1440P',
            ]);
            const mobileSizeSmall = findItems(resolutions?.MOBILE, 'size', ['SIZE_360P']);
            const mobileSizeXSmall = findItems(resolutions?.MOBILE, 'size', ['SIZE_LT_240P', 'SIZE_240P']);

            actions.push(
              of(
                setFieldAction({
                  users,
                  totalMinutes: minutesTotal,
                  averageMinutes: minutesAvg,
                  averageMinutesPercent: Math.round(minutesAvgPct * 100) / 100,
                  desktop: {
                    all: roundValuePct(desktop),
                    medium: roundValuePct(desktopSizeMedium),
                    large: roundValuePct(desktopSizeLarge),
                    xLarge: roundValuePct(desktopSizeXLarge),
                  },
                  mobile: {
                    all: roundValuePct(mobile),
                    medium: roundValuePct(mobileSizeMedium),
                    small: roundValuePct(mobileSizeSmall),
                    xSmall: roundValuePct(mobileSizeXSmall),
                  },
                  countries: {
                    all: countriesTotal,
                    items:
                      countries?.map((country) => ({
                        name: countriesFullList.find((item) => item.uiKey === country.code)?.name ?? country.code,
                        value: country.value,
                        percent: Math.round(country.valuePct),
                      })) ?? [],
                  },
                }),
              ),
            );
          }

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

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