import dayjs from 'dayjs';
import durationPlugin from 'dayjs/plugin/duration';
import { ofType } from 'redux-observable';
import { concat } from 'rxjs';
import { concatMap, delay, filter, map, repeat, takeUntil } from 'rxjs/operators';

import { INTERNAL_ENDPOINT, NON_RECURRING } from '../../constants';

import { liveEventSchedulesSelector, streamIdSelector } from '../selectors';
import { cancelLiveStreamRequestAction, setLiveStreamDataAction, updateLiveEventFormAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getToken } from '@/modules/@common/token/helpers';

dayjs.extend(durationPlugin);

const queryGQL = `
  query getLiveStream($id: String!) {
    getLiveStream(id: $id) {
      url
      schedules {
        id
        title
        startTime
        endTime
        durationIn
      }
      rtmpInputUrl
      rtmpSecondaryInputUrl
      rtmpStreamKey
      rtmpSecondaryStreamKey
      status
      delivery
      region
      liveCcEnabled
      liveCcLang
      recurrent
      recurrentPeriod
      timeZone
      recurrentEndDate
    }
  }
`;

// there 2 places where stored scheduler
// stream weavo and pcn api
// need add id from pcn
function addIdFromPcnLiveEventSchedules(pcnLiveEventSchedules, streamSchedules) {
  return streamSchedules.map((schedule) => {
    const scheduleFromPcnLiveEventSchedules = pcnLiveEventSchedules?.find(
      (pcnLiveEventSchedule) =>
        pcnLiveEventSchedule.endTime === schedule.endTime &&
        pcnLiveEventSchedule.fromTime === schedule.fromTime &&
        pcnLiveEventSchedule.durationIn === schedule.durationIn,
    );

    if (scheduleFromPcnLiveEventSchedules) {
      // eslint-disable-next-line no-param-reassign
      schedule.pcnId = scheduleFromPcnLiveEventSchedules.id;
    }

    return schedule;
  });
}

function getModifiedSchedules(schedules, copy, pcnLiveEventSchedules) {
  const enhancedSchedules = addIdFromPcnLiveEventSchedules(pcnLiveEventSchedules, schedules);
  return copy
    ? enhancedSchedules
        .filter((schedule) => schedule.startTime > Date.now())
        .map((schedule) => ({
          ...schedule,
          duration: dayjs.duration(schedule.endTime - schedule.startTime).as(schedule.durationIn),
          isEditDisabled: false,
          isValid: true,
          errors: {},
        }))
    : enhancedSchedules.map((schedule) => ({
        ...schedule,
        duration: dayjs.duration(schedule.endTime - schedule.startTime).as(schedule.durationIn),
        isEditDisabled: schedule.startTime <= Date.now(),
        isValid: true,
        errors: {},
      }));
}

export default (action$, state$) =>
  action$.pipe(
    ofType(setLiveStreamDataAction.type),
    concatMap(({ payload }) => {
      const { repeatRequest, copy } = payload;
      const streamId = payload?.streamId ?? streamIdSelector(state$.value);
      const liveEventSchedules = liveEventSchedulesSelector(state$.value);

      const additionalArgs = repeatRequest
        ? [
            delay(10000),
            filter(() => !!getToken()),
            repeat(),
            takeUntil(action$.pipe(ofType(cancelLiveStreamRequestAction.type))),
          ]
        : [];

      const stream$ = gqlRequest({
        query: queryGQL,
        variables: {
          id: streamId,
        },
      }).pipe(
        map(({ data, errors }) => {
          if (errors.length) {
            return updateLiveEventFormAction({
              liveStreamRequestFailed: true,
            });
          }

          let modifiedSchedules = [];

          if (data.getLiveStream?.schedules) {
            modifiedSchedules = getModifiedSchedules(data.getLiveStream.schedules, copy, liveEventSchedules);
          }

          const isInternalCopy = data.getLiveStream.delivery === INTERNAL_ENDPOINT && copy;

          const resData = {
            ...data.getLiveStream,
            url: isInternalCopy ? '' : data.getLiveStream.url,
            rtmpInputUrl: isInternalCopy ? '' : data.getLiveStream.rtmpInputUrl,
            rtmpSecondaryInputUrl: isInternalCopy ? '' : data.getLiveStream.rtmpSecondaryInputUrl,
            rtmpStreamKey: isInternalCopy ? '' : data.getLiveStream.rtmpStreamKey,
            rtmpSecondaryStreamKey: isInternalCopy ? '' : data.getLiveStream.rtmpSecondaryStreamKey,
            region: isInternalCopy ? 'US_EAST' : data.getLiveStream.region,
            status: copy ? '' : data.getLiveStream.status,
            schedules: modifiedSchedules,
            isTimezoneDisabled: modifiedSchedules[0]?.startTime < Date.now(),
            recurrentPeriod: data.getLiveStream.recurrent ? data.getLiveStream.recurrentPeriod : NON_RECURRING,
          };

          if (repeatRequest) {
            delete resData.schedules;
            delete resData.recurrent;
            delete resData.recurrentPeriod;
            delete resData.recurrentEndDate;
          }

          return updateLiveEventFormAction(resData);
        }),
        ...additionalArgs,
      );

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