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

import { selectedVideoSelector } from '../selectors';
import { updateVideoTagsAction } from '../slices';
import { iabFlatToTree } from '@/modules/@common/iab/helpers';
import { gqlRequest } from '@/modules/@common/request';
import { videosSelector } from '@/modules/editorial/editorialSearchResults/redux/selectors';
import { videosAction } from '@/modules/editorial/editorialSearchResults/redux/slices';

import queryVideoUpdateGQL from '@/modules/@common/gql/queries/videoUpdate';

const DELAY = 500;

export default (action$, state$) =>
  action$.pipe(
    ofType(updateVideoTagsAction.type),
    debounceTime(DELAY),
    switchMap((action) => {
      const videos = videosSelector(state$.value);
      const { uid } = selectedVideoSelector(state$.value);
      const { payload: updateVideo } = action;

      const updatedVideos = videos.map((originalVideo) => {
        if (originalVideo.uid === uid) {
          const forUpdateVideo = { ...updateVideo };

          if (forUpdateVideo.iab) {
            forUpdateVideo.iab = {
              data: JSON.stringify({
                categories: iabFlatToTree(updateVideo.iab),
              }),
            };
          }

          return { ...originalVideo, ...forUpdateVideo };
        }

        return originalVideo;
      });

      const stream$ = gqlRequest({
        query: queryVideoUpdateGQL,
        variables: {
          id: uid,
          video: {
            ...updateVideo,
            updateClip: true,
          },
        },
      }).pipe(
        switchMap(({ data, errors }) => {
          const actions = [];

          if (!errors.length) {
            const updatedVideoList = videos.map((originalVideo) =>
              originalVideo.uid === uid ? { ...originalVideo, ...data.videoUpdate } : originalVideo,
            );

            actions.push(of(videosAction(updatedVideoList)));
          }

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

      return concat(of(videosAction(updatedVideos)), stream$);
    }),
  );
