'use client';

import { useDynamicConfig, useGateValue } from '@statsig/react-bindings';
import clsx from 'clsx';
import { omit } from 'lodash-es';
import { observer } from 'mobx-react-lite';
import { usePathname } from 'next/navigation';
import React, { RefObject, useEffect, useMemo, useRef, useState } from 'react';
import { usePress } from 'react-aria';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { ClipContextProvider } from '@/components/clipBrowser/ClipContext';
import { MoreMenuContents } from '@/components/clipBrowser/ClipMenus';
import { RightClickMenuTrigger } from '@/components/contextMenu/ContextMenu';
import Avatar from '@/components/image/Avatar';
import { SkeletonBone, SkeletonText } from '@/components/layout/Skeleton';
import Link from '@/components/link/Link';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import SongActions from '@/components/song/SongActions';
import { ModelNameTagClip } from '@/components/tag/ModelNameTag';
import Tag from '@/components/tag/Tag';
import { Tooltip } from '@/components/tooltip/Tooltip';
import { useFetchClip } from '@/hooks/useClip';
import {
  CreditCardIcon,
  CrownIcon,
  EditIcon,
  FourStarIcon,
  ImageIcon,
  PauseIcon,
  PlayIcon,
  PulsingLinesIcon,
  TrashIcon,
  VideoIcon,
} from '@/icons';
import { ContextType } from '@/logging/contextTypes';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip, isTimedOut } from '@/state/clipStore';
import { FeatureKey } from '@/state/sessionStore';
import { getClipTitle } from '@/utils/clip';
import { isSubscriber } from '@/utils/session';
import {
  colorVar,
  isSecretStatsProfile,
  isVerifiedProfile,
} from '@/utils/utils';

import { SMALL_IMAGE, TOOLTIP_BACKGROUND } from '../../utils/constants';
import ImageWithFallback from '../image/ImageWithFallback';
import SpinnerSVG from '../svg/SpinnerSVG';
import MusicStyleTags from '../tag/MusicStyleTags';
import PersonaTag from '../tag/PersonaTag';
import VerifiedBadge from '../timbaland/VerifiedBadge';
import MobileSongActions from './MobileSongActions';
import {
  SunoShortType,
  TIME_AGO,
  formatDuration,
  getSunoShortType,
  isSunoShort,
  shouldShowPersona,
  tagsToArray,
  tagsToNegativeTags,
} from './songUtils';

type PreviewClipType = 'preview' | 'lockedPreview' | undefined;

export interface SongRowUIProps {
  stream?: boolean;
  showStats?: boolean;
  showTags?: boolean;
  showModelTagOnly?: boolean;
  trendingMode?: boolean;
  showActions?: boolean;
  showUser?: boolean;
  isFromSongRow?: boolean;
  isCreatePage?: boolean;
  isLoading?: boolean;
  rankingMode?: boolean;
  showDislike?: boolean;
}

export interface SongRowProps extends SongRowUIProps {
  clip: Clip;
  onClick: (e: any) => any;
  onPlay: () => any;
  onTriggerEditMode?: () => void;
  onPinClipToProject?: () => void;
  expanded?: boolean;
  selected?: boolean;
  focusedClip?: Clip;
  index?: number;
  playlistId?: string;
  contextId?: string;
  contextType?: string;
  condensed?: boolean;
  isContestClip?: boolean;
  rankingMode?: boolean;
  rowKey?: string;
  style?: object;
  mini?: boolean;
  enablePin?: boolean;
  showTopTrackIcon?: boolean;
  ref?: RefObject<any>;
  sectionName?: string;
  imageOnly?: boolean;
}

