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

import { VIDEO_ADMIN } from '@/modules/@common/acl/constants';
import { TYPE_ERROR, TYPE_SUCCESS } from '@/modules/@common/notify/constants';

import { selectedVideoSelector } from '../selectors';
import { reloadSelectedVideoAction, updateVideoAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { monitoringAction } from '@/modules/editorial/editorialSearch/redux/slices';
import { videosSelector } from '@/modules/editorial/editorialSearchResults/redux/selectors';
import { startSearchEventAction, videosAction } from '@/modules/editorial/editorialSearchResults/redux/slices';
import { showNotificationAction } from '@/modules/layout/redux/slices';

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

export default (action$, state$) =>
  action$.pipe(
    ofType(updateVideoAction.type),
    switchMap((action) => {
      const userPermissions = getUserPermissionsSelector(state$.value);
      const videos = videosSelector(state$.value);
      const selectedVideo = selectedVideoSelector(state$.value);
      const { payload: updateVideo } = action;
      const { uid } = selectedVideo;

      if (
        action.payload?.videoCreationDate < 0 ||
        action.payload?.videoCreationDate > new Date(dayjs().endOf('minute')).valueOf()
      ) {
        if (Object.keys(action.payload).length === 1) {
          return EMPTY;
        }
        // todo: check if date creation could be limited from Video Card
        // eslint-disable-next-line no-param-reassign
        delete action.payload.videoCreationDate;
      }

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

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

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

        return originalVideo;
      });

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

          if (!errors.length) {
            const updatedVideoList = videos
              .map((originalVideo) =>
                originalVideo.uid === uid ? { ...originalVideo, ...data.videoUpdate } : originalVideo,
              )
              .filter(
                (originalVideo) => originalVideo.status !== 'DISABLED' || hasPermission(VIDEO_ADMIN, userPermissions),
              );

            actions.push(of(videosAction(updatedVideoList)), of(reloadSelectedVideoAction()));

            if (updateVideo?.lang) {
              actions.push(of(monitoringAction()));
            }

            if (!hasPermission(VIDEO_ADMIN, userPermissions) && updateVideo.status === 'DISABLED') {
              const message = {
                type: TYPE_SUCCESS,
                message: 'Video archived',
              };
              actions.push(of(showNotificationAction(message)));
            }

            if (updateVideo.status === 'DISABLED') {
              actions.push(of(startSearchEventAction({ onlyCounters: true })));
            }
          } else {
            let message = {
              type: TYPE_ERROR,
              message: (errors[0] && 'A video with the same title already exist') || 'Something went wrong',
            };

            if (updateVideo?.refId) {
              message = {
                type: TYPE_ERROR,
                message: 'Video with the GUID already exists. Try another GUID.',
              };
            }

            actions.push(of(showNotificationAction(message)));
          }

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

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