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

import { EVENT_UX_TYPES_SAME } from '../../constants';
import { TYPE_SUCCESS } from '@/modules/@common/notify/constants';

import { getEventData } from '../../helpers/request';
import {
  getLiveEventByIdAction,
  setIsLoadingAction,
  slice,
  updateForcePosterStatusAction,
  updateLiveEventAction,
  updateViewersCounterStatusAction,
} from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { showNotificationAction } from '@/modules/layout/redux/slices';
import { idSelector } from '@/modules/liveEvents/liveEvent/redux/selectors';

const queryGQL = `
  mutation updateLiveEvent(
    $id: Int!,
    $name: String!,
    $description: String,
    $guid: String,
    $streamId: String!,
    $timezone: String,
    $liveEventSchedules: [LiveEventSchedulesInputType]!,
    $indicationText: String,
    $indicationColor: String,
    $playerId: Float!,
    $preEventText: String,
    $preEventType: String,
    $preEventId: String,
    $postEventText: String,
    $postEventType: String,
    $postEventId: String,
    $transitionText: String,
    $countdown: Boolean,
    $startTime: Float,
    $endTime: Float,
    $aspectRatio: String!,
    $recurrent: Boolean,
    $recurrentEndDate: Float,
    $displayViewersCounter: Boolean,
    $forcePoster: Boolean,
    $forcePosterType: String,
  ) {
    updateLiveEvent(
      id: $id,
      name: $name,
      description: $description,
      guid: $guid,
      streamId: $streamId,
      timezone: $timezone,
      liveEventSchedules: $liveEventSchedules,
      indicationText: $indicationText,
      indicationColor: $indicationColor,
      playerId: $playerId,
      preEventText: $preEventText,
      preEventType: $preEventType,
      preEventId: $preEventId,
      postEventText: $postEventText,
      postEventType: $postEventType,
      postEventId: $postEventId,
      transitionText: $transitionText,
      countdown: $countdown,
      startTime: $startTime,
      endTime: $endTime,
      aspectRatio: $aspectRatio,
      recurrent: $recurrent,
      recurrentEndDate: $recurrentEndDate,
      displayViewersCounter: $displayViewersCounter,
      forcePoster: $forcePoster,
      forcePosterType: $forcePosterType,
    ) {
      id
      name
      description
      timezone
      streamId
      indicationText
      indicationColor
      playerId
      guid
      preEventText
      postEventText
      countdown
      transitionText
      preEventType
      preEventId
      postEventType
      postEventId
      liveEventSchedules {
        id
        title
        startTime
        endTime
        durationIn
      }
      player {
        name
        id
        publisher {
          name
          id
        }
      },
      aspectRatio
      status
      recurrent,
      recurrentEndDate,
      displayViewersCounter,
      forcePoster,
      forcePosterType,
    }
  }
`;

export default (action$, state$) =>
  action$.pipe(
    ofType(updateLiveEventAction.type, updateViewersCounterStatusAction.type, updateForcePosterStatusAction.type),
    filter(() => !!idSelector(state$.value)),
    switchMap((action) => {
      const getUpdateSpecificProperties = {
        [updateViewersCounterStatusAction.type]: {
          getProperties: (state) => ({
            displayViewersCounter: state.displayViewersCounter,
            forcePoster: state.forcePoster,
            forcePosterType: state.forcePosterType,
          }),
          notificationMessage: 'Display on Player Saved',
        },
        [updateForcePosterStatusAction.type]: {
          getProperties: (state) => ({
            forcePoster: state.forcePoster,
            forcePosterType: state.forcePosterType,
            displayViewersCounter: state.displayViewersCounter,
          }),
          notificationMessage: 'Force Poster is Saved',
        },
      };

      const updateSpecificProperties = getUpdateSpecificProperties[action.type];
      const data = getEventData(state$.value[slice.name], updateSpecificProperties);
      const id = idSelector(state$.value);

      if (data.postEventType === EVENT_UX_TYPES_SAME) {
        data.postEventType = data.preEventType;
      }

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

          if (!errors.length) {
            actions.push(
              of(
                showNotificationAction({
                  type: TYPE_SUCCESS,
                  message: !updateSpecificProperties ? 'Event Saved' : updateSpecificProperties.notificationMessage,
                }),
              ),
            );

            if (!updateSpecificProperties) {
              actions.push(of(getLiveEventByIdAction({ id })));
            }
          }

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

      return concat(of(setIsLoadingAction(true)), stream$);
    }),
  );
