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

import {
  DEFAULT_VERIFICATION_TYPE_VALUE,
  DEFAULT_VIDEO_STATUS_VALUE,
} from '@/modules/editorial/editorialSearchFilter/constants';

import { getOriginValue } from '../../helpers';
import * as selectors from '../selectors';
import { isNextVideosLoadingAction, loadNextEventAction, pageAction, totalCountAction, videosAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getToken } from '@/modules/@common/token/helpers';
import { querySelector } from '@/modules/editorial/editorialSearch/reduxSearch/selectors';

import videosQuery from '@/modules/@common/gql/queries/videos';

export default (action$, state$) =>
  action$.pipe(
    ofType(loadNextEventAction.type),
    debounceTime(500),
    filter(() => !!getToken()),
    filter(() => !selectors.isVideosLoadingSelector(state$.value)),
    filter(() => !selectors.isNextVideosLoadingSelector(state$.value)),
    switchMap(() => {
      const state = state$.value;
      const query = querySelector(state);

      const page = selectors.pageSelector(state$.value);
      const size = selectors.sizeSelector(state$.value);
      const videos = selectors.videosSelector(state$.value);
      const filterInternalParams = selectors.filterInternalParamsSelector(state$.value);
      const isVideosLoading = selectors.isVideosLoadingSelector(state$.value);

      const updatedPage = page + 1;

      const requestParams = {
        ...filterInternalParams,
        typeValue: 'SHORT_FORM',
        page: updatedPage,
        size,
        queryIds: true,
      };

      if (query.length) {
        requestParams.query = query;
      }

      requestParams.origins = getOriginValue(filterInternalParams);

      if (filterInternalParams.status && filterInternalParams.status !== DEFAULT_VIDEO_STATUS_VALUE) {
        requestParams.stateValue = filterInternalParams.status;
      }

      if (filterInternalParams.verification && filterInternalParams.verification !== DEFAULT_VERIFICATION_TYPE_VALUE) {
        requestParams.verificationValue = filterInternalParams.verification;
      }

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

          if (data.videoSearch && !errors.length && !isVideosLoading) {
            const updatedVideos = videos.concat(...data.videoSearch.videos);

            actions.push(of(videosAction(updatedVideos)));
            actions.push(of(totalCountAction(data.videoSearch.totalCount)));
            actions.push(of(pageAction(updatedPage)));
          }

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

      return concat(of(isNextVideosLoadingAction(true)), stream$, of(isNextVideosLoadingAction(false)));
    }),
  );
