import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { useCallback, useMemo } from 'react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import { FeedListContextProps } from '@/components/feed/FeedItemList';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import { SongQueueSongData } from '@/components/song-queue/SongQueueSongData';
import { tagsToArray } from '@/components/song/songUtils';
import { StatefulPlayPauseIcon } from '@/icons';
import { components } from '@/lib/gen';
import { ContextType } from '@/logging/contextTypes';
import { getClipDisplayTags } from '@/utils/clip';
import { SMALL_IMAGE } from '@/utils/constants';

export const getPropsForSongQueueSongItem = ({
  item,
}: {
  item: components['schemas']['GeneratedClipSchema'];
}): SongQueueSongItemProps & { key: string } => {
  return {
    key: `${item.title}-${item.id}`,
    imgUrl: item.image_url ?? '',
    title: item.title ?? '',
    clipId: item.id ?? '',
    tags: tagsToArray(getClipDisplayTags(item)),
    displayName: item.display_name ?? '',
    handle: item.handle ?? '',
    avatarImageUrl: item.avatar_image_url ?? '',
    personaId: item.persona?.id ?? '',
    personaName: item.persona?.name ?? '',
    personaImageUrl: item.persona?.image_s3_id ?? '',
    playCount: item.play_count ?? 0,
    upvoteCount: item.upvote_count ?? 0,
    commentCount: item.comment_count ?? 0,
    artistId: item.user_id ?? '',
  };
};

export type SongQueueSongItemProps = React.HTMLAttributes<HTMLDivElement> & {
  imgUrl: string;
  title: string;
  clipId: string;
  tags: string[];
  displayName: string;
  handle: string;
  avatarImageUrl: string;
  playCount: number;
  upvoteCount: number;
  commentCount: number;
  personaId?: string;
  personaName?: string;
  personaImageUrl?: string;
  onPlayClick?: () => void;
  artistId: string;
  manualQueueIndex?: number;
  autoplayQueueIndex?: number;
  isNowPlayingSection?: boolean;
};

export type Props = Omit<
  React.HTMLAttributes<HTMLDivElement>,
  keyof FeedListContextProps | keyof SongQueueSongItemProps
> &
  SongQueueSongItemProps &
  FeedListContextProps;

const SongQueueSongItem: React.FC<Props> = observer((props) => {
  const {
    imgUrl,
    title,
    clipId,
    tags,
    displayName,
    handle,
    avatarImageUrl,
    personaId,
    personaName,
    personaImageUrl,
    playCount,
    upvoteCount,
    commentCount,
    listId,
    listTitle,
    listClips,
    className,
    artistId,
    manualQueueIndex,
    autoplayQueueIndex,
    isNowPlayingSection,
    ...restProps
  } = props;

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

  const { t } = useTranslation();
  const isNotInterested = clipStore.notInterestedById[clipId];

  const handlePlayClip = useCallback(() => {
    // If this is a manual queue song, use special handler
    if (manualQueueIndex !== undefined) {
      queueStore.playManualQueueSongByIndex(manualQueueIndex);
      playbarStore.playClip(clipStore.clipById[clipId]);
      return;
    }

    // If this is an autoplay queue song, use special handler
    if (autoplayQueueIndex !== undefined) {
      queueStore.playAutoplayQueueSongByIndex(autoplayQueueIndex);
      playbarStore.playClip(clipStore.clipById[clipId]);
      return;
    }

    // Otherwise, use existing logic for context queue songs
    const clipIndex = queueStore.findClipIndex(clipId);
    if (clipIndex >= 0) {
      playbarStore.playClip(clipStore.clipById[clipId]);
      queueStore.setPlayContext({
        clips: queueStore.contextClips,
        clipIndexOrder: queueStore.contextClipIndexOrder,
        contextId: queueStore.contextId || '',
        contextType: queueStore.contextType || ContextType.Playlist,
        currentIndex: clipIndex,
      });
    }
  }, [
    clipStore,
    playbarStore,
    queueStore,
    clipId,
    manualQueueIndex,
    autoplayQueueIndex,
  ]);

  const handlePlayClick = useCallback(() => {
    // If this is a manual or autoplay queue item, always jump to it
    if (manualQueueIndex !== undefined || autoplayQueueIndex !== undefined) {
      handlePlayClip();
      return;
    }

    // For non-queue items, toggle play/pause if same song is already playing
    if (playbarStore.clip?.id === clipId && !playbarStore.isClipPreloaded) {
      playbarStore.togglePlay();
      return;
    }
    handlePlayClip();
  }, [
    playbarStore,
    clipId,
    handlePlayClip,
    manualQueueIndex,
    autoplayQueueIndex,
  ]);

  const handleDoubleClick = useCallback(() => {
    // Always play from beginning
    handlePlayClip();
  }, [handlePlayClip]);

  const isCurrentSong = useMemo(() => {
    // Only show as current if this is the now playing section
    return isNowPlayingSection && playbarStore.clip?.id === clipId;
  }, [clipId, isNowPlayingSection, playbarStore.clip?.id]);
  const isPlaying = isCurrentSong && playbarStore.isPlaying;
  return (
    <div
      className={twMerge(
        clsx(
          'group flex w-full flex-row items-center justify-between rounded-lg p-2',
          'transition-colors duration-150',
          'focus-within:bg-background-secondary-glass'
        ),
        className
      )}
      onDoubleClick={handleDoubleClick}
      data-media-playing={isPlaying}
      aria-disabled={isNotInterested}
      inert={isNotInterested}
      {...restProps}
    >
      <div className='flex w-full flex-row gap-4'>
        <button
          className='group relative shrink-0'
          onClick={handlePlayClick}
          aria-label={isPlaying ? t('media.pause') : t('media.play')}
        >
          <ImageWithFallback
            className='lazyload h-16 w-12 rounded-lg object-cover'
            src={imgUrl}
            alt={title}
            imageSize={SMALL_IMAGE}
          />
          <div
            className={clsx(
              'absolute inset-0 flex items-center justify-center rounded-lg',
              'transition-colors duration-150',
              'group-hover:bg-opacity-black-30 group-hover:text-foreground-primary-glass',
              'group-focus-within:bg-opacity-black-30 group-focus-within:text-foreground-primary-glass',
              {
                'bg-transparent text-transparent': !(
                  isPlaying || isCurrentSong
                ),
                'bg-opacity-black-30 text-foreground-primary-glass':
                  isPlaying || isCurrentSong,
              }
            )}
          >
            <StatefulPlayPauseIcon className='h-6 w-6' />
          </div>
        </button>
        <div className='min-w-0'>
          <SongQueueSongData
            title={title}
            clipId={clipId}
            tags={tags}
            displayName={displayName}
            handle={handle}
            imageUrl={avatarImageUrl}
            personaId={personaId}
            personaName={personaName}
            personaImageUrl={personaImageUrl}
            playCount={playCount}
            commentCount={commentCount}
            onPlayClick={handlePlayClick}
            artistId={artistId}
          />
        </div>
      </div>
    </div>
  );
});

export default SongQueueSongItem;
