import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'next/navigation';
import { useRouter } from 'next/router';
import { CodeRounded } from '@mui/icons-material';

import {
  ASPECT_RATIO,
  EVENT_STATUS_ARCHIVED,
  EVENT_UX_TYPES_IMAGE,
  EVENT_UX_TYPES_RECOMMENDED,
  EVENT_UX_TYPES_SAME,
  INTERNAL_ENDPOINT,
  POST_EVENT,
  PRE_EVENT,
  TAB_EVENT_DELIVERY,
  TAB_EVENT_DETAILS,
  TAB_EVENT_PRE_POST,
  TAB_EVENT_SCHEDULE,
} from '../constants';
import { TYPE_ERROR } from '@/modules/@common/notify/constants';

import validateField, { getTimeWithoutS } from '../helpers/validation';
import {
  activeTabIdSelector,
  aspectRatioSelector,
  createdPostEventPlaylistSelector,
  createdPreEventPlaylistSelector,
  deliverySelector,
  embedCodeSelector,
  errorsSelector,
  eventStatusSelector,
  idSelector,
  isEditContinueSelector,
  isLoadingSelector,
  liveCcEnabledSelector,
  liveCcLangSelector,
  liveStreamRequestFailedSelector,
  nameSelector,
  playerAspectRatioSelector,
  playerConfigSelector,
  playerIdSelector,
  playerSelector,
  postEventIdSelector,
  postEventImagesSelector,
  postEventTypeSelector,
  preEventIdSelector,
  preEventImagesSelector,
  preEventTypeSelector,
  publisherIdSelector,
  publishersSelector,
  recurrentEndDateSelector,
  recurrentSelector,
  schedulesSelector,
  tmPlaylistSelector,
  urlSelector,
} from '../redux/selectors';
import {
  clearFormAction,
  createLiveEventFlowAction,
  deleteLiveEventPlaylistAction,
  getLiveEventByIdAction,
  getLiveEventContentOwnerAction,
  getLiveEventDefaultImagesAction,
  getLiveEventEmbedCodeAction,
  getLiveEventImageAction,
  getPlayerConfigAction,
  getPublisherInfoByIdAction,
  getPublisherPlayersAction,
  setActiveTabIdAction,
  setErrorAction,
  updateLiveEventFlowAction,
  updateLiveEventFormAction,
} from '../redux/slices';
import { getPlaylistApiEndpoint } from '@/modules/@common/PlayerWidget/helpers';
import { showNotificationAction } from '@/modules/layout/redux/slices';

import EmbedCodePopup from '@/modules/@common/EmbedCodePopup';
import { Form, FormContent, FormGroup, FormRow, FormSection } from '@/modules/@common/Form';
import useForceReload from '../hooks/useForceReload';
import useIsAllowedToCreateOrEdit from '../hooks/useIsAllowedToCreateOrEdit';
import EventDelivery from './EventDelivery';
import EventPrePost from './EventPrePost';
import EventSchedule from './EventSchedule';
import EventSetting from './EventSetting';
import PlayerPreview from './PlayerPreview';
import ForcePoster from './PlayerPreview/components/ForсePoster/ForсePoster';
import ViewersCounter from './PlayerPreview/components/ViewersCounter/ViewersCounter';
import { Button, Divider, Stack, Tab, TabContent, Tabs, Typography } from '@/mui/components';

import styles from './styles.module.scss';

const LIVE_EVENT_DISABLED_STATUS = -1;