const SongRow = observer(
  ({
    clip,
    rowKey,
    onClick,
    onPlay,
    onTriggerEditMode,
    onPinClipToProject,
    trendingMode = false,
    expanded = false,
    index = undefined,
    playlistId = undefined,
    contextId = undefined,
    contextType = undefined,
    isFromSongRow = true,
    isCreatePage = false,
    isLoading = false,
    condensed = false,
    isContestClip = false,
    mini = false,
    enablePin = false,
    rankingMode = false,
    ref,
    sectionName,
    showTopTrackIcon = false,
    showDislike = false,
    showStats = false,
    showTags = true,
    showActions = true,
    showUser = false,
    showModelTagOnly: _showModelTagOnly = false,
    imageOnly = false,
  }: SongRowProps) => {
    const {
      playbar: playbarState,
      genForm,
      queue,
      session,
      menus,
      clips,
      project,
    } = useStores();

    const isPlaying = queue.currentPlayingSongIsRemoved
      ? false
      : playbarState.clip?.id === clip?.id &&
        queue.contextType === contextType &&
        queue.contextId === contextId;
    const showModelTagOnly =
      _showModelTagOnly || clip.user_id !== session.userId;

    // Show user information if we're in a shared project context
    const shouldShowUserInSharedProject =
      project.currentProject?.shared &&
      contextType === ContextType.Workspace &&
      contextId === project.userSelectedProjectId;

    const effectiveShowUser = showUser || shouldShowUserInSharedProject;

    const [showPlayIcon, setShowPlayIcon] = useState(false);

    const fetchClip = useFetchClip();

    useEffect(() => {
      // should only poll if the clip is preview and the user is a subscriber
      if (
        !clip.id ||
        clip.metadata.type !== 'preview' ||
        !isSubscriber(session)
      ) {
        return;
      }

      // Add this clip to the centralized polling queue
      clips.addToPreviewPollingQueue(clip.id);

      return () => {
        clips.removeFromPreviewPollingQueue(clip.id);
      };
    }, [clip.id, clip.metadata.type]);

    const previewUnlocking =
      clip.metadata.type === 'preview' && isSubscriber(session);

    const manualUnlock = clips.shouldShowManualUnlock(clip.id);

    const isProcessing =
      isLoading ||
      clip?.status === 'queued' ||
      clip?.status === 'submitted' ||
      clip?.status === 'processing' ||
      (previewUnlocking && !manualUnlock);

    const focusedClip = genForm.selectedClip;

    const isInHistory =
      focusedClip?.metadata?.history
        ?.map((h: any) => h?.id || h)
        .includes(clip.id) ||
      focusedClip?.metadata?.concat_history
        ?.map((h: any) => h?.id || h)
        .includes(clip.id) ||
      // catch ids appended with "m_" in the upload audio flow
      // TODO later we should refactor the backend so these get stored as clip IDs
      focusedClip?.metadata?.history
        ?.map((h: any) => h?.id || h)
        .includes(`m_${clip.id}`) ||
      focusedClip?.metadata?.concat_history
        ?.map((h: any) => h?.id || h)
        .includes(`m_${clip.id}`) ||
      // catch stemming
      focusedClip?.metadata?.stem_from_id === clip?.id;

    const tooltipTriggerRef = useRef<HTMLDivElement>(null);

    const timeAgo = new Date(clip.created_at);
    const pathname = usePathname();
    const [isHovered, setIsHovered] = useState(false);
    const [isUnlocking, setIsUnlocking] = useState(false);

    const handleMouseEnter = () => setIsHovered(true);
    const handleMouseLeave = () => setIsHovered(false);

    const [hasBeenPlayed, setHasBeenPlayed] = useState(false);

    const sunoShortType = getSunoShortType(clip);
    const previewClipType: PreviewClipType =
      clip.preview_seconds == null
        ? undefined
        : clip.preview_seconds === 0
          ? 'lockedPreview'
          : 'preview';

    useEffect(() => {
      if (
        playbarState.clip?.id === clip.id &&
        playbarState.isPlaying &&
        !hasBeenPlayed
      ) {
        if (!hasBeenPlayed) {
          setHasBeenPlayed(true);
        }
        playbarState.addToRecentlyPlayedIds(clip.id);
      }
    }, [clip.id, hasBeenPlayed, playbarState.clip?.id, playbarState.isPlaying]);

    const tags = [
      ...tagsToArray(clip.metadata?.tags || ''),
      ...tagsToNegativeTags(tagsToArray(clip.metadata?.negative_tags || '')),
    ];

    const visibleStats = !isSecretStatsProfile({
      handle: clip?.handle || '',
    });

    const imageDimensions = {
      width: mini ? '32px' : '56px',
      height: mini ? '42px' : '77px',
    };

    const { pressProps: containerPressProps } = usePress({
      onPress:
        onClick &&
        ((e) => {
          onClick(e as any);
        }),
    });
    const { pressProps: imagePressProps } = usePress({
      onPress:
        onPlay &&
        (() => {
          setHasBeenPlayed(true);
          onPlay();
        }),
    });
    // Prevent pointer down from bubbling up to the GridListItem
    const linkPressProps = useMemo(
      () => ({
        onPointerDownCapture: (e: React.PointerEvent) => {
          e.stopPropagation();
        },
      }),
      []
    );

    const unplayedSong =
      clip.play_count === 0 &&
      (clip.reaction?.play_count || 0) === 0 &&
      !isProcessing &&
      !hasBeenPlayed &&
      session.user?.id === clip.user_id &&
      !playbarState.recentlyPlayedIds.includes(clip.id) &&
      !mini &&
      !playlistId;

    const handleToggle = (e: React.MouseEvent) => {
      if (clip.preview_seconds == null) return;
      menus.setCurrentUpsellFeature(FeatureKey.UPGRADE_LATEST_MODEL);
      e.stopPropagation();
      e.preventDefault();
      logWebUserEvent({
        actionName: 'UpgradeClipPreviewClicked',
        principalObjectType: 'song',
        principalObjectValue: clip.id,
        context: {
          songId: clip.id,
          previewSeconds: clip.preview_seconds,
        },
      });
      menus.openModal(ModalTypes.UPSELL_MODAL);
    };

    const handleUnlockPreview = async (e: React.MouseEvent) => {
      const currentClip = clips.clipById[clip.id];
      if (currentClip?.metadata.type === 'gen' || isUnlocking) return;

      e.stopPropagation();
      e.preventDefault();

      try {
        setIsUnlocking(true);
        await clips.unlockPreview(clip.id);
        await fetchClip(clip.id, false, true, undefined, true);
        clips.addToPreviewPollingQueue(clip.id);
      } catch (error) {
        console.error('Failed to unlock preview:', error);
      } finally {
        setIsUnlocking(false);
      }
    };

    const enableManualUnlock = useGateValue('manual-unlock');
    const { value: verifiedProfiles } = useDynamicConfig('verified-profiles');
    const handles = (verifiedProfiles?.handles as string[]) || [];

    return isTimedOut(clip) || clips.isNotInterested(clip.id) ? null : (
      <ClipContextProvider clip={clip}>
        <RightClickMenuTrigger ContentsComponent={MoreMenuContents}>
          <div
            ref={ref}
            tabIndex={0}
            role='button'
            className={clsx(
              'flex cursor-pointer py-1 select-none group-data-[selected]:bg-background-tertiary',
              'flex-col items-start md:flex-row lg:items-center',
              'hover:bg-white/[0.03]',
              {
                'pr-1': mini || imageOnly,
                'pr-3 md:pr-6': !mini && !imageOnly,
                'ml-0': mini || imageOnly,
                'ml-3 md:ml-6': !mini && !imageOnly,
                'pl-1': mini || condensed || imageOnly,
                'pl-5 md:pl-3 lg:pl-1': !mini && !condensed && !imageOnly,
              }
            )}
            style={{
              background: isPlaying
                ? colorVar('white', 0.08)
                : isInHistory
                  ? colorVar('white', 0.03)
                  : undefined,
            }}
            onMouseEnter={() => {
              if (previewClipType !== 'lockedPreview') setShowPlayIcon(true);
            }}
            onMouseLeave={() => setShowPlayIcon(false)}
            {...containerPressProps}
            onDoubleClick={() => {
              if (previewClipType === 'lockedPreview') return;
              setHasBeenPlayed(true);
              onPlay();
            }}
            onPointerDown={(e) => {
              if (clip.metadata.type === 'preview') {
                e.stopPropagation();
                e.preventDefault();
                return;
              }
              if (previewClipType === 'lockedPreview') {
                e.stopPropagation();
                e.preventDefault();
                handleToggle(e);
                return;
              }
              const isMac = navigator.userAgent.includes('Mac');
              const isRightClick =
                e.button === 2 || (isMac && e.button === 0 && e.ctrlKey);
              // We want to override the default mult-select behavior in the
              // case of a right-click, so we can use it to open the pop-up menu
              if (isRightClick) {
                e.stopPropagation();
              }
            }}
            onContextMenu={() => {
              requestAnimationFrame(() => {
                if (
                  (rowKey || clip?.id) &&
                  ![...(menus.selected || [])].includes(rowKey || clip?.id)
                ) {
                  menus.setSelected(new Set([rowKey || clip?.id]));
                  if (clip) {
                    menus.setCurrentClip(clip);
                  }
                }
              });
            }}
            data-clip-id={clip?.id}
            data-testid='song-row'
          >
            <div className='relative flex w-full items-center'>
              {unplayedSong && previewClipType !== 'lockedPreview' && (
                <div className='absolute -left-3 z-[9999] h-2 w-2 rounded-full bg-accent-pink md:-left-4'></div>
              )}
              <div
                className={clsx('flex flex-1 flex-row items-center gap-3', {
                  'opacity-60': isProcessing,
                })}
              >
                {index !== undefined && rankingMode && (
                  <div className='mr-[14px] flex flex-col items-center'>
                    {index >= 3 ? (
                      <span className='w-[50px] text-center font-mono text-lg font-bold text-white/80'>
                        {index + 1}
                      </span>
                    ) : (
                      <CrownIcon
                        className={clsx('h-[30px] w-[50px]', {
                          'text-[#ffd700]': index === 0,
                          'text-[#c0c0c0]': index === 1,
                          'text-[#cd7f32]': index === 2,
                        })}
                        aria-label={`${index === 0 ? 'Gold' : index === 1 ? 'Silver' : 'Bronze'} crown`}
                      />
                    )}
                  </div>
                )}
                <div
                  className={clsx('relative flex shrink-0', {
                    'justify-center': imageOnly,
                    'justify-start': !imageOnly,
                  })}
                  {...imagePressProps}
                  aria-label='Play Song'
                  style={{
                    width: imageOnly ? '100%' : imageDimensions.width,
                    height: imageDimensions.height,
                    minWidth: imageDimensions.width,
                    minHeight: imageDimensions.height,
                  }}
                  data-testid='song-row-play-button'
                >
                  {clip?.image_url ? (
                    <div className='relative'>
                      {!mini && previewClipType !== 'lockedPreview' && (
                        <span className='absolute right-[2px] bottom-[2px] flex items-center rounded-sm bg-background-primary-dark/70 px-[2px] font-mono text-[11px] font-bold text-foreground-primary-on-dark'>
                          {sunoShortType &&
                            (sunoShortType == SunoShortType.VIDEO ? (
                              <VideoIcon className='mr-1 h-3 w-3' />
                            ) : (
                              <ImageIcon className='mr-1 h-3 w-3' />
                            ))}
                          {formatDuration(
                            clip.metadata?.duration,
                            isSunoShort(clip)
                          )}
                        </span>
                      )}
                      <ImageWithFallback
                        alt='Song Image'
                        className={clsx(
                          `shrink-0 rounded-sm object-cover text-foreground-primary`,
                          {
                            'border border-foreground-primary':
                              isPlaying && mini,
                            'border-2 border-foreground-primary':
                              isPlaying && !mini,
                            'blur-sm': previewClipType === 'lockedPreview',
                          }
                        )}
                        style={{
                          height: imageDimensions.height,
                          width: imageDimensions.width,
                        }}
                        src={clip?.image_url}
                      />
                    </div>
                  ) : (
                    <SkeletonBone
                      style={{
                        width: imageDimensions.width,
                        height: imageDimensions.height,
                      }}
                    />
                  )}

                  {isProcessing ? (
                    <div
                      className='absolute inset-0 flex items-center justify-center'
                      style={{
                        width: imageDimensions.width,
                        height: imageDimensions.height,
                      }}
                      data-testid='loading-clip'
                    >
                      <SpinnerSVG className='h-8 w-8' />
                    </div>
                  ) : (
                    <div
                      aria-label={playbarState.isPlaying ? 'Pause' : 'Play'}
                      onMouseEnter={handleMouseEnter}
                      onMouseLeave={handleMouseLeave}
                      className={clsx(
                        'absolute inset-0 flex items-center justify-center text-white transition-colors duration-200',
                        {
                          'opacity-100': isPlaying || showPlayIcon,
                          'opacity-0': !(isPlaying || showPlayIcon),
                        }
                      )}
                    >
                      {!isPlaying || !playbarState.isPlaying ? (
                        <PlayIcon className={mini ? 'h-4 w-4' : 'h-6 w-6'} />
                      ) : isHovered ? (
                        <PauseIcon className={mini ? 'h-4 w-4' : 'h-6 w-6'} />
                      ) : (
                        <PulsingLinesIcon
                          className={mini ? 'h-4 w-4' : 'h-6 w-6'}
                        />
                      )}
                    </div>
                  )}
                </div>

                <div
                  className={clsx('flex-1', {
                    hidden: imageOnly,
                    flex: !imageOnly,
                    'flex-row': mini,
                    'flex-col @3xl/rows:flex-row': !mini && isCreatePage,
                    'flex-col xl:flex-row': !mini && !isCreatePage,
                  })}
                >
                  <div
                    className={clsx(
                      'flex flex-1 flex-col justify-start pb-1 md:justify-center',
                      {
                        'ml-2': mini,
                        'ml-5': !mini,
                      }
                    )}
                  >
                    {clip?.status === 'submitted' ? (
                      <div className='py-1'>
                        <SkeletonText className='block' />
                        <SkeletonText className='block' />
                      </div>
                    ) : (
                      <>
                        <div className='flex w-full items-center gap-2'>
                          <span
                            className='line-clamp-1 font-sans text-base font-medium break-all text-foreground-primary'
                            title={getClipTitle(clip)}
                          >
                            {previewClipType !== 'lockedPreview' &&
                            (clip.status === 'streaming' ||
                              clip.status === 'complete') ? (
                              <Link
                                {...linkPressProps}
                                href={`/song/${clip?.id}/`}
                                onClick={() => {
                                  logWebUserEvent({
                                    actionName: 'SongRowTitleClicked',
                                    principalObjectType: 'song',
                                    principalObjectValue: clip.id,
                                    context: {
                                      index,
                                      playCount: clip.play_count || 0,
                                      likeCount: clip.upvote_count || 0,
                                      commentCount: clip.comment_count || 0,
                                      sectionId:
                                        pathname === '/create'
                                          ? 'create'
                                          : pathname === '/me'
                                            ? 'library'
                                            : pathname === '/me/history'
                                              ? 'history'
                                              : pathname.includes('playlist')
                                                ? 'playlist'
                                                : 'unknown',
                                      sectionTitle:
                                        pathname === '/create'
                                          ? 'Create'
                                          : pathname === '/me'
                                            ? 'Library'
                                            : pathname === '/me/history'
                                              ? 'History'
                                              : pathname.includes('playlist')
                                                ? 'Playlist'
                                                : 'Unknown',
                                      artistId: clip.user_id || '',
                                    },
                                  });
                                }}
                              >
                                <span className='cursor-pointer hover:underline'>
                                  {getClipTitle(clip)}
                                </span>
                              </Link>
                            ) : (
                              getClipTitle(clip)
                            )}
                          </span>

                          {pathname === '/feed' && (
                            <span className='font-sans text-xs text-foreground-inactive'>
                              {'· ' + TIME_AGO.format(timeAgo, 'mini') + ' ago'}
                            </span>
                          )}
                          {showTopTrackIcon ? (
                            <Tag>
                              <FourStarIcon className='text-accent-yellow-on-primary' />
                              <span className='whitespace-nowrap'>
                                Top Song
                              </span>
                            </Tag>
                          ) : null}
                          {(showTags || showModelTagOnly) &&
                          clip?.model_name ? (
                            <div className='flex flex-row gap-2'>
                              <ModelNameTagClip
                                clip={clip}
                                showSecondaryBadges={!showModelTagOnly}
                              />
                              {showModelTagOnly ? null : (
                                <>
                                  {clip.is_trashed ? (
                                    <Tag>
                                      <TrashIcon />
                                    </Tag>
                                  ) : null}
                                  {clip.metadata?.refund_credits ? (
                                    <>
                                      <Tooltip
                                        label='Generation was too short, so no credits were used. If generations are silent and you continued a clip, that clip probably ended in silence. You may want to try continuing from a different clip.'
                                        placement='auto-start'
                                        background={TOOLTIP_BACKGROUND}
                                        backdropFilter='blur(40px)'
                                        rounded='md'
                                        color='#ffffff'
                                        padding='10px'
                                      >
                                        <Tag ref={tooltipTriggerRef}>
                                          Credits Refunded
                                        </Tag>
                                      </Tooltip>
                                    </>
                                  ) : null}
                                  {[
                                    'edit_crop',
                                    'edit_fade',
                                    'edit_speed',
                                  ].includes(clip.metadata?.type || '') &&
                                  session.flags?.['edit-mode-ui'] ? (
                                    <Tag>
                                      <EditIcon />
                                      <span className='whitespace-nowrap'>
                                        {clip.metadata?.type === 'edit_crop'
                                          ? 'Crop'
                                          : clip.metadata?.type === 'edit_fade'
                                            ? 'Fade'
                                            : 'Speed'}
                                      </span>
                                    </Tag>
                                  ) : null}
                                  {clip.ownership?.ownership_reason ===
                                  'bought' ? (
                                    <Tag>
                                      <CreditCardIcon />
                                      <span className='whitespace-nowrap'>
                                        Purchased
                                      </span>
                                    </Tag>
                                  ) : null}
                                </>
                              )}
                            </div>
                          ) : null}
                        </div>
                        <div className='flex'>
                          {effectiveShowUser && (
                            <div className='flex items-center font-sans text-sm font-medium text-foreground-primary'>
                              <div className='relative mr-2'>
                                <Avatar
                                  className='h-4 w-4'
                                  src={clip.avatar_image_url || null}
                                  imageSize={SMALL_IMAGE}
                                  alt='User avatar'
                                />
                                {isVerifiedProfile(
                                  {
                                    handle: clip.handle || '',
                                  },
                                  handles
                                ) && (
                                  <VerifiedBadge className='absolute end-0 bottom-0 h-2 w-2 drop-shadow-avatar-overlay' />
                                )}
                              </div>
                              <div className='line-clamp-1 max-w-full flex-1 break-all hover:underline'>
                                <Link
                                  {...linkPressProps}
                                  href={`/@${clip.handle}`}
                                >
                                  {clip.display_name || 'Untitled User'}
                                </Link>
                              </div>
                            </div>
                          )}
                          {!mini &&
                            shouldShowPersona(
                              clip.persona,
                              session.user?.handle
                            ) && (
                              <div
                                className={`flex items-center ${effectiveShowUser ? 'ml-2' : ''}`}
                              >
                                <PersonaTag
                                  persona={clip.persona}
                                  showAvatar={true}
                                  showUser={false}
                                  size={'small'}
                                />
                              </div>
                            )}
                        </div>
                        {!tags.length && !visibleStats ? null : (
                          <div className='flex flex-row'>
                            <MusicStyleTags
                              className='line-clamp-1 flex-nowrap pr-2 text-xs text-foreground-primary'
                              tags={tags}
                              title={clip.metadata.tags || ''}
                              renderTag={(props) => (
                                <span {...omit(props, 'className', 'href')} />
                              )}
                            />
                          </div>
                        )}
                      </>
                    )}
                  </div>
                  {showActions && !previewClipType && (
                    <>
                      <div
                        className={clsx('flex px-0 md:hidden', {
                          'ml-2': mini,
                          'ml-5': !mini,
                        })}
                      >
                        <MobileSongActions
                          trendingMode={trendingMode}
                          showStats={showStats}
                          clip={clip}
                          onPinClipToProject={onPinClipToProject}
                          enablePin={enablePin}
                          mini={mini}
                        />
                      </div>
                      <div className='hidden px-0 md:flex'>
                        <SongActions
                          rowKey={rowKey}
                          trendingMode={trendingMode}
                          showStats={showStats}
                          clip={clip}
                          isFromSongRow={isFromSongRow}
                          onTriggerEditMode={onTriggerEditMode}
                          isContestClip={isContestClip}
                          className={
                            isFromSongRow && !mini ? 'ml-4' : undefined
                          }
                          onPinClipToProject={onPinClipToProject}
                          enablePin={enablePin}
                          mini={mini}
                          onPlayCountClick={onClick}
                          showDislike={showDislike}
                          sectionName={sectionName}
                        />
                      </div>
                    </>
                  )}
                </div>
                {/* preview unlocking handles new clip preview method, previewClipType is for old hacky preview method */}
                {previewUnlocking ? (
                  manualUnlock && enableManualUnlock ? (
                    <Button
                      onClick={handleUnlockPreview}
                      variant={ButtonVariant.Primary}
                      size={ButtonSize.Small}
                      shape={ButtonShape.Rounded}
                      className='text-xs lg:text-sm'
                      disabled={isUnlocking}
                    >
                      {isUnlocking ? 'Unlocking...' : 'Unlock song'}
                    </Button>
                  ) : (
                    <span className='animate-pulse text-xs text-foreground-primary lg:text-sm'>
                      Unlocking song...
                    </span>
                  )
                ) : previewClipType ? (
                  <Button
                    onClick={handleToggle}
                    variant={ButtonVariant.Primary}
                    size={ButtonSize.Small}
                    shape={ButtonShape.Rounded}
                    className='text-xs lg:text-sm'
                  >
                    Upgrade for full song
                  </Button>
                ) : null}
              </div>
            </div>
            {expanded && genForm.showLyrics ? (
              <div className='flex text-xs whitespace-pre-wrap lg:hidden'>
                {clip.metadata?.prompt}
              </div>
            ) : null}
          </div>
        </RightClickMenuTrigger>
      </ClipContextProvider>
    );
  }
);

export default SongRow;
