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

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

import { getClosestKnownTimeZone, getOriginValue } from '../../helpers';
import * as selectors from '../selectors';
import {
  currentFiltersAsStringAction,
  isNextVideosLoadingAction,
  isSearchFilteredAction,
  isTargetClipIdLoadingAction,
  isVideosLoadingAction,
  maxPerformanceAction,
  pageAction,
  selectedVideoAction,
  startSearchEventAction,
  targetClipIdAction,
  targetVideoIdAction,
  totalCountAction,
  videosAction,
} from '../slices';
import { removeQueriesAction } from '@/modules/@common/location/redux/slices';
import { gqlRequest } from '@/modules/@common/request';
import { getToken } from '@/modules/@common/token/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { closeAction as closeMultipleBulkAction } from '@/modules/editorial/bulkActions/redux/slices';
import { fromSuggesterSelector, querySelector } from '@/modules/editorial/editorialSearch/reduxSearch/selectors';
import {
  configSelector,
  isFilterDirtySelector,
  tabCountersSelector,
} from '@/modules/editorial/editorialSearchFilter/filterContainer/redux/selectors';
import {
  configAction,
  configChangedEventAction,
  tabCountersAction,
} from '@/modules/editorial/editorialSearchFilter/filterContainer/redux/slices';
import { getDefaultTab, ifAllTabAvailable } from '@/modules/editorial/helpers/videoTab';

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

const getResponse = ({ data: { videoSearch }, errors }) => ({ videoSearch, errors });

const FETCH_VIDEO = 'FETCH_VIDEO';

export default (action$, state$) =>
  action$.pipe(
    ofType(startSearchEventAction.type),
    filter(() => !!getToken()),
    switchMap((action) => {
      const state = state$.value;
      const query = querySelector(state);
      const fromSuggester = fromSuggesterSelector(state);
      const isFilterDirty = isFilterDirtySelector(state);
      const tabCounters = tabCountersSelector(state);
      const config = configSelector(state);
      const size = selectors.sizeSelector(state);
      const filterInternalParams = selectors.filterInternalParamsSelector(state);
      const selectedVideo = selectors.selectedVideoSelector(state);

      // by default get tabs counters
      // pay attention -> for counters tabView always ALL and size === 0
      const requestParams = {
        ...filterInternalParams,
        videoTab: 'ALL',
        typeValue: 'SHORT_FORM',
        page: 0,
        size: 0,
        timeZone: getClosestKnownTimeZone(),
        queryIds: true,
        includeMaxPerformance: false,
        withTotalCounters: true,
      };

      if (filterInternalParams.account?.[0]?.owners?.length) {
        requestParams.owners = filterInternalParams.account[0].owners.map((o) => o.toString());
        delete requestParams.account;
      }

      if (action.payload?.fetch === FETCH_VIDEO && !action.payload?.onlyCounters) {
        requestParams.videoTab = filterInternalParams.videoTab;
        requestParams.size = size;
        requestParams.includeMaxPerformance = true;
        requestParams.queryIds = true;
        requestParams.withTotalCounters = false;
      }

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

        if (fromSuggester || action.payload?.fromSuggester) {
          requestParams.names = [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 sharedVideo = Router.query.videoId;

      if (sharedVideo && !selectedVideo) {
        requestParams.videoIds = [sharedVideo];
      }

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

          if (!response.errors.length) {
            const res = getResponse(response);

            if (res.videoSearch.counter) {
              actions.push(of(tabCountersAction(res.videoSearch.counter)));

              const shouldDefineDefaultTabWhenSharedVideo = ifAllTabAvailable(getUserPermissionsSelector(state$.value))
                ? false
                : !Router.query.videoTabs;

              const shouldDefineDefaultTab =
                !isFilterDirty &&
                Object.values(tabCounters).every((tab) => tab === null) &&
                (!sharedVideo ? true : shouldDefineDefaultTabWhenSharedVideo);

              if (shouldDefineDefaultTab) {
                const tabDefaultFilterConfig = getDefaultTab(
                  res.videoSearch.counter,
                  getUserPermissionsSelector(state$.value),
                );
                const updateFilterConfig = {
                  ...config,
                  videoTabs: {
                    filters: [tabDefaultFilterConfig],
                  },
                };

                actions.push(of(configAction(updateFilterConfig)), of(configChangedEventAction()));
              }

              if (!action.payload?.onlyCounters) {
                actions.push(
                  of(
                    startSearchEventAction({
                      fetch: FETCH_VIDEO,
                      fromSuggester,
                    }),
                  ),
                );
              }
            } else {
              if (res.videoSearch) {
                actions.push(
                  of(currentFiltersAsStringAction(requestParams)),
                  of(selectedVideoAction()),
                  of(videosAction(res.videoSearch.videos)),
                  of(maxPerformanceAction(res.videoSearch.maxPerformance)),
                  of(totalCountAction(res.videoSearch.totalCount)),
                );
              }

              if (sharedVideo && !selectedVideo && res.videoSearch.videos?.find((video) => video.uid === sharedVideo)) {
                actions.push(of(selectedVideoAction(res.videoSearch.videos[0])));
              } else if (sharedVideo && selectedVideo) {
                actions.push(of(removeQueriesAction('videoId')));
              }

              actions.push(of(isSearchFilteredAction(!!query.length || isFilterDirty)));
            }
          }

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

      return concat(
        of(totalCountAction()),
        of(targetVideoIdAction()),
        of(targetClipIdAction()),
        of(pageAction()),
        of(isTargetClipIdLoadingAction()),
        of(isNextVideosLoadingAction()),
        of(isVideosLoadingAction(!action.payload?.onlyCounters)),
        of(closeMultipleBulkAction()),
        stream$,
        of(isVideosLoadingAction(false)),
      );
    }),
  );
