import React, { useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import dynamic from 'next/dynamic';
import { useDraggable } from '@dnd-kit/core';

import { ASPECT_RATIOS } from '@/modules/@common/EmbedCodePopup/constants';
import { DND_MAIN_LIST_OF_VIDEO_TYPE } from '@/modules/editorial/constants/dnd';
import { SELECTED_PLAYER } from '@/modules/editorial/editorialVideoDetails/constants';

import { getPreferences, setPreferences } from '../../../editorialVideoDetails/helpers';
import { getIsWPVideoMode } from '@/modules/@common/app/helpers';
import {
  getPublisherIdsSelector,
  getUserIdSelector,
  getUserPermissionsSelector,
} from '@/modules/@common/user/redux/selectors';
import { createDndId } from '@/modules/editorial/helpers/createDndId';
import { canChangeAccess, canShare } from '@/modules/editorial/shareAndAccess/helpers/permissions';

import VideoDetails from '@/modules/editorial/editorialVideoDetails';
import VideoInfo from '@/modules/editorial/editorialVideoInfo/components/index';
import VideoPlaceholder from '../placeholder';

const EmbedCodePopup = dynamic(() => import('@/modules/@common/EmbedCodePopup'), { ssr: false });
const ShareAndAccess = dynamic(() => import('@/modules/editorial/shareAndAccess/components'), { ssr: false });

function ListItem({
  selectedVideo = null,
  searchFilters = null,
  isInsightsMode = false,
  activeSorter = null,
  selectedPlayer = null,
  selectedAspectRatio = null,
  ...props
}) {
  const video = props.videos[props.index];

  const [showEmbedPopup, setShowEmbedPopup] = useState(false);
  const [includeVideoObject, setIncludeVideoObject] = useState(false);
  const [showShareAndAccess, setShowShareAndAccess] = useState(false);
  const [showListOfSitePopup, setShowListOfSitePopup] = useState(false);
  const [showListOfUserPopup, setShowListOfUserPopup] = useState(false);
  const [showTagEditor, setShowTagEditor] = useState(false);
  const [shouldOpenVideoMenuImmediately, setShouldOpenVideoMenuImmediately] = useState(false);
  const [isWPVideoMode, setIsWPVideoMode] = useState(false);

  const userId = useSelector(getUserIdSelector);
  const userPublisherIds = useSelector(getPublisherIdsSelector);
  const userPermissions = useSelector(getUserPermissionsSelector);

  const {
    attributes,
    listeners,
    setNodeRef,
    isDragging: isDragging$,
  } = useDraggable({
    id: createDndId({
      type: DND_MAIN_LIST_OF_VIDEO_TYPE,
      videoUid: video.uid,
      distributionId: video.distributionId,
      itemIndex: props.index,
    }),
    data: { nodeId: video.uid },
    disabled: props.isDragDisabled,
  });

  const showLoader = props.index === props.videos.length - 1 && props.videos.length < props.totalCount;

  const selectedPlayer$ = selectedPlayer ? { value: selectedPlayer.id, label: selectedPlayer.alias } : null;

  const selectedAspectRatio$ = video?.aspectRatio
    ? ASPECT_RATIOS.find(({ value }) => value === video?.aspectRatio)
    : selectedAspectRatio || ASPECT_RATIOS[0];

  const players = useMemo(
    () =>
      props.players
        .filter((player) => player?.displayEmbedCode)
        .map(({ id, alias, videoObjectSupported }) => ({
          value: id,
          label: alias,
          videoObjectSupported,
        })),
    [props.players],
  );

  const getEmbedCode = ({ player, aspectRatio: changedAspectRatio, seo }) => {
    const playerId = player?.id || selectedPlayer?.id;
    const aspectRatio = changedAspectRatio?.label ?? selectedAspectRatio$.label;

    if (playerId && aspectRatio) {
      let info = {
        videoId: video.distributionId,
        playerId,
        aspectRatio,
      };

      if (seo) {
        info = {
          ...info,
          seo,
          video,
        };
      }
      props.getEmbedCodeAction(info);
    }
  };

  const handlePlayerChange = (playerData) => {
    const player = {
      id: playerData.value,
      alias: playerData.label,
      videoObjectSupported: playerData.videoObjectSupported,
      publisherId: playerData.publisherId,
    };
    props.selectedPlayerAction(player);
    getEmbedCode({ player, seo: includeVideoObject });
    setPreferences(SELECTED_PLAYER, player);
  };

  const handleAspectRatioChange = (aspectRatio) => {
    props.selectedAspectRatioAction(aspectRatio);
    getEmbedCode({ aspectRatio, seo: includeVideoObject });
  };

  const openEmbedPopup = () => {
    getEmbedCode({});
    setShowEmbedPopup(true);
  };

  const openShareAndAccess = () => {
    setShowShareAndAccess(true);
  };

  const closeShareAndAccess = () => {
    setShowShareAndAccess(false);
  };

  const closeEmbedPopup = () => {
    setShowEmbedPopup(false);
    setIncludeVideoObject(false);
  };

  const handleUnselectVideo = () => {
    props.selectedVideoAction({
      uid: null,
    });
  };

  const changeIncludeVideoObject = () => {
    setIncludeVideoObject(!includeVideoObject);
    getEmbedCode({ seo: !includeVideoObject });

    if (!video.name?.length || !video.thumbnailFiles?.length) {
      setIncludeVideoObject(false);

      if (!selectedPlayer?.id) {
        props.getEmbedCodeAction({
          playerId: true,
          seo: !includeVideoObject,
          video,
        });
      }
    }
  };

  const title = isWPVideoMode ? 'Choose Player' : 'Video Embed Code';
  const thumbnailUrl = video?.thumbnailUrl ?? '';

  useEffect(() => {
    if (!selectedPlayer$) {
      const playerFromPrefs = getPreferences()?.[SELECTED_PLAYER] ?? {};
      if (players.find((player) => playerFromPrefs.id === player.value)) {
        props.selectedPlayerAction(playerFromPrefs);
      }
    }
    setIsWPVideoMode(getIsWPVideoMode());
  }, []);

  useEffect(() => {
    if (players.length) {
      props.showEmbedCodeButtonAction(true);
    }
  }, [players]);

  return (
    <div data-id="listItem" id={video.uid} ref={setNodeRef} {...attributes} {...listeners}>
      {video.uid === (selectedVideo && selectedVideo.uid) ? (
        <VideoDetails
          video={video}
          videos={props.videos}
          videosAction={props.videosAction}
          searchFilters={searchFilters}
          canAddToPlaylist={props.canAddToPlaylist}
          addToPlaylistAction={props.addToPlaylistAction}
          openEmbedPopup={openEmbedPopup}
          openShareAndAccess={openShareAndAccess}
          showEmbedButton={props.showEmbedCodeButton}
          isInsightsMode={isInsightsMode}
          playlistMode={props.playlistMode}
          unselectVideo={handleUnselectVideo}
          showListOfSitePopup={showListOfSitePopup}
          setShowListOfSitePopup={setShowListOfSitePopup}
          showListOfUserPopup={showListOfUserPopup}
          setShowListOfUserPopup={setShowListOfUserPopup}
          shouldOpenVideoMenuImmediately={shouldOpenVideoMenuImmediately}
          setShowTagsEditor={setShowTagEditor}
          isTagsEditorOpened={showTagEditor}
        />
      ) : (
        <VideoInfo
          video={video}
          searchFilters={searchFilters}
          canAddToPlaylist={props.canAddToPlaylist}
          addToPlaylistAction={props.addToPlaylistAction}
          selectedVideoAction={props.selectedVideoAction}
          showEmbedButton={props.showEmbedCodeButton}
          openEmbedPopup={openEmbedPopup}
          openShareAndAccess={openShareAndAccess}
          isInsightsMode={isInsightsMode}
          activeSorter={activeSorter}
          isDragging={isDragging$}
          playlistMode={props.playlistMode}
          isPlaylistSectionOpened={props.isPlaylistSectionOpened}
          maxPerformance={props.maxPerformance}
          showListOfSitePopup={showListOfSitePopup}
          setShowListOfSitePopup={setShowListOfSitePopup}
          showListOfUserPopup={showListOfUserPopup}
          setShowListOfUserPopup={setShowListOfUserPopup}
          setShouldOpenVideoMenuImmediately={setShouldOpenVideoMenuImmediately}
          openTagsEditor={setShowTagEditor}
        />
      )}
      {showLoader && <VideoPlaceholder onMount={props.loadNextEventAction} />}

      {/* Prevent drag'n'drop for modal  */}
      <div onPointerDown={(e) => e.stopPropagation()}>
        {showEmbedPopup && (
          <EmbedCodePopup
            title={title}
            onClose={closeEmbedPopup}
            selectedPlayer={selectedPlayer$}
            players={players}
            handlePlayerChange={handlePlayerChange}
            selectedAspectRatio={selectedAspectRatio$}
            handleAspectRatioChange={handleAspectRatioChange}
            isAspectRatioDisabled={video?.aspectRatio}
            embedCode={props.embedCode}
            isInProcessing={video.status === 'PROCESSING'}
            thumbnail={thumbnailUrl}
            isCopyDisabled={!selectedPlayer$}
            videoObjectChecked={selectedPlayer && !selectedPlayer?.videoObjectSupported ? false : includeVideoObject}
            videoObjectOnChange={changeIncludeVideoObject}
            showVideoObjectSwitch
            disableVideoObjectSwitch={selectedPlayer && !selectedPlayer?.videoObjectSupported}
          />
        )}

        {showShareAndAccess && (
          <ShareAndAccess
            onClose={closeShareAndAccess}
            video={video}
            canShare={canShare(video, userPublisherIds, userId)}
            canChangeAccess={canChangeAccess(video, userId, userPermissions)}
          />
        )}
      </div>
    </div>
  );
}

ListItem.propTypes = {
  addToPlaylistAction: PropTypes.func.isRequired,
  canAddToPlaylist: PropTypes.bool.isRequired,
  embedCode: PropTypes.string.isRequired,
  getEmbedCodeAction: PropTypes.func.isRequired,
  index: PropTypes.number.isRequired,
  loadNextEventAction: PropTypes.func.isRequired,
  players: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  searchFilters: PropTypes.shape({}),
  selectedAspectRatio: PropTypes.shape({}),
  selectedAspectRatioAction: PropTypes.func.isRequired,
  selectedPlayer: PropTypes.shape({
    id: PropTypes.string.isRequired,
    alias: PropTypes.string.isRequired,
    videoObjectSupported: PropTypes.string.isRequired,
  }),
  selectedPlayerAction: PropTypes.func.isRequired,
  selectedVideo: PropTypes.shape({
    uid: PropTypes.string.isRequired,
  }),
  selectedVideoAction: PropTypes.func.isRequired,
  totalCount: PropTypes.number.isRequired,
  videos: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  videosAction: PropTypes.func.isRequired,
  isInsightsMode: PropTypes.bool,
  isDragging: PropTypes.bool,
  playlistMode: PropTypes.string.isRequired,
  activeSorter: PropTypes.string,
  showEmbedCodeButtonAction: PropTypes.func.isRequired,
  showEmbedCodeButton: PropTypes.bool.isRequired,
  isPlaylistSectionOpened: PropTypes.bool.isRequired,
  isDragDisabled: PropTypes.bool.isRequired,
  maxPerformance: PropTypes.shape({
    completed: PropTypes.number,
    engagement: PropTypes.number,
    likes: PropTypes.number,
    avgPlayback: PropTypes.number,
    minutesViewed: PropTypes.number,
    recommendationPlaylistRatio: PropTypes.number,
    s20VideoViews: PropTypes.number,
    shares: PropTypes.number,
    trending: PropTypes.number,
    uniqueUsers: PropTypes.number,
    views: PropTypes.number,
  }).isRequired,
};

export default ListItem;
