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

import { TYPE_ERROR } from '@/modules/@common/notify/constants';

import { embedCodeAction, getEmbedCodeAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getToken } from '@/modules/@common/token/helpers';
import { showNotificationAction } from '@/modules/layout/redux/slices';

dayjs.extend(durationPlugin);

const queryGQL = `
  query getPlaylistEmbedCode(
    $aspectRatio: String,
    $playerId: Int!,
    $playlistId: String,
    $seo: Boolean,
    $name: String,
    $desc: String,
    $duration: String,
    $thumbnailUrl: String,
    $uploadDate: String,
    $views: Int,
    $contentUrl: String,
  ) {
    getPlaylistEmbedCode(
      aspectRatio: $aspectRatio,
      playerId: $playerId,
      playlistId: $playlistId,
      seo: $seo,
      name: $name,
      desc: $desc,
      duration: $duration,
      thumbnailUrl: $thumbnailUrl,
      uploadDate: $uploadDate,
      views: $views
      contentUrl: $contentUrl,
    ) {
      displayEmbedCode
      embedCode
    }
  }
`;

export default (action$) =>
  action$.pipe(
    ofType(getEmbedCodeAction.type),
    filter((action) => action.payload.playerId || !!getToken()),
    switchMap((action) => {
      const { videoId, playerId, aspectRatio, seo, video } = action.payload;

      let videoInfo = {};

      if (seo) {
        let thumbnailUrl = '';
        const uploadDate = new Date(video.created);

        if (video.thumbnailFiles?.length) {
          const thumbnailSorted = video.thumbnailFiles.slice().sort((a, b) => a.width - b.width);
          const thumbnail =
            thumbnailSorted.find((item) => item.width >= 480 && item.height >= 270) ?? thumbnailSorted.pop();
          thumbnailUrl = thumbnail.file ?? '';
        }

        videoInfo = {
          seo,
          name: video.name,
          desc: video.plot ?? '',
          thumbnailUrl: thumbnailUrl
            .replace('cdn5.anyclip.com', 'stream.geniusplus.ai')
            .replace('aceu-weavo-euprod.eu.anyclip.com', 'stream-eu.geniusplus.ai'),
          duration: dayjs.duration(video.videoLength).toISOString(),
          uploadDate: uploadDate.toISOString(),
          views: video.performanceTotal?.numberOfViews ?? 0,
        };

        const contentUrl = video?.videoFiles.reduce((prevVideo, nextVideo) => {
          const currentResolution = nextVideo.width * nextVideo.height;
          const prevResolution = prevVideo.width * prevVideo.height;

          return currentResolution > prevResolution ? nextVideo : prevVideo;
        });

        if (contentUrl?.file) {
          videoInfo.contentUrl = contentUrl.file;
        }

        if (!videoInfo.name.length) {
          return concat(
            of(
              showNotificationAction({
                type: TYPE_ERROR,
                message: 'This Video couldn’t be added to the VideoObject for SEO as the name field is missing.',
              }),
            ),
          );
        }

        if (!videoInfo.thumbnailUrl.length) {
          return concat(
            of(
              showNotificationAction({
                type: TYPE_ERROR,
                message:
                  'This Video couldn’t be added to the VideoObject for SEO as the thumbnail URL field is missing.',
              }),
            ),
          );
        }

        if (!videoInfo.uploadDate.length) {
          return concat(
            of(
              showNotificationAction({
                type: TYPE_ERROR,
                message: 'This Video couldn’t be added to the VideoObject for SEO as the upload date field is missing.',
              }),
            ),
          );
        }
      }

      const stream$ = gqlRequest({
        query: queryGQL,
        variables: {
          aspectRatio,
          playerId,
          playlistId: videoId,
          ...videoInfo,
        },
      }).pipe(
        switchMap(({ data, errors }) => {
          let actions = [];

          if (!errors.length) {
            actions = [of(embedCodeAction(data.getPlaylistEmbedCode.embedCode))];
          }

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

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