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

import { playlistIdSelector, playlistsSelector } from '../../selectors';
import { getPlaylistByIdAction, setPlaylistsAction, updatePlaylistAction } from '../../slices';
import { gqlRequest } from '@/modules/@common/request';

const queryGQL = `
  mutation updatePlaylist(
  $playlistId: Int!,
  $publisherId: Int!,
  $name: String,
  $clips: [String],
  $playerId: Int,
  $isPrefix: Boolean,
  $status: Boolean
  $shuffle: Boolean
  ) {
    updatePlaylist(
      playlistId: $playlistId,
      publisherId: $publisherId,
      name: $name,
      clips: $clips,
      playerId: $playerId,
      isPrefix: $isPrefix,
      status: $status
      shuffle: $shuffle
    ){
      playlistId
    }
  }
`;

export default (action$, state$) =>
  action$.pipe(
    ofType(updatePlaylistAction.type),
    filter(({ payload }) => payload.publisherId),
    concatMap(({ payload }) => {
      const plId = playlistIdSelector(state$.value);

      const playlistId = payload?.playlistId || plId;

      const data = { ...payload };

      if (payload?.clips) {
        data.clips = payload.clips.filter((id) => id).map((id) => id.toString());
      }

      const stream$ = gqlRequest({ query: queryGQL, variables: { ...data, playlistId } }).pipe(
        concatMap((_, errors) => {
          const actions = [];

          if (!errors.length) {
            if (payload?.shouldRefreshCurrentPlaylistData) {
              actions.push(of(getPlaylistByIdAction({ id: playlistId })));
            }
          }

          const playlists = playlistsSelector(state$.value);
          const updatedPlaylists = playlists.map((playlist) => {
            if (playlist.id === playlistId) {
              return {
                ...playlist,
                ...payload,
                videos: payload?.clips
                  ? (playlist.videos ?? []).filter((video$) => data.clips?.includes(video$.distributionId.toString()))
                  : playlist.videos,
              };
            }

            return playlist;
          });

          actions.push(of(setPlaylistsAction(updatedPlaylists)));

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

      return concat(stream$);
    }),
  );
