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

import { TYPE_ERROR } from '@/modules/@common/notify/constants';
import { UPLOAD_STATUS_COMPLETE, UPLOAD_STATUS_FAILED } from '@/modules/uploaderNew/constants';

import { getCurrentUploadStateFromQueue, processedUploadQueueIdSelector } from '../selectors';
import {
  createVideoVersionAction,
  errorAction,
  loadingAction,
  loadingProgressAction,
  setProcessUploadStatusAction,
  startUploadFromQueueAction,
} from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { videosSelector } from '@/modules/editorial/editorialSearchResults/redux/selectors';
import {
  videosAction,
  videosChangeProcessingStatusMonitoringAction,
} from '@/modules/editorial/editorialSearchResults/redux/slices';
import { selectedVideoSelector } from '@/modules/editorial/editorialVideoDetails/redux/selectors';
import { selectedVideoAction } from '@/modules/editorial/editorialVideoDetails/redux/slices';
import { showNotificationAction } from '@/modules/layout/redux/slices';

const queryGQL = `
  mutation CreateNewVideoVersion(
    $videoId: String!
    $videoUrl: String!
    $videoCreationDate: Float!
    $features: [String]
    $videoVersionId: String
    $videoVersionNotes: String
    $sites: [String]
  ) {
    createNewVideoVersion(
      videoId: $videoId
      videoUrl: $videoUrl
      videoCreationDate: $videoCreationDate
      features: $features
      videoVersionId: $videoVersionId
      videoVersionNotes: $videoVersionNotes
      sites: $sites
    )
  }
`;

const FEATURES_SEND_NOTIFICATION = 'SEND_NOTIFICATION';
const FEATURES_SEND_HUBS_NOTIFICATION = 'SEND_HUBS_NOTIFICATION';

const getErrorMessage = (errors) => {
  const { message } = errors[0];

  return message;
};

export default (action$, state$) =>
  action$.pipe(
    ofType(createVideoVersionAction.type),
    switchMap(() => {
      const processedUploadQueueId = processedUploadQueueIdSelector(state$.value);
      const {
        videoId,
        uploadVideo,
        videoUrl,
        date,
        isNotify,
        isNotifyToAccessUsers,
        videoVersionId,
        videoVersionNotes,
        videoAccess,
      } = getCurrentUploadStateFromQueue(state$.value);

      const videos = videosSelector(state$.value);
      const selectedVideo = selectedVideoSelector(state$.value);

      const variables = {
        videoId,
        videoUrl: uploadVideo.downloadUrl || videoUrl,
        videoCreationDate: dayjs(date || new Date())
          .utc()
          .valueOf(),
        features: [],
      };

      if (isNotify) {
        variables.features.push(FEATURES_SEND_NOTIFICATION);
      }

      if (isNotifyToAccessUsers) {
        variables.features.push(FEATURES_SEND_HUBS_NOTIFICATION);
      }

      if (videoVersionId) {
        variables.videoVersionId = videoVersionId;
      }

      if (videoVersionNotes) {
        variables.videoVersionNotes = videoVersionNotes;
      }

      if (videoAccess?.sites) {
        variables.sites = videoAccess.sites.map((site) => site.id);
      }

      const stream$ = gqlRequest(
        {
          query: queryGQL,
          variables,
        },
        {
          showNotificationMessage: false,
        },
      ).pipe(
        switchMap(({ errors }) => {
          const actions = [];

          if (errors.length) {
            actions.push(
              of(
                showNotificationAction({
                  type: TYPE_ERROR,
                  message: getErrorMessage(errors),
                }),
              ),
              of(
                setProcessUploadStatusAction({
                  status: UPLOAD_STATUS_FAILED,
                  processedUploadQueueId,
                }),
              ),
              of(startUploadFromQueueAction()),
            );
          } else {
            const updateVideoList = videos.map((video) => {
              if (video.uid === videoId) {
                return {
                  ...video,
                  status: 'PROCESSING',
                };
              }
              return video;
            });
            actions.push(
              of(
                loadingProgressAction({
                  percentage: 1,
                  processedUploadQueueId,
                }),
              ),
              of(
                setProcessUploadStatusAction({
                  status: UPLOAD_STATUS_COMPLETE,
                  processedUploadQueueId,
                }),
              ),
              of(startUploadFromQueueAction()),
              of(videosAction(updateVideoList)),
              of(videosChangeProcessingStatusMonitoringAction()),
            );

            if (selectedVideo?.uid === videoId) {
              actions.push(of(selectedVideoAction({ ...selectedVideo, status: 'PROCESSING' })));
            }
          }

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

      return concat(stream$, of(loadingAction(false)), of(errorAction({})));
    }),
  );
