/* eslint jsx-a11y/click-events-have-key-events: warn */

/* eslint jsx-a11y/no-static-element-interactions: warn */
import { useGateValue } from '@statsig/react-bindings';
import { observer } from 'mobx-react-lite';
import React, { useCallback, useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';

import { useStores } from '@/app/(root)/AppProviders';
import Button, { ButtonVariant } from '@/components/button/Button';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import { toast } from '@/components/toast/Toast';
import { useModalContext } from '@/context/ModalContext';
import { Playlist } from '@/state/clipStore';
import { getClipTitle } from '@/utils/clip';
import {
  FALLBACK_AURA_URL,
  LIKED_SONGS_PLAYLIST_COVER_URL,
  SMALL_IMAGE,
} from '@/utils/constants';
import { canUserEditPlaylist } from '@/utils/playlistConditionUtils';
import { staticAssetUrl } from '@/utils/staticAssetUrl';
import { PLAYLISTS_PAGE_SIZE } from '@/utils/utils';

import SpinnerSVG from '../svg/SpinnerSVG';
import Modal from './Modal';

const AddToPlaylistModal: React.FC = observer(() => {
  const {
    library: libraryStore,
    clips: clipsStore,
    playlist: playlistStore,
    menus: menusStore,
    session,
  } = useStores();

  const { closeModal, getModalData } = useModalContext();
  const modalData = getModalData(ModalTypes.ADD_TO_PLAYLIST);

  const onClose = useCallback(() => {
    closeModal(ModalTypes.ADD_TO_PLAYLIST);
  }, [closeModal]);

  const { contextType, recommendationItemId, hookId } = modalData || {};
  const showSharelist = useGateValue(
    'enable-sharelist-and-share-notifications'
  );

  const { ref: spinnerRef } = useInView({
    threshold: 0,
    onChange: async (inView) => {
      if (inView) {
        const pageToLoad =
          Math.floor(clipsStore.allPlaylists?.length / PLAYLISTS_PAGE_SIZE) + 1;
        libraryStore.loadPlaylists(pageToLoad, showSharelist);
      }
    },
  });

  const [createPlaylistLoading, setCreatePlaylistLoading] =
    useState<boolean>(false);

  const selectedClipIds = menusStore.selectedClipIds;

  useEffect(() => {
    if (session.userId) {
      libraryStore.loadPlaylists(undefined, showSharelist);
    }
  }, [session.userId, libraryStore, showSharelist]);

  useEffect(() => {
    async function ensureClipsLoaded() {
      selectedClipIds.forEach(async (clipId) => {
        if (!clipsStore.clipById[clipId]) {
          const clip = await clipsStore.loadClipById(clipId);
          clipsStore.updateClips([clip]);
        }
      });
    }
    if (session.userId) {
      ensureClipsLoaded();
    }
  }, [session.userId, selectedClipIds, clipsStore]);

  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        onClose();
      }
    };
    window.addEventListener('keydown', handleEscape, true);
    return () => window.removeEventListener('keydown', handleEscape, true);
  }, [onClose]);

  const playlists = clipsStore.allPlaylists?.filter(
    (pl) => pl.id !== libraryStore.activePlaylist?.id && canUserEditPlaylist(pl)
  );

  const [randomFallbackImage, setRandomFallbackImage] = useState('');
  const [playlistName, setPlaylistName] = useState('');

  const handleLikedSongsClick = useCallback(() => {
    // Like the clip(s)
    selectedClipIds.forEach((clipId) => {
      clipsStore.likeClip(clipId, true, {
        requireClipById: false,
        contextType,
        recommendationItemId,
        hookId,
      });
    });
    // Pop the toast
    const singleClip =
      selectedClipIds.length === 1
        ? clipsStore.clipById[selectedClipIds[0]]
        : undefined;
    const clipString =
      selectedClipIds.length !== 1
        ? `${selectedClipIds.length} clips`
        : singleClip
          ? `"${getClipTitle(singleClip)}"`
          : `1 clip`;
    toast({
      title: `${clipString} added to Liked songs`,
      duration: 4000,
      isClosable: true,
      status: 'info',
    });
    onClose();
  }, [
    onClose,
    selectedClipIds,
    clipsStore,
    contextType,
    recommendationItemId,
    hookId,
  ]);

  const handlePlaylistClick = useCallback(
    (playlist: Playlist) => {
      // Add clip(s) to playlist
      playlistStore.addClipsToPlaylistById(selectedClipIds, playlist.id, {
        contextType,
        recommendationItemId,
        hookId,
      });
      // Pop the toast
      const singleClip =
        selectedClipIds.length === 1
          ? clipsStore.clipById[selectedClipIds[0]]
          : undefined;
      const clipString =
        selectedClipIds.length !== 1
          ? `${selectedClipIds.length} clips`
          : singleClip
            ? `"${getClipTitle(singleClip)}"`
            : `1 clip`;
      const playlistName = playlist?.name ? playlist.name : 'Untitled Playlist';
      toast({
        title: `${clipString} added to "${playlistName}"`,
        duration: 4000,
        isClosable: true,
        status: 'info',
      });
      onClose();
    },
    [
      onClose,
      selectedClipIds,
      clipsStore,
      playlistStore,
      contextType,
      recommendationItemId,
      hookId,
    ]
  );

  useEffect(() => {
    const fallbackImages = [
      FALLBACK_AURA_URL,
      staticAssetUrl('images/placeholder-2.jpg'),
      staticAssetUrl('images/placeholder-3.jpg'),
    ];
    const randomImage =
      fallbackImages[Math.floor(Math.random() * fallbackImages.length)];
    setRandomFallbackImage(randomImage);
  }, []);

  return (
    <Modal
      title='Add to Playlist'
      onClose={onClose}
      wrapperClasses='max-h-[480px] mb-4'
      withHorizontalPadding
    >
      <div className='mb-4 max-h-[400px] overflow-y-auto'>
        <div
          className='flex cursor-pointer items-center rounded-md p-2 hover:bg-background-fog-thin'
          onClick={handleLikedSongsClick}
        >
          <ImageWithFallback
            imageSize={SMALL_IMAGE}
            src={LIKED_SONGS_PLAYLIST_COVER_URL}
            className='w-[40px] rounded-sm'
            alt='Playlist cover image'
          />
          <div className='ml-4 font-sans'>Liked Songs</div>
        </div>
        {playlists.map((playlist: Playlist) => (
          <div
            key={playlist.id}
            className='flex cursor-pointer items-center rounded-md p-2 hover:bg-background-fog-thin'
            onClick={() => handlePlaylistClick(playlist)}
          >
            <ImageWithFallback
              imageSize={SMALL_IMAGE}
              src={
                playlist.image_url ||
                playlist.playlist_clips[0]?.clip?.image_url ||
                randomFallbackImage
              }
              className='w-[40px] rounded-sm'
              alt='Playlist cover image'
            />
            <div className='ml-4 font-sans'>
              {playlist.name || 'Untitled Playlist'}
            </div>
          </div>
        ))}
        {clipsStore.allPlaylists?.length < libraryStore.numTotalPlaylists && (
          <div className='flex justify-center p-4'>
            <SpinnerSVG ref={spinnerRef} />
          </div>
        )}
      </div>
      <div className='flex w-full gap-4 whitespace-nowrap'>
        <input
          className='w-full rounded-md border border-foreground-secondary/20 bg-transparent px-2 py-3 text-sm whitespace-nowrap focus-within:outline-white'
          placeholder='Playlist Name'
          value={playlistName}
          onChange={(e) => setPlaylistName(e.target.value)}
        />
        <Button
          variant={ButtonVariant.Secondary}
          onClick={async () => {
            setCreatePlaylistLoading(true);
            setPlaylistName('');
            await clipsStore.createPlaylist(
              playlistName && {
                name: playlistName,
              }
            );
            await libraryStore.loadPlaylists(undefined, showSharelist);
            setCreatePlaylistLoading(false);
          }}
          disabled={createPlaylistLoading}
          icon={createPlaylistLoading && <SpinnerSVG />}
        >
          Create Playlist
        </Button>
      </div>
    </Modal>
  );
});

export default AddToPlaylistModal;
