import { observer } from 'mobx-react-lite';
import { usePathname, useRouter } from 'next/navigation';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import ImpressionLogger, {
  ImpressionLoggerConfig,
} from '@/components/ImpressionLogger';
import BaseDiscoverSongCard, {
  Props as BaseDiscoverSongCardProps,
} from '@/components/card/DiscoverSongCard';
import usePlaySourceContext from '@/hooks/usePlaySource';
import { usePlaybarStatusForClip } from '@/hooks/usePlaybar';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip, ClipEntity } from '@/state/clipStore';
import { PlayContext } from '@/state/queueStore';
import { eventLogger } from '@/utils/event-logger';
import { ActionName } from '@/utils/event-names';

type Props = BaseDiscoverSongCardProps & {
  clip: ClipEntity;
  contextId?: PlayContext['contextId'];
  contextType?: PlayContext['contextType'];
  allItems?: Clip[];
  contestCard?: boolean;
};

const DiscoverSongCard: React.FC<Props> = observer((props) => {
  const {
    clip,
    index,
    contextType,
    contextId,
    allItems,
    contestCard,
    ...restProps
  } = props;

  const router = useRouter();
  const pathname = usePathname();

  const {
    clips: clipsStore,
    queue: queueStore,
    playbar: playbarStore,
    session,
  } = useStores();

  const playSource = usePlaySourceContext();
  const { isPlaying, isCurrentSong } = usePlaybarStatusForClip(clip.id, {
    contextId,
    contextType,
  });

  // Local copy of some clip fields for immediate updates
  const [clipState, setClipState] = useState({
    isPlaying,
    isCurrentSong,
    clip,
    clipFromStore: clipsStore.clipById[clip.id],
  });
  const clipStateRef = useRef(clipState);
  useEffect(() => {
    clipStateRef.current = clipState;
  }, [clipState]);
  useEffect(() => {
    setClipState((prevClipState) => ({
      ...prevClipState,
      isPlaying,
      isCurrentSong,
      clip,
      clipFromStore: clipsStore.clipById[clip.id],
    }));
  }, [clip, isPlaying, isCurrentSong, clipsStore]);

  const clips = useMemo(
    () =>
      (allItems ?? []).filter(
        (element) => !clipsStore.isNotInterested(element.id)
      ),
    [allItems, clipsStore]
  );

  const handlePlayPauseClick = useCallback(() => {
    const { isCurrentSong, isPlaying, clip } = clipStateRef.current;
    logWebUserEvent({
      actionName: 'DiscoverSongCardPlayClicked',
      principalObjectType: 'clip',
      principalObjectValue: clip.id,
      context: {
        title: clip.title || '',
        caption: clip.caption || '',
        artistDisplayName: clip.displayName || '',
        artistHandle: clip.handle || '',

        likeCount: clip.upvoteCount ?? undefined,
        commentCount: clip.commentCount ?? undefined,
        playCount: clip.playCount ?? undefined,

        playSourceType: playSource.playSourceType,
        playSourceId: playSource.playSourceId,
        index,
        actionType: isCurrentSong && isPlaying ? 'pause' : 'play',
      },
    });
    if (isCurrentSong && isPlaying) {
      playbarStore.togglePlay();
      return;
    } else {
      if (contextId && contextType) {
        queueStore.setPlayContext({
          contextType,
          contextId,
          clips,
          currentIndex: 0,
          surfaceType: playSource.playSourceType,
          surfaceId: playSource.playSourceId,
        });
      }
      playbarStore.playClip(clipsStore.clipById[clip.id]);
    }
  }, [
    contextId,
    contextType,
    clips,
    index,
    playSource,
    clipsStore,
    queueStore,
    playbarStore,
  ]);

  const handleLikeClick = useCallback(
    ({ isLiked }: { isLiked: boolean }) => {
      logWebUserEvent({
        actionName: 'DiscoverSongCardButtonClicked',
        principalObjectType: 'clip',
        principalObjectValue: clip.id,
        context: {
          buttonId: 'play_count',

          title: clip.title || '',
          caption: clip.caption || '',
          artistDisplayName: clip.displayName || '',
          artistHandle: clip.handle || '',

          likeCount: clip.upvoteCount ?? undefined,
          commentCount: clip.commentCount ?? undefined,
          playCount: clip.playCount ?? undefined,

          playSourceType: playSource.playSourceType,
          playSourceId: playSource.playSourceId,
          index,
        },
      });

      eventLogger.logAudioActionEvent(
        false,
        isLiked ? ActionName.likeSong : ActionName.undoLikeSong,
        clipsStore.clipById[clip.id],
        session,
        pathname
      );
    },
    [clip, index, playSource, clipsStore, pathname, session]
  );

  const handleCommentClick = useCallback(() => {
    logWebUserEvent({
      actionName: 'SongCardCommentClicked',
      principalObjectType: 'song',
      principalObjectValue: clip.id,
      context: {
        playSourceType: playSource.playSourceType,
        playSourceId: playSource.playSourceId,
      },
    });
    router.push(`/song/${clip.id}?show_comments=true`);
  }, [clip.id, router, playSource]);

  const impressionLoggerConfig = useMemo<ImpressionLoggerConfig[]>(() => {
    const baseEvent = {
      principalObjectType: 'clip' as const,
      principalObjectValue: clip.id,
      context: {
        title: clip.title || '',
        caption: clip.caption || '',
        artistDisplayName: clip.displayName || '',
        artistHandle: clip.handle || '',

        likeCount: clip.upvoteCount ?? undefined,
        commentCount: clip.commentCount ?? undefined,
        playCount: clip.playCount ?? undefined,

        playSourceType: playSource.playSourceType,
        playSourceId: playSource.playSourceId,
        index,
      },
    };
    return [
      {
        event: {
          ...baseEvent,
          actionName: 'DiscoverSongCardSeen',
        },
        threshold: 0.95,
      },
      {
        event: {
          ...baseEvent,
          actionName: 'DiscoverSongCardSeenPartially',
        },
        threshold: 0.25,
      },
    ];
  }, [clip, playSource, index]);

  return (
    <ImpressionLogger configs={impressionLoggerConfig}>
      <BaseDiscoverSongCard
        clipId={clip.id}
        clipImage={clip.imageUrl ?? undefined}
        clipVideo={clip.previewUrl ?? undefined}
        clipTitle={clip.title}
        // clipCaption={clip.caption}
        clipArtistAvatar={clip.avatarImageUrl ?? undefined}
        clipArtistDisplayName={clip.displayName ?? undefined}
        clipArtistHandle={clip.handle ?? undefined}
        playCount={clip.playCount ?? undefined}
        commentCount={clip.commentCount ?? undefined}
        likeCount={clip.upvoteCount ?? undefined}
        isPlaying={isPlaying}
        onPlayPauseClick={handlePlayPauseClick}
        onPlayCountClick={handlePlayPauseClick}
        onLikeClick={handleLikeClick}
        onCommentClick={handleCommentClick}
        index={index}
        contestCard={contestCard}
        {...restProps}
      />
    </ImpressionLogger>
  );
});

export default DiscoverSongCard;
