import { observer } from 'mobx-react-lite';
import { useCallback, useMemo, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import ImpressionLogger, {
  ImpressionLoggerConfig,
} from '@/components/ImpressionLogger';
import BaseDiscoverPlaylistCard, {
  Props as BaseDiscoverPlaylistCardProps,
} from '@/components/card/DiscoverPlaylistCard';
import usePlaySourceContext from '@/hooks/usePlaySource';
import { ContextType } from '@/logging/contextTypes';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { PlaylistEntity, PlaylistMetadataEntity } from '@/state/clipStore';

type Props = BaseDiscoverPlaylistCardProps & {
  playlist: PlaylistEntity | PlaylistMetadataEntity;
};

const DiscoverPlaylistCard: React.FC<Props> = observer((props) => {
  const { playlist, index, ...restProps } = props;

  const {
    clips: clipsStore,
    queue: queueStore,
    playbar: playbarStore,
    playlist: playlistStore,
  } = useStores();
  const playSource = usePlaySourceContext();

  const [isLoading, setIsLoading] = useState(false);

  const isCurrentContext = queueStore.isPlaylistCurrentContext(playlist.id);
  const isPlaying = isCurrentContext && playbarStore.isPlaying;

  const handlePlayPauseClick = useCallback(() => {
    async function loadAndPlayPlaylist() {
      // Make sure we have the playlist loaded
      if (!clipsStore.playlistById[playlist.id]) {
        setIsLoading(true);
        await clipsStore.loadPlaylist(playlist.id, 0, undefined, true);
      }
      setIsLoading(false);
      const currentPlaylist = clipsStore.playlistById[playlist.id];
      if (queueStore.isPlaylistCurrentContext(currentPlaylist.id)) {
        // If it's the current playlist, toggle play
        playbarStore.togglePlay();
        return;
      } else {
        queueStore.setPlayContext({
          contextType: ContextType.Playlist,
          contextId: playlist.id,
          clips: currentPlaylist.playlist_clips.map((pc: any) => pc.clip),
          currentIndex: 0,
          surfaceType: playSource.playSourceType,
          surfaceId: playSource.playSourceId,
        });
        playbarStore.playClip(currentPlaylist.playlist_clips[0].clip);
        playlistStore.incrementPlaylistPlayCount(
          playlist.id,
          currentPlaylist.playlist_clips[0].clip.id
        );
      }

      logWebUserEvent({
        actionName: 'DiscoverPlaylistCardPlayClicked',
        principalObjectType: 'playlist',
        principalObjectValue: playlist.id,
        context: {
          title: playlist.name || '',
          description: playlist.description || '',
          artistDisplayName: playlist.userDisplayName || '',
          artistHandle: playlist.userHandle || '',

          songCount: playlist.songCount ?? undefined,
          likeCount: playlist.upvoteCount ?? undefined,
          playCount: playlist.playCount ?? undefined,

          playSourceType: playSource.playSourceType,
          playSourceId: playSource.playSourceId,
          index,
        },
      });
    }
    loadAndPlayPlaylist();
  }, [
    playlist,
    index,
    playSource,
    clipsStore,
    queueStore,
    playbarStore,
    playlistStore,
  ]);

  const impressionLoggerConfig = useMemo<ImpressionLoggerConfig[]>(() => {
    const baseEvent = {
      principalObjectType: 'playlist' as const,
      principalObjectValue: playlist.id,
      context: {
        title: playlist.name || '',
        description: playlist.description || '',
        artistDisplayName: playlist.userDisplayName || '',
        artistHandle: playlist.userHandle || '',

        songCount: playlist.songCount ?? undefined,
        likeCount: playlist.upvoteCount ?? undefined,
        playCount: playlist.playCount ?? undefined,

        playSourceType: playSource.playSourceType,
        playSourceId: playSource.playSourceId,
        index,
      },
    };
    return [
      {
        event: {
          ...baseEvent,
          actionName: 'DiscoverPlaylistCardSeen',
        },
        threshold: 0.95,
      },
      {
        event: {
          ...baseEvent,
          actionName: 'DiscoverPlaylistCardSeenPartially',
        },
        threshold: 0.25,
      },
    ];
  }, [playlist, playSource, index]);

  // @TODO: Get from backend instead
  const hidePlaylistAuthor = playlist.userHandle === 'groovebot';

  return (
    <ImpressionLogger configs={impressionLoggerConfig}>
      <BaseDiscoverPlaylistCard
        playlistId={playlist.id}
        playlistImage={playlist.imageUrl ?? undefined}
        playlistTitle={playlist.name}
        playlistDescription={playlist.description}
        playlistAuthorAvatar={
          hidePlaylistAuthor
            ? undefined
            : (playlist.userAvatarImageUrl ?? undefined)
        }
        playlistAuthorDisplayName={
          hidePlaylistAuthor
            ? undefined
            : (playlist.userDisplayName ?? undefined)
        }
        playlistAuthorHandle={
          hidePlaylistAuthor ? undefined : (playlist.userHandle ?? undefined)
        }
        songCount={playlist.songCount ?? undefined}
        playCount={playlist.playCount ?? undefined}
        likeCount={playlist.upvoteCount ?? undefined}
        isPlaying={isPlaying || isLoading}
        onPlayPauseClick={handlePlayPauseClick}
        index={index}
        // onLikeClick={handleLikeClick} // @TODO: We don't actually have the correct liked state on playlists
        {...restProps}
      />
    </ImpressionLogger>
  );
});

export default DiscoverPlaylistCard;