function LiveEvent() {
  const dispatch = useDispatch();
  const router = useRouter();
  const { id: paramsId } = useParams();
  const id = useSelector(idSelector) ?? 0;
  const name = useSelector(nameSelector);
  const url = useSelector(urlSelector);
  const publisherId = useSelector(publisherIdSelector);
  const playerId = useSelector(playerIdSelector);
  const playerAspectRatio = useSelector(playerAspectRatioSelector);
  const preEventType = useSelector(preEventTypeSelector);
  const preEventId = useSelector(preEventIdSelector);
  const postEventType = useSelector(postEventTypeSelector);
  const postEventId = useSelector(postEventIdSelector);
  const errors = useSelector(errorsSelector);
  const isEditContinue = useSelector(isEditContinueSelector);
  const embedCode = useSelector(embedCodeSelector);
  const preEventImages = useSelector(preEventImagesSelector);
  const postEventImages = useSelector(postEventImagesSelector);
  const activeTabId = useSelector(activeTabIdSelector);
  const createdPreEventPlaylist = useSelector(createdPreEventPlaylistSelector);
  const createdPostEventPlaylist = useSelector(createdPostEventPlaylistSelector);
  const isLoading = useSelector(isLoadingSelector);
  const playerConfig = useSelector(playerConfigSelector);
  const eventStatus = useSelector(eventStatusSelector);
  const liveStreamRequestFailed = useSelector(liveStreamRequestFailedSelector);
  const schedules = useSelector(schedulesSelector);
  const publishers = useSelector(publishersSelector);
  const liveCcEnabled = useSelector(liveCcEnabledSelector);
  const liveCcLang = useSelector(liveCcLangSelector);
  const recurrentEndDate = useSelector(recurrentEndDateSelector);
  const delivery = useSelector(deliverySelector);
  const tmPlaylist = useSelector(tmPlaylistSelector);
  const aspectRatio = useSelector(aspectRatioSelector);
  const player = useSelector(playerSelector);
  const recurrent = useSelector(recurrentSelector);
  const [playerWidget, setPlayerWidget] = useState(null);

  const [force, reload] = useForceReload(100);

  const { id: existedEventId } = router.query;
  const isArchived = eventStatus === EVENT_STATUS_ARCHIVED;
  const [showEmbedPopup, setShowEmbedPopup] = useState(false);

  const copiedEventId = router.query.copied;
  const liveEventId = +existedEventId || copiedEventId;

  const isAllowedToCreateOrEdit = useIsAllowedToCreateOrEdit();

  const updatePlayerPreview = (fieldName, fieldValue) => {
    if (playerWidget && tmPlaylist) {
      const tmPlaylist$ = {
        geo: {
          ...tmPlaylist.geo,
        },
        liveEvent: {
          ...tmPlaylist.liveEvent,
        },
        userAgent: {
          ...tmPlaylist.userAgent,
        },
      };

      if (fieldValue) {
        tmPlaylist$.liveEvent[fieldName] = fieldValue;
      }

      // if (fieldName === 'url') {
      //   tmPlaylist$.liveEvent.liveUrl = fieldName;
      // }

      if (fieldName === 'poster' && preEventImages.length) {
        tmPlaylist$.liveEvent.prePoster = [[...preEventImages]];
      }

      if (fieldName === 'poster' && postEventImages.length) {
        tmPlaylist$.liveEvent.postPoster = [[...postEventImages]];
      }

      if (playerWidget.setExternalPlaylistResponse) {
        playerWidget.setExternalPlaylistResponse(tmPlaylist$);
      }

      dispatch(
        updateLiveEventFormAction({
          tmPlaylist: tmPlaylist$,
        }),
      );
    }
  };

  useEffect(() => {
    if (publisherId) {
      dispatch(getPublisherInfoByIdAction(publisherId));
    }
  }, [publisherId]);

  useEffect(() => () => dispatch(clearFormAction()), []);

  useEffect(() => {
    updatePlayerPreview('poster');
  }, [preEventImages, postEventImages, playerWidget]);

  useEffect(() => {
    updatePlayerPreview('aspectRatio', aspectRatio);
  }, [aspectRatio]);

  const handleEmbedLiveEvent = (eventId) => {
    setShowEmbedPopup(true);
    dispatch(getLiveEventEmbedCodeAction(eventId));
  };

  const handleOnSaveClick = () => {
    if (!schedules[0].isEditDisabled && schedules[0].startTime + 5 * 60 * 1000 < getTimeWithoutS(Date.now())) {
      dispatch(
        showNotificationAction({
          type: TYPE_ERROR,
          message: 'The event may not be set more than 5 minutes in the past',
        }),
      );
      return;
    }

    if (id) {
      dispatch(updateLiveEventFlowAction());
      return;
    }

    dispatch(createLiveEventFlowAction());
  };

  const handleOnChange = (fieldName, fieldValue) => {
    if (fieldName === 'description' && fieldValue.length > 250) {
      return;
    }
    dispatch(
      updateLiveEventFormAction({
        [fieldName]: fieldValue,
      }),
    );

    if (
      [
        'preEventText',
        'postEventText',
        'transitionText',
        'countdown',
        'indicationText',
        'indicationColor',
        'name',
      ].includes(fieldName)
    ) {
      updatePlayerPreview(fieldName, fieldValue);
      reload();
    }

    if (['name', 'url', 'playerId'].includes(fieldName)) {
      validateField(
        {
          fieldName,
          fieldValue,
        },
        (params) => dispatch(setErrorAction(params)),
      );
    }

    if (['preEventType', 'postEventType'].includes(fieldName)) {
      const fieldIdToUpdate = fieldName === 'preEventType' ? 'preEventId' : 'postEventId';

      if (fieldValue === EVENT_UX_TYPES_RECOMMENDED) {
        dispatch(
          updateLiveEventFormAction({
            [fieldIdToUpdate]: null,
          }),
        );
      }

      if (fieldValue === EVENT_UX_TYPES_IMAGE) {
        const type = fieldName === 'preEventType' ? PRE_EVENT : POST_EVENT;
        const imagesAspectRatio = ASPECT_RATIO[playerAspectRatio];
        dispatch(
          updateLiveEventFormAction({
            [fieldIdToUpdate]: null,
          }),
        );
        dispatch(
          getLiveEventDefaultImagesAction({
            eventType: type,
            aspectRatio: imagesAspectRatio,
          }),
        );
      }

      if (fieldValue === EVENT_UX_TYPES_SAME) {
        dispatch(
          updateLiveEventFormAction({
            postEventId: preEventId,
            postEventImages: preEventImages,
          }),
        );
      }
    }
  };

  const tabs = [
    {
      title: 'General',
      id: TAB_EVENT_DETAILS,
      dataId: 'eventSetting',
      content: EventSetting,
    },
    {
      title: 'Schedule',
      id: TAB_EVENT_SCHEDULE,
      dataId: 'eventSchedule',
      content: EventSchedule,
    },
    {
      title: 'Delivery',
      id: TAB_EVENT_DELIVERY,
      dataId: 'eventDelivery',
      content: EventDelivery,
    },
    {
      title: 'Pre/Post',
      id: TAB_EVENT_PRE_POST,
      dataId: 'eventPrePost',
      content: EventPrePost,
    },
  ];

  useEffect(() => {
    if (!isEditContinue && liveEventId) {
      dispatch(
        getLiveEventByIdAction({
          id: +liveEventId,
          copy: !!copiedEventId,
          publisherId,
        }),
      );
    }
  }, [liveEventId]);

  useEffect(() => {
    if (publisherId) {
      dispatch(
        getPublisherPlayersAction({
          publisherId,
        }),
      );
      dispatch(
        getLiveEventContentOwnerAction({
          publisherId,
        }),
      );
    }

    if (preEventId && preEventType === EVENT_UX_TYPES_IMAGE && !preEventImages?.length) {
      dispatch(
        getLiveEventImageAction({
          id: preEventId,
          type: PRE_EVENT,
        }),
      );
    }

    if (postEventId && postEventType === EVENT_UX_TYPES_IMAGE && !postEventImages?.length) {
      dispatch(
        getLiveEventImageAction({
          id: postEventId,
          type: POST_EVENT,
        }),
      );
    }
  }, [publisherId, preEventType, postEventType, preEventImages]);

  useEffect(() => {
    if (!playerConfig && !!playerId && !!id && !!url && !!player && publishers.length) {
      dispatch(getPlayerConfigAction());
    }
  }, [playerId, playerConfig, id, url, liveStreamRequestFailed, player, publishers]);

  useEffect(() => {
    if (
      (postEventId === preEventId && preEventType === postEventType) ||
      (!postEventId && !preEventId && postEventType === preEventType) ||
      postEventType === EVENT_UX_TYPES_SAME
    ) {
      dispatch(
        updateLiveEventFormAction({
          postEventType: EVENT_UX_TYPES_SAME,
          postEventId: preEventId,
          postEventImages: preEventImages,
        }),
      );
    }
  }, [preEventId, postEventId, preEventImages, postEventType]);

  useEffect(() => {
    if (!liveEventId) {
      dispatch(clearFormAction());
    }
  }, [router, liveEventId]);

  const handleClose = () => {
    router.push('/live');

    if (createdPreEventPlaylist) {
      dispatch(
        deleteLiveEventPlaylistAction({
          id: +preEventId,
          publisherId,
        }),
      );
    }
    if (createdPostEventPlaylist) {
      dispatch(
        deleteLiveEventPlaylistAction({
          id: +postEventId,
          publisherId,
        }),
      );
    }
    dispatch(clearFormAction());
  };

  const isSaveDisabled = () =>
    [name, url, playerId, publisherId].some((item) => !item) ||
    Object.keys(errors).some((key) => !errors[key].isValid) ||
    schedules.some((schedule) => !schedule.isValid) ||
    !schedules.length ||
    isLoading ||
    (delivery === INTERNAL_ENDPOINT && liveCcEnabled && !liveCcLang);

  const cachedPlayerContent = useMemo(
    () =>
      playerConfig && force ? (
        <PlayerPreview
          key={force}
          id={Math.random().toString()}
          conf={{
            ...playerConfig,
            lre_export_for_demo: true,
            tmPassthrough: {
              leid: id,
            },
            lre_playlistApiEndpoint: getPlaylistApiEndpoint(),
          }}
          publisherId={playerConfig.publisherId}
          widgetId={playerConfig.widgetId}
          onWidgetUpdate={(widget) => setPlayerWidget(widget)}
        />
      ) : null,
    [playerConfig, force],
  );

  const shouldShowViewCounter =
    eventStatus !== LIVE_EVENT_DISABLED_STATUS &&
    Date.now() > schedules[0]?.startTime &&
    (Date.now() < schedules[schedules.length - 1]?.endTime || (recurrent && Date.now() < recurrentEndDate));

  const newEvent = paramsId === 'new';

  return (
    <div className={styles.Wrapper}>
      <Stack direction="column" fullWidth justifyContent="center" className={styles.Title}>
        <Typography component="div" variant="h6" noWrap>
          {newEvent ? 'New Live Event' : `${name} > Settings`}
        </Typography>
      </Stack>
      <Stack
        spacing={1}
        fullWidth
        direction="row"
        alignItems="center"
        justifyContent="space-between"
        className={styles.Controls}
      >
        {tabs.length > 1 && (
          <Tabs
            className={styles.Tabs}
            value={activeTabId}
            onChange={(_, value) => {
              dispatch(setActiveTabIdAction(value));
            }}
          >
            {tabs.map((tab) => (
              <Tab key={tab.id} label={tab.title} value={tab.id} disabled={tab.disabled} />
            ))}
          </Tabs>
        )}
        <Stack spacing={2} justifyContent="flex-end" alignItems="center" direction="row">
          <Button
            size="small"
            disabled={!id || isArchived}
            variant="text"
            color="neutral"
            data-id="liveEventEmbed"
            onClick={() => handleEmbedLiveEvent(id)}
            startIcon={<CodeRounded />}
          >
            Embed Live
          </Button>
          <Divider flexItem />
          <Button variant="outlined" size="small" color="primary" onClick={handleClose} disabled={!!id && isLoading}>
            Cancel
          </Button>
          {isAllowedToCreateOrEdit && (
            <Button
              size="small"
              variant="contained"
              color="primary"
              data-id="liveEventSave"
              disabled={isSaveDisabled() || isArchived}
              onClick={handleOnSaveClick}
            >
              Save
            </Button>
          )}
        </Stack>
      </Stack>
      <Form loading={!!id && isLoading}>
        <FormContent>
          {tabs.map((tab) => {
            const Content = tab.content;

            return (
              <TabContent key={tab.id} selectedId={activeTabId} id={tab.id} component={FormSection}>
                <Content handleOnChange={handleOnChange} />
              </TabContent>
            );
          })}
          {(!newEvent || (!!newEvent && !!cachedPlayerContent)) && (
            <FormSection>
              <FormRow fullWidth>
                <div className={styles.PlayerWrapper}>{cachedPlayerContent}</div>
              </FormRow>
              {!!cachedPlayerContent && (
                <FormGroup fullWidth>
                  {shouldShowViewCounter && <ViewersCounter />}
                  <ForcePoster />
                </FormGroup>
              )}
            </FormSection>
          )}
        </FormContent>
      </Form>
      {showEmbedPopup && (
        <EmbedCodePopup
          isPlayerDisabled
          isAspectRatioDisabled
          title="Live Event Embed Code"
          embedCode={embedCode}
          onClose={() => setShowEmbedPopup(false)}
        />
      )}
    </div>
  );
}

export default LiveEvent;
