import { css } from '@emotion/react';
import styled from '@emotion/styled';
import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { usePathname } from 'next/navigation';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { FocusedObjectContext } from '@/app/(root)/create/v2/useFocusedObject';
import { SkeletonBone } from '@/components/layout/Skeleton';
import Tag, { TagVariant } from '@/components/tag/Tag';
import { ThemeMode, useThemeContext } from '@/context/ThemeContext';
import { useContextSelector } from '@/hooks/useContextSelector';
import useDeviceAttributes from '@/hooks/useDeviceAttributes';
import usePublishClip from '@/hooks/usePublishClip';
import {
  CheckIcon,
  CheckboxIcon,
  CheckboxOutlineIcon,
  CloseIcon,
  CommentIcon,
  CreditCardIcon,
  EditIcon,
  EditUndoIcon,
  GlobeIcon,
  InProjectTagIcon,
  MoreHorizontalIcon,
  PauseIcon,
  PinIcon,
  PlayIcon,
  ShareArrowIcon,
  StemsIcon,
  ThumbsDownIcon,
  ThumbsUpIcon,
  TrashIcon,
  UploadIcon,
} from '@/icons';
import { withWebUserEvent } from '@/logging/logWebUserEvent';
import { isDisliked, isLiked, isUpload } from '@/state/clipStore';
import { getClipDisplayTags, getClipTitle } from '@/utils/clip';
import {
  DEFAULT_PROJECT_ID,
  MAX_TITLE_CHARS,
  SMALL_IMAGE,
} from '@/utils/constants';
import { encodeTimeFormat } from '@/utils/utils';

import Button, { ButtonShape, ButtonVariant } from '../button/Button';
import CountButton from '../button/CountButton';
import { ResponsiveChild, useContainer } from '../containerQueries/components';
import { ContextMenuTrigger } from '../contextMenu/ContextMenu';
import ImageWithFallback from '../image/ImageWithFallback';
import Link from '../link/Link';
import { tagsToArray, tagsToNegativeTags } from '../song/songUtils';
import StudioContext from '../studio/StudioContext';
import { getAllUsedClipIds, getStudioClipsByClipId } from '../studio/selectors';
import SpinnerSVG from '../svg/SpinnerSVG';
import { TAG_ICON_MAP, TagIconKey } from '../tag/ModelNameTag';
import PersonaTag from '../tag/PersonaTag';
import { Tooltip } from '../tooltip/Tooltip';
import { useClipContext, useNullableClipContext } from './ClipContext';
import { MoreMenuContents } from './ClipMenus';
import MultiSelectContext from './MultiSelectContext';
import PlayingAnimation from './PlayingAnimation';
import { useIsOwnClip } from './clipHelpers';
import { BooleanFilter } from './types';
import { ClipBrowserContext } from './useClipBrowser';
import useClipChanges from './useClipChanges';
import { useClipPlaybackContext } from './useClipPlayback';
import useDeletePermanently from './useDeletePermanently';
import useHasBeenPlayed from './useHasBeenPlayed';
import useShareClip from './useShareClip';
import useTrashActions from './useTrashActions';

export const HoverOnlyCSS = css`
  .hover-only {
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .not-hover-only {
    opacity: 1;
    transition: opacity 0.15s ease;
  }

  .hover-fade-in {
    opacity: 0.35;
    transition: opacity 0.15s ease;
  }

  &:hover {
    background-color: rgba(255, 255, 255, 0.03);
    .hover-only {
      opacity: 1;
    }
    .not-hover-only {
      opacity: 0;
    }
    .hover-fade-in {
      opacity: 1;
    }
    .full-width-when-not-hovered {
      width: auto;
      position: relative;
    }

    .edit-icon-wrapper {
      width: 20px;
      opacity: 1;
    }
  }

  /* Mobile-specific overrides - ensure buttons are visible on mobile */
  @media (max-width: 768px) {
    .hover-only {
      opacity: 1 !important;
    }
    .hover-fade-in {
      opacity: 1 !important;
    }

    .edit-icon-wrapper {
      width: 20px !important;
      opacity: 1 !important;
    }

    /* Hide multi-select checkbox on mobile */
    .multi-select-button button {
      display: none !important;
    }
  }
`;

const KeepHoveringCSS = `
  .hover-only {
    opacity: 1;
  }
  .not-hover-only {
    opacity: 0;
  }
  .hover-fade-in {
    opacity: 1;
  }
  
  .edit-icon-wrapper {
    width: 20px;
    opacity: 1;
  }
`;

export const ClipRowHeight = 110 as const;
export const ClipRowHeightShort = 64 as const;
export const ClipRowHeightMicro = 52 as const;

export const ClipRowWrapper = styled.div<{
  keepHovering?: boolean;
  height?:
    | typeof ClipRowHeight
    | typeof ClipRowHeightShort
    | typeof ClipRowHeightMicro;
}>`
  color: var(--color-foreground-primary);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px;
  container-type: size;
  container-name: clip-row;

  .remix-menu-trigger {
    @container clip-row (width < 700px) {
      display: none;
    }
  }

  height: ${({ height }) => `${height ?? ClipRowHeight}px`};

  animation: fadeIn 0.15s ease;

  border-radius: 20px;

  background-color: rgba(255, 255, 255, 0);

  ${HoverOnlyCSS}

  ${({ keepHovering }) =>
    keepHovering &&
    `
      background-color: var(--color-background-fog-thin);
      ${KeepHoveringCSS}
    `}

  transition: background-color 0.15s ease;

  @media (max-width: 768px) {
    padding: 0 4px 0 4px;
  }
`;

export const MicroClipRowWrapper = styled(
  (props: Parameters<typeof ClipRowWrapper>[0]) => (
    <ClipRowWrapper {...props} height={ClipRowHeightMicro} />
  )
)`
  border-radius: 8px;
  padding: 4px 8px;
`;

export const ImageContainer = styled.div<{ small?: boolean }>`
  width: ${({ small }) => (small ? '40px' : '67px')};
  height: ${({ small }) => (small ? '50px' : '86px')};
  border-radius: ${({ small }) => (small ? '8px' : '12px')};
  overflow: hidden;
  position: relative;
  flex-shrink: 0;
  color: var(--color-foreground-primary-on-dark);
`;

export const ImagePlayButtonWrapper = styled.div`
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.5);
  .playing-pause {
    opacity: 0;
  }
  .playing-animation {
    opacity: 1;
  }
  &:hover {
    .playing-pause {
      opacity: 1;
    }
    .playing-animation {
      opacity: 0;
    }
  }
`;

export const ImageDurationWrapper = styled.div`
  position: absolute;
  bottom: 4px;
  right: 4px;
  z-index: 3;
  border-radius: 12px;
  padding: 0 6px;
  font-size: 10px;
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Input Sans', sans-serif;
  background-color: rgba(0, 0, 0, 0.15);
  backdrop-filter: blur(40px);
  letter-spacing: -0.6px;
  text-shadow: 0 2px 5px rgba(0, 0, 0, 0.35);
  pointer-events: none;
`;

export const ClipRowGroup = styled.div<{ tight?: boolean }>`
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: ${({ tight }) => (tight ? '8px' : '16px')};
  min-width: 0;
`;

export const PlayedStatusDot = styled.div<{ hasBeenPlayed: boolean }>`
  width: 8px;
  height: 8px;
  border-radius: 1000px;
  background-color: ${(props) =>
    props.hasBeenPlayed ? 'transparent' : 'var(--color-accent-brand)'};
`;

export const ClipRowDotWrapper = styled.div`
  position: relative;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  margin-right: -12px;
  > * {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
  flex-shrink: 0;
`;

export const ClipDetailsWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
`;

export const ClipMetadataRow = styled.div`
  display: flex;
  flex-direction: row;
  gap: 2px;
  min-width: 0;
  flex-wrap: nowrap;
  margin-bottom: 2px;
`;

export const MetadataBadge = styled.span<{
  backgroundColor?: string;
  textColor?: string;
  borderColor?: string;
}>`
  background-color: ${({ backgroundColor }) =>
    backgroundColor ? `#${backgroundColor}` : 'rgba(255, 255, 255, 0.1)'};
  padding: ${({ borderColor }) =>
    borderColor ? '0px 3px 0px 3px' : '1px 4px 1px 4px'};
  font-size: 11px;
  color: ${({ textColor }) =>
    textColor ? `#${textColor}` : 'var(--color-foreground-primary)'};
  border-radius: 4px;
  border: ${({ borderColor }) =>
    borderColor ? `1px solid #${borderColor}` : 'none'};
  white-space: nowrap;
  height: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 18px;
`;

export const StudioMetadataBadge = styled(MetadataBadge)`
  background-color: transparent;
  border: none;
`;

export const ProjectBadge = styled.span<{ backgroundColor?: string }>`
  background-color: ${({ backgroundColor }) =>
    backgroundColor || 'rgb(220, 79, 46)'};
  width: 18px;
  height: 18px;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: top;
`;

export const ClipTitleWrapper = styled.div<{ isPlaying?: boolean }>`
  font-size: 14px;
  line-height: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color 0.5s linear;
  color: var(--color-foreground-primary);
  min-width: 0;
  flex-shrink: 1;
  ${({ isPlaying }) =>
    isPlaying &&
    `
      color: var(--color-accent-brand);
    `}
`;

export const ClipDescriptionWrapper = styled.div`
  font-size: 12px;
  line-height: 14px;
  color: var(--color-foreground-inactive);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 4px;
`;

export const EditButton = styled.button`
  display: flex;
  align-items: center;
  justify-content: center;
  width: 0;
  height: 24px;
  border-radius: 4px;
  border: none;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  opacity: 0;
  background-color: transparent;
  color: var(--color-foreground-primary);
  transition:
    width 0.15s ease,
    opacity 0.15s ease,
    background-color 0.15s ease;
  > * {
    opacity: 0.5;
  }
  &:hover {
    > * {
      opacity: 1;
    }
  }
`;

export const TitleEditWrapper = styled.div<{ editable?: boolean }>`
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: 6px;
  padding: 0;
  transition: background-color 0.15s ease;
  min-width: 0;
  flex-shrink: 1;

  ${({ editable }) =>
    editable &&
    `
      &:hover {
        background-color: var(--color-background-fog-thin);

        .edit-icon-wrapper {
          width: 20px;
          opacity: 1;
        }
      }
    `}
`;

export const TitleInput = styled.input`
  font-size: 14px;
  line-height: 16px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--color-foreground-primary);
  border-radius: 0;
  padding: 4px 0 3px 0;
  color: var(--color-foreground-primary);
  outline: none;
  min-width: 50px;

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

export const HiddenTextMeasure = styled.span`
  position: absolute;
  visibility: hidden;
  white-space: pre;
  font-size: 14px;
  line-height: 16px;
  padding: 2px 0;
  pointer-events: none;
`;

export const EditActionButton = styled.button`
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  transition: background-color 0.15s ease;
  background-color: var(--color-background-glass-thin);
  color: var(--color-foreground-primary);

  &:hover:not(:disabled) {
    background-color: var(--color-background-glass-thick);
  }

  &:active:not(:disabled) {
    background-color: var(--color-background-smoke-thick);
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

export const ClipInteractionsWrapper = styled.div`
  margin-top: 4px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
`;

export const PublishButtonHider = styled.div<{ hide: boolean }>`
  opacity: ${({ hide }) => (hide ? 0 : 1)};
  transform: ${({ hide }) => (hide ? 'translateX(-10px)' : 'translateX(0)')};
  pointer-events: ${({ hide }) => (hide ? 'none' : 'auto')};
  transition:
    opacity 0.15s ease,
    transform 0.15s ease;

  .hovered-text {
    display: none;
  }
  .default-text {
    display: inline;
  }

  &:hover {
    .hovered-text {
      display: inline;
    }
    .default-text {
      display: none;
    }
  }
`;

export const AutoSkeletonBone = ({ width }: { width: string | number }) => (
  <span className='relative inline-block'>
    &nbsp;
    <SkeletonBone
      style={{ width }}
      className='absolute top-0 left-0 h-3 rounded-md'
    />
  </span>
);

export const ClipDotAndCheckbox = observer(function ClipDotAndCheckbox() {
  const clip = useNullableClipContext();
  const [hasBeenPlayed] = useHasBeenPlayed(clip);
  const isSelected = useContextSelector(MultiSelectContext, (ctx) =>
    ctx.selectedClipIds.includes(clip?.id || '')
  );
  const toggleClip = useContextSelector(
    MultiSelectContext,
    (ctx) => ctx.toggleClip
  );

  return (
    <ClipRowDotWrapper className='multi-select-button'>
      <PlayedStatusDot
        className='not-hover-only h-4 w-4'
        hasBeenPlayed={hasBeenPlayed}
      />
      <Button
        className={isSelected ? '' : 'hover-only'}
        variant={ButtonVariant.Tertiary}
        icon={
          isSelected ? (
            <CheckboxIcon className='h-3 w-3' />
          ) : (
            <CheckboxOutlineIcon className='h-3 w-3 opacity-15' />
          )
        }
        onClick={() => {
          if (clip) {
            toggleClip(clip.id);
          }
        }}
      />
    </ClipRowDotWrapper>
  );
});

const ImagePlaceholder = styled.div<{
  gradientColor1: string;
  gradientColor2: string;
}>`
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;

  &::before {
    content: '';
    position: absolute;
    inset: -50%;
    height: 200%;
    width: 200%;
    animation: gradient-shift 4s ease infinite;
    background: linear-gradient(
      45deg,
      ${({ gradientColor1 }) => gradientColor1},
      ${({ gradientColor2 }) => gradientColor2},
      ${({ gradientColor1 }) => gradientColor1},
      ${({ gradientColor2 }) => gradientColor2}
    );
    background-size: 400% 400%;
  }

  @keyframes gradient-shift {
    0% {
      background-position: 0% 50%;
    }
    50% {
      background-position: 100% 50%;
    }
    100% {
      background-position: 0% 50%;
    }
  }
`;

const gradientSets = [
  ['var(--color-amethyst-600)', 'var(--color-slime-600)'], // Purple → Green
  ['var(--color-slime-600)', 'var(--color-dandelion-600)'], // Green → Yellow
  ['var(--color-strawberry-600)', 'var(--color-dandelion-600)'], // Pink → Yellow
  ['var(--color-amethyst-600)', 'var(--color-dandelion-600)'], // Purple → Yellow
  ['var(--color-dodger-blue-600)', 'var(--color-dandelion-600)'], // Blue → Yellow
];

export const ClipImage = observer(({ small }: { small?: boolean }) => {
  const clip = useNullableClipContext();
  const { onPlayClick, isPlaying, willPlay } = useClipPlaybackContext();
  const iconSizeClasses = small ? 'w-4 h-4' : 'w-6 h-6';
  const validForInteraction = ['complete', 'streaming'].includes(
    clip?.status ?? ''
  );

  // Use clip ID to deterministically pick a gradient (so it doesn't change on re-render)
  const [gradientColors] = useState(() => {
    const index = clip?.id
      ? parseInt(clip.id.slice(0, 8), 16) % gradientSets.length
      : Math.floor(Math.random() * gradientSets.length);
    return gradientSets[index];
  });

  return (
    <ImageContainer
      onClick={onPlayClick}
      small={small}
      className={`clip-image-container ${validForInteraction ? 'cursor-pointer' : 'pointer-events-none'}`}
    >
      {clip?.audio_url && clip?.image_url ? (
        <ImageWithFallback
          imageSize={SMALL_IMAGE}
          className='h-full w-full object-cover'
          src={clip.image_url}
          alt={`${clip ? getClipTitle(clip) : 'Default clip'} artwork`}
        />
      ) : (
        <ImagePlaceholder
          gradientColor1={gradientColors[0]}
          gradientColor2={gradientColors[1]}
        />
      )}
      {clip?.audio_url ? (
        <>
          <ImagePlayButtonWrapper className={isPlaying ? '' : 'hover-only'}>
            {isPlaying ? (
              <>
                <div className='playing-pause absolute top-[50%] left-[50%] -translate-x-1/2 -translate-y-1/2'>
                  <PauseIcon className={iconSizeClasses} />
                </div>
                <div className='playing-animation absolute top-[50%] left-[50%] -translate-x-1/2 -translate-y-1/2'>
                  <PlayingAnimation />
                </div>
              </>
            ) : willPlay ? (
              <SpinnerSVG className={iconSizeClasses} />
            ) : (
              <PlayIcon className={iconSizeClasses} />
            )}
          </ImagePlayButtonWrapper>
          {!small && (
            <ImageDurationWrapper>
              {clip?.metadata?.duration ? (
                encodeTimeFormat(clip?.metadata?.duration, 0, false)
              ) : (
                <SpinnerSVG className='h-3 w-3' />
              )}
            </ImageDurationWrapper>
          )}
        </>
      ) : null}
    </ImageContainer>
  );
});

export const StudioClipInteractions = observer(
  ({
    setIsMoreMenuOpen,
    containerName,
  }: {
    setIsMoreMenuOpen: (isOpen: boolean) => void;
    containerName: string;
  }) => {
    const clip = useClipContext();
    const { setClipLiked, setClipDisliked } = useClipChanges();

    return (
      <ClipInteractionsWrapper>
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsUpIcon className='h-4 w-4' />}
          className={`clip-interaction-button ${
            clip && isLiked(clip)
              ? 'animate-[small-bounce_0.25s_ease-in-out]'
              : ''
          }`}
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionLikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                likeStatus: clip ? !isLiked(clip) : false,
              },
            },
            () => clip && setClipLiked(clip.id, !isLiked(clip))
          )}
          variant={
            clip && isLiked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
        />
        <ResponsiveChild hideBelowWidth={400} containerName={containerName}>
          <Button
            disabled={!clip?.audio_url}
            shape={ButtonShape.Pill}
            icon={<ThumbsDownIcon className='h-4 w-4' />}
            className='clip-interaction-button'
            onClick={withWebUserEvent(
              {
                actionName: 'SongActionDislikeClicked',
                principalObjectValue: clip?.id || '',
                principalObjectType: 'song',
                context: {
                  dislikeStatus: clip ? !isDisliked(clip) : false,
                },
              },
              () => clip && setClipDisliked(clip.id, !isDisliked(clip))
            )}
            variant={
              clip && isDisliked(clip)
                ? ButtonVariant.Primary
                : ButtonVariant.Standard
            }
          />
          <ContextMenuTrigger
            onOpenChange={setIsMoreMenuOpen}
            ButtonComponent={(props) => (
              <Button
                className='p-2'
                shape={ButtonShape.Pill}
                icon={<MoreHorizontalIcon className='h-4 w-4' />}
                {...props}
              />
            )}
            ContentsComponent={MoreMenuContents}
          />
        </ResponsiveChild>
      </ClipInteractionsWrapper>
    );
  }
);

export const WorkspaceClipInteractions = observer(
  ({
    isPinned,
    likeOnboardingRef,
    shareOnboardingRef,
  }: {
    isPinned?: boolean;
    likeOnboardingRef?: React.RefObject<HTMLDivElement | null>;
    shareOnboardingRef?: React.RefObject<HTMLDivElement | null>;
  }) => {
    const clip = useNullableClipContext();
    const { setClipLiked, setClipDisliked } = useClipChanges();
    const { isPlaying } = useClipPlaybackContext();
    const { isMobile } = useDeviceAttributes();
    const isOwnClip = useIsOwnClip(clip);
    const isMultiSelected = useContextSelector(MultiSelectContext, (ctx) =>
      ctx.selectedClipIds.includes(clip?.id || '')
    );
    const { togglePublishClicked, isPublished } = usePublishClip(clip);
    const canPinToWorkspace = useContextSelector(
      ClipBrowserContext,
      (context) =>
        context.filters.workspace.presence === BooleanFilter.True &&
        context.filters.workspace.workspaceId !== null &&
        context.filters.workspace.workspaceId !== DEFAULT_PROJECT_ID
    );
    const unpinWorkspaceClip = useContextSelector(
      ClipBrowserContext,
      (context) => context.unpinWorkspaceClip
    );
    const pinWorkspaceClip = useContextSelector(
      ClipBrowserContext,
      (context) => context.pinWorkspaceClip
    );
    const emphasize =
      clip && (isLiked(clip) || isPlaying || isMultiSelected || isPublished);

    const showPublishButton = clip && (isLiked(clip) || isPublished);

    const shareClip = useShareClip();

    const shouldShowPersona = useMemo(() => {
      return !!clip?.persona;
    }, [clip?.persona]);

    return (
      <ClipInteractionsWrapper className={!emphasize ? 'hover-fade-in' : ''}>
        {shouldShowPersona && (
          <Button shape={ButtonShape.Pill} className='px-3 py-1'>
            <PersonaTag
              persona={clip?.persona}
              showAvatar={true}
              showUser={false}
              size={'small'}
            />
          </Button>
        )}
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsUpIcon className='h-4 w-4' />}
          className={`clip-interaction-button ${
            clip && isLiked(clip)
              ? 'animate-[small-bounce_0.25s_ease-in-out]'
              : ''
          }`}
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionLikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                likeStatus: clip ? !isLiked(clip) : false,
              },
            },
            () => clip && setClipLiked(clip.id, !isLiked(clip))
          )}
          variant={
            clip && isLiked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          ref={likeOnboardingRef}
          aria-label='Like clip'
        />
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsDownIcon className='h-4 w-4' />}
          className='clip-interaction-button'
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionDislikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                dislikeStatus: clip ? !isDisliked(clip) : false,
              },
            },
            () => clip && setClipDisliked(clip.id, !isDisliked(clip))
          )}
          variant={
            clip && isDisliked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          aria-label='Dislike clip'
        />
        {canPinToWorkspace && (
          <Button
            disabled={!clip?.audio_url}
            shape={ButtonShape.Pill}
            icon={<PinIcon className='h-4 w-4' />}
            variant={isPinned ? ButtonVariant.Primary : ButtonVariant.Standard}
            className='clip-interaction-button'
            onClick={async () => {
              if (!clip) {
                return;
              }
              if (isPinned) {
                unpinWorkspaceClip(clip);
              } else {
                pinWorkspaceClip(clip);
              }
            }}
            aria-label={
              isPinned ? 'Unpin clip from workspace' : 'Pin clip to workspace'
            }
          />
        )}
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ShareArrowIcon className='h-4 w-4' />}
          className='clip-interaction-button'
          onClick={() => clip && shareClip(clip)}
          ref={shareOnboardingRef}
          aria-label='Share clip'
        />
        <PublishButtonHider
          hide={isMobile || !isOwnClip || (!showPublishButton && !isPublished)}
        >
          <Button
            variant={
              isPublished ? ButtonVariant.Primary : ButtonVariant.Standard
            }
            shape={ButtonShape.Pill}
            className='text-xs'
            onClick={togglePublishClicked}
            icon={isPublished ? <GlobeIcon className='-mr-1 h-4 w-4' /> : null}
            aria-label={isPublished ? 'Unpublish clip' : 'Publish clip'}
          >
            {isPublished ? (
              <>
                <span className='default-text'>Published</span>
                <span className='hovered-text'>Unpublish</span>
              </>
            ) : (
              'Publish'
            )}
          </Button>
        </PublishButtonHider>
      </ClipInteractionsWrapper>
    );
  }
);

export const LibraryClipInteractions = observer(() => {
  const clip = useNullableClipContext();
  const { setClipLiked, setClipDisliked } = useClipChanges();
  const { onPlayClick, isPlaying, willPlay } = useClipPlaybackContext();
  const { isMobile } = useDeviceAttributes();
  const isOwnClip = useIsOwnClip(clip);
  const emphasize = clip && (isLiked(clip) || isPlaying);
  const { togglePublishClicked, isPublished } = usePublishClip(clip);
  const setFocusedObject = useContextSelector(
    FocusedObjectContext,
    (ctx) => ctx.setFocusedObject
  );

  const shareClip = useShareClip();

  const shouldShowPersona = useMemo(() => {
    return !!clip?.persona;
  }, [clip?.persona]);

  const { containerName, containerRef } = useContainer();
  return (
    <div ref={containerRef} className='h-10'>
      <ClipInteractionsWrapper className={!emphasize ? 'hover-fade-in' : ''}>
        {shouldShowPersona && (
          <Button shape={ButtonShape.Pill} className='px-3 py-1'>
            <PersonaTag
              persona={clip?.persona}
              showAvatar={true}
              showUser={false}
              size={'small'}
            />
          </Button>
        )}
        <CountButton
          disabled={!clip}
          shape={ButtonShape.Pill}
          variant={
            isPlaying || willPlay
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          className='clip-interaction-button p-2 text-xs'
          onMouseDown={() => {
            onPlayClick();
            if (clip) setFocusedObject({ type: 'clip', clipId: clip.id });
          }}
          count={clip?.play_count || 0}
          itemId={clip?.id || 'loading'}
          neverShowZeroCount
          icon={
            isPlaying || willPlay ? (
              <PauseIcon className='h-4 w-4' />
            ) : (
              <PlayIcon className='h-4 w-4' />
            )
          }
        />

        <CountButton
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsUpIcon className='h-4 w-4' />}
          className={`clip-interaction-button ${
            clip && isLiked(clip)
              ? 'animate-[small-bounce_0.25s_ease-in-out]'
              : ''
          } p-2 text-xs`}
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionLikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                likeStatus: clip ? !isLiked(clip) : false,
              },
            },
            () => clip && setClipLiked(clip.id, !isLiked(clip))
          )}
          variant={
            clip && isLiked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          aria-label='Like clip'
          count={clip?.upvote_count || 0}
          itemId={clip?.id || 'loading'}
          neverShowZeroCount
        />
        <ResponsiveChild
          hideBelowWidth={shouldShowPersona ? 300 : undefined}
          containerName={containerName}
        >
          <div className='contents'>
            <CountButton
              disabled={!clip?.audio_url}
              shape={ButtonShape.Pill}
              icon={<ThumbsDownIcon className='h-4 w-4' />}
              className='clip-interaction-button p-2 text-xs'
              onClick={withWebUserEvent(
                {
                  actionName: 'SongActionDislikeClicked',
                  principalObjectValue: clip?.id || '',
                  principalObjectType: 'song',
                  context: {
                    dislikeStatus: clip ? !isDisliked(clip) : false,
                  },
                },
                () => clip && setClipDisliked(clip.id, !isDisliked(clip))
              )}
              aria-label='Dislike clip'
              variant={
                clip && isDisliked(clip)
                  ? ButtonVariant.Primary
                  : ButtonVariant.Standard
              }
              count={0}
              itemId={clip?.id || 'loading'}
              neverShowZeroCount
            />

            <CountButton
              disabled={!clip?.allow_comments}
              shape={ButtonShape.Pill}
              className='clip-interaction-button p-2 text-xs'
              onClick={() =>
                clip &&
                window.open(`/song/${clip.id}?show_comments=true`, '_blank')
              }
              icon={<CommentIcon className='h-4 w-4' />}
              count={clip?.comment_count || 0}
              itemId={clip?.id || 'loading'}
              neverShowZeroCount
              aria-label='Comment on clip'
            />
          </div>
        </ResponsiveChild>

        <CountButton
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ShareArrowIcon className='h-4 w-4' />}
          className='clip-interaction-button p-2 text-xs'
          onClick={() => clip && shareClip(clip)}
          count={0}
          itemId={clip?.id || 'loading'}
          neverShowZeroCount
          aria-label='Share clip'
        />
        <PublishButtonHider
          hide={isMobile || !isOwnClip || (!emphasize && !isPublished)}
        >
          <Button
            variant={
              isPublished ? ButtonVariant.Primary : ButtonVariant.Standard
            }
            shape={ButtonShape.Pill}
            className='text-xs'
            onClick={togglePublishClicked}
            icon={isPublished ? <GlobeIcon className='-mr-1 h-4 w-4' /> : null}
            aria-label={isPublished ? 'Unpublish clip' : 'Publish clip'}
          >
            {isPublished ? (
              <>
                <span className='default-text'>Published</span>
                <span className='hovered-text'>Unpublish</span>
              </>
            ) : (
              'Publish'
            )}
          </Button>
        </PublishButtonHider>
      </ClipInteractionsWrapper>
    </div>
  );
});

export const TrashedClipInteractions = observer(() => {
  const clip = useNullableClipContext();
  const selectedClipIds = useContextSelector(
    MultiSelectContext,
    (ctx) => ctx.selectedClipIds
  );
  const { restoreFromTrash } = useTrashActions();
  const { deletePermanently } = useDeletePermanently();

  return (
    <ClipInteractionsWrapper>
      <Button
        disabled={!clip?.audio_url}
        variant={ButtonVariant.Standard}
        shape={ButtonShape.Pill}
        onClick={withWebUserEvent(
          {
            actionName: 'TrashedClipRestoreClicked',
            principalObjectValue: clip?.id || '',
            principalObjectType: 'song',
            context: {
              selectedCount:
                selectedClipIds.length > 0 ? selectedClipIds.length : 1,
            },
          },
          async () => {
            if (!clip) return;
            const clipIds =
              selectedClipIds.length > 0 ? selectedClipIds : [clip.id];
            await restoreFromTrash(clipIds);
          }
        )}
        icon={<EditUndoIcon className='h-4 w-4' />}
        aria-label='Restore to library'
        className='clip-interaction-button'
      />
      <Button
        disabled={!clip?.audio_url}
        variant={ButtonVariant.Standard}
        shape={ButtonShape.Pill}
        onClick={withWebUserEvent(
          {
            actionName: 'TrashedClipDeletePermanentlyClicked',
            principalObjectValue: clip?.id || '',
            principalObjectType: 'song',
            context: {
              selectedCount:
                selectedClipIds.length > 0 ? selectedClipIds.length : 1,
            },
          },
          () => {
            if (!clip) return;
            const clipIds =
              selectedClipIds.length > 0 ? selectedClipIds : [clip.id];
            deletePermanently(clipIds);
          }
        )}
        icon={<TrashIcon className='h-4 w-4' />}
        aria-label='Delete permanently'
        className='clip-interaction-button'
      />
    </ClipInteractionsWrapper>
  );
});

export const OrpheusClipInteractions = observer(
  ({
    likeOnboardingRef,
    shareOnboardingRef,
    showShareLabel = false,
  }: {
    likeOnboardingRef?: React.RefObject<HTMLDivElement | null>;
    shareOnboardingRef?: React.RefObject<HTMLDivElement | null>;
    showShareLabel?: boolean;
  }) => {
    const clip = useNullableClipContext();
    const { setClipLiked, setClipDisliked } = useClipChanges();
    const { isPlaying } = useClipPlaybackContext();
    const { isMobile } = useDeviceAttributes();
    const isOwnClip = useIsOwnClip(clip);
    const { togglePublishClicked, isPublished } = usePublishClip(clip);
    const emphasize = clip && (isLiked(clip) || isPlaying || isPublished);

    const showPublishButton = clip && (isLiked(clip) || isPublished);

    const shareClip = useShareClip();

    const shouldShowPersona = useMemo(() => {
      return !!clip?.persona;
    }, [clip?.persona]);

    return (
      <ClipInteractionsWrapper
        className={clsx('max-h-8', { 'hover-fade-in': !emphasize })}
      >
        {shouldShowPersona && (
          <Button shape={ButtonShape.Pill} className='px-3 py-1'>
            <PersonaTag
              persona={clip?.persona}
              showAvatar={true}
              showUser={false}
              size={'small'}
            />
          </Button>
        )}
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsUpIcon className='h-4 w-4' />}
          className={`clip-interaction-button ${
            clip && isLiked(clip)
              ? 'animate-[small-bounce_0.25s_ease-in-out]'
              : ''
          }`}
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionLikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                likeStatus: clip ? !isLiked(clip) : false,
              },
            },
            () => clip && setClipLiked(clip.id, !isLiked(clip))
          )}
          variant={
            clip && isLiked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          ref={likeOnboardingRef}
          aria-label='Like clip'
        />
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ThumbsDownIcon className='h-4 w-4' />}
          className='clip-interaction-button'
          onClick={withWebUserEvent(
            {
              actionName: 'SongActionDislikeClicked',
              principalObjectValue: clip?.id || '',
              principalObjectType: 'song',
              context: {
                dislikeStatus: clip ? !isDisliked(clip) : false,
              },
            },
            () => clip && setClipDisliked(clip.id, !isDisliked(clip))
          )}
          variant={
            clip && isDisliked(clip)
              ? ButtonVariant.Primary
              : ButtonVariant.Standard
          }
          aria-label='Dislike clip'
        />
        <Button
          disabled={!clip?.audio_url}
          shape={ButtonShape.Pill}
          icon={<ShareArrowIcon className='h-4 w-4' />}
          className='clip-interaction-button'
          onClick={() => clip && shareClip(clip)}
          ref={shareOnboardingRef}
          aria-label='Share clip'
        >
          {showShareLabel ? <span className='p-0 text-xs'>Share</span> : null}
        </Button>
        <PublishButtonHider
          hide={isMobile || !isOwnClip || (!showPublishButton && !isPublished)}
        >
          <Button
            variant={
              isPublished ? ButtonVariant.Primary : ButtonVariant.Standard
            }
            shape={ButtonShape.Pill}
            className='text-xs'
            onClick={togglePublishClicked}
            icon={isPublished ? <GlobeIcon className='-mr-1 h-4 w-4' /> : null}
            aria-label={isPublished ? 'Unpublish clip' : 'Publish clip'}
          >
            {isPublished ? (
              <>
                <span className='default-text'>Published</span>
                <span className='hovered-text'>Unpublish</span>
              </>
            ) : (
              'Publish'
            )}
          </Button>
        </PublishButtonHider>
      </ClipInteractionsWrapper>
    );
  }
);

export const ClipTitle = observer(function ClipTitle({
  className = '',
  link = true,
  tags = true,
  truncateTags = false,
  editableIfOwned = true,
  suffix,
  showNewIndicator: showNewIndicatorProp = false,
}: {
  className?: string;
  link?: boolean;
  tags?: boolean;
  truncateTags?: boolean;
  editableIfOwned?: boolean;
  suffix?: string;
  showNewIndicator?: boolean;
}) {
  const clip = useNullableClipContext();
  const { isPlaying, willPlay } = useClipPlaybackContext();
  const pathname = usePathname();
  const { clips, session } = useStores();
  const isOwnClip = clip && clip.user_id === session.user?.id;
  const editable = Boolean(editableIfOwned && isOwnClip);
  const [hasBeenPlayed] = useHasBeenPlayed(clip);
  const showNewIndicator =
    showNewIndicatorProp && Boolean(clip && !hasBeenPlayed);

  const [isEditing, setIsEditing] = useState(false);
  const [editedTitle, setEditedTitle] = useState('');
  const [isSaving, setIsSaving] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const measureRef = useRef<HTMLSpanElement>(null);

  const updateInputWidth = useCallback(() => {
    if (measureRef.current && inputRef.current) {
      const width = measureRef.current.offsetWidth;
      inputRef.current.style.width = `${Math.max(width + 2, 50)}px`;
    }
  }, []);

  // Auto-focus and select text when entering edit mode
  useEffect(() => {
    if (isEditing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
      // Initial width measurement
      updateInputWidth();
    }
  }, [isEditing, updateInputWidth]);

  const handleCancel = useCallback((e?: React.MouseEvent) => {
    e?.stopPropagation();
    setIsEditing(false);
    setEditedTitle('');
    setIsSaving(false);
  }, []);

  const handleEditClick = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation();
      if (clip) {
        setEditedTitle(getClipTitle(clip));
        setIsEditing(true);
      }
    },
    [clip]
  );

  const handleSave = useCallback(
    async (e?: React.MouseEvent) => {
      e?.stopPropagation();
      if (!clip || !editedTitle.trim() || isSaving) {
        handleCancel();
        return;
      }

      const trimmedTitle = editedTitle.trim();

      // Don't save if title hasn't changed
      if (clip.title === trimmedTitle) {
        setIsEditing(false);
        return;
      }

      setIsSaving(true);

      try {
        const result = await clips.setMetadata({
          clipId: clip.id,
          title: trimmedTitle,
        });

        if (result?.success) {
          // Update the clip object directly (MobX will handle reactivity)
          clip.title = trimmedTitle;
          setIsEditing(false);
          setIsSaving(false);
        } else {
          // Revert on failure
          setEditedTitle(getClipTitle(clip));
          setIsEditing(false);
          setIsSaving(false);
        }
      } catch (error) {
        console.error('Failed to update title:', error);
        // Revert on error
        setEditedTitle(getClipTitle(clip));
        setIsEditing(false);
        setIsSaving(false);
      }
    },
    [clip, editedTitle, isSaving, clips, handleCancel]
  );

  const handleInputChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setEditedTitle(e.target.value);
      // Update width immediately via DOM
      requestAnimationFrame(updateInputWidth);
    },
    [updateInputWidth]
  );

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        e.stopPropagation();
        handleSave();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        handleCancel();
      }
    },
    [handleSave, handleCancel]
  );

  return (
    <div className={clsx('flex items-center gap-2', className)}>
      {showNewIndicator ? (
        <PlayedStatusDot hasBeenPlayed={false} aria-hidden='true' />
      ) : null}
      {isEditing && (
        <HiddenTextMeasure ref={measureRef}>{editedTitle}</HiddenTextMeasure>
      )}
      {isEditing ? (
        <div className='flex items-center gap-[1px]'>
          <TitleInput
            ref={inputRef}
            value={editedTitle}
            onChange={handleInputChange}
            onKeyDown={handleKeyDown}
            onClick={(e) => e.stopPropagation()}
            onMouseDown={(e) => e.stopPropagation()}
            maxLength={MAX_TITLE_CHARS}
            disabled={isSaving}
          />
          <EditActionButton
            type='button'
            onClick={handleSave}
            onMouseDown={(e) => e.stopPropagation()}
            aria-label='Save title'
            disabled={isSaving}
          >
            {isSaving ? (
              <SpinnerSVG className='h-3 w-3' />
            ) : (
              <CheckIcon className='h-3 w-3' />
            )}
          </EditActionButton>
          <EditActionButton
            type='button'
            onClick={handleCancel}
            onMouseDown={(e) => e.stopPropagation()}
            aria-label='Cancel editing'
            disabled={isSaving}
          >
            <CloseIcon className='h-3 w-3' />
          </EditActionButton>
        </div>
      ) : (
        <TitleEditWrapper editable={editable}>
          <ClipTitleWrapper
            isPlaying={isPlaying || willPlay}
            style={!clip ? { width: 140 } : undefined}
          >
            {clip ? (
              link ? (
                <Tooltip label='Open song page'>
                  <Link
                    target={pathname === '/studio' ? '_blank' : undefined}
                    href={`/song/${clip.id}`}
                    className='hover:underline'
                    onClick={(e) => e.stopPropagation()}
                  >
                    {getClipTitle(clip)}
                    {suffix && (
                      <>
                        {' '}
                        <span className='text-accent'>{suffix}</span>
                      </>
                    )}
                  </Link>
                </Tooltip>
              ) : (
                getClipTitle(clip)
              )
            ) : (
              <AutoSkeletonBone width={140} />
            )}
          </ClipTitleWrapper>
          {editable && (
            <Tooltip label='Edit title'>
              <EditButton
                type='button'
                className='edit-icon-wrapper'
                onClick={handleEditClick}
                onMouseDown={(e) => e.stopPropagation()}
                aria-label='Edit title'
              >
                <EditIcon className='h-4 w-4' />
              </EditButton>
            </Tooltip>
          )}
        </TitleEditWrapper>
      )}
      {tags && (
        <>
          <ClipModelVersion truncateTags={truncateTags} />
          <ClipSecondaryBadges truncateTags={truncateTags} />
          <ClipPurchaseTag truncateTags={truncateTags} />
        </>
      )}
    </div>
  );
});

export const ClipDisplayTags = ({ className }: { className?: string }) => {
  const clip = useNullableClipContext();
  return (
    <ClipDescriptionWrapper className={className}>
      {clip ? (
        getClipDisplayTags(clip) || <i>(no styles)</i>
      ) : (
        <AutoSkeletonBone width={160} />
      )}
    </ClipDescriptionWrapper>
  );
};

export const ClipExactTags = ({ className }: { className?: string }) => {
  const clip = useNullableClipContext();
  const formattedTags = useMemo(() => {
    if (!clip) return null;
    return [
      ...tagsToArray(clip.metadata?.tags || ''),
      ...tagsToNegativeTags(tagsToArray(clip.metadata?.negative_tags || '')),
    ].join(', ');
  }, [clip]);
  if (!formattedTags) return <ClipDisplayTags className={className} />;
  return (
    <ClipDescriptionWrapper className={className}>
      {clip ? (
        formattedTags || <i>(no styles)</i>
      ) : (
        <AutoSkeletonBone width={160} />
      )}
    </ClipDescriptionWrapper>
  );
};

export const ClipInProject = () => {
  const clip = useNullableClipContext();
  const isInProject = useContextSelector(StudioContext, (ctx) =>
    clip && ctx?.state ? getAllUsedClipIds(ctx.state).includes(clip.id) : false
  );

  const trackColor = useContextSelector(StudioContext, (ctx) =>
    clip && ctx?.state
      ? (getStudioClipsByClipId(ctx.state)[clip.id]?.[0]?.color ?? 'orange')
      : 'orange'
  );

  if (!clip || !isInProject) return null;

  return (
    <ProjectBadge backgroundColor={trackColor}>
      <InProjectTagIcon className='h-4 w-4' />
    </ProjectBadge>
  );
};

export const ClipHasStem = () => {
  const clip = useNullableClipContext();

  if (!clip?.metadata?.has_stem) return null;

  return (
    <MetadataBadge>
      <StemsIcon className='inline h-3 w-3' />
      Stems
    </MetadataBadge>
  );
};

export const ClipBPM = () => {
  const clip = useNullableClipContext();

  if (!clip?.metadata?.avg_bpm && clip?.metadata?.avg_bpm !== 0) return null;
  if (typeof clip.metadata.avg_bpm !== 'number' || isNaN(clip.metadata.avg_bpm))
    return null;

  return <MetadataBadge>{Math.round(clip.metadata.avg_bpm)} BPM</MetadataBadge>;
};

export const ClipPurchaseTag = ({
  truncateTags,
}: {
  truncateTags?: boolean;
}) => {
  const clip = useNullableClipContext();

  if (clip?.ownership?.ownership_reason !== 'bought') return null;

  return (
    <MetadataBadge>
      <CreditCardIcon className='inline h-3 w-3' />
      {!truncateTags && 'Purchased'}
    </MetadataBadge>
  );
};

export const ClipMadeWithStudio = () => {
  const clip = useNullableClipContext();
  if (clip?.metadata?.type !== 'studio_export') return null;

  return (
    <StudioMetadataBadge>
      <Tag variant={TagVariant.Studio}>Made with Studio</Tag>
    </StudioMetadataBadge>
  );
};

export const ClipSecondaryBadges = ({
  truncateTags,
}: {
  truncateTags?: boolean;
}) => {
  const clip = useNullableClipContext();
  const { effectiveTheme } = useThemeContext();

  if (!clip) return null;

  return (
    <>
      {clip.metadata?.secondary_badges?.map((badge: any, index: number) => {
        const Icon = badge.icon_key
          ? TAG_ICON_MAP[badge.icon_key as TagIconKey]
          : undefined;

        return (
          <MetadataBadge
            key={`${badge.display_name}-${index}`}
            backgroundColor={
              effectiveTheme === ThemeMode.Dark
                ? badge.dark?.background_color || undefined
                : badge.light?.background_color || undefined
            }
            textColor={
              effectiveTheme === ThemeMode.Dark
                ? badge.dark?.text_color || undefined
                : badge.light?.text_color || undefined
            }
            borderColor={
              effectiveTheme === ThemeMode.Dark
                ? badge.dark?.border_color || undefined
                : badge.light?.border_color || undefined
            }
          >
            {Icon && <Icon className='mr-0.5 inline h-3 w-3' />}
            {!(Icon && truncateTags) && badge.display_name}
          </MetadataBadge>
        );
      })}
    </>
  );
};

export const ClipModelVersion = ({
  truncateTags,
}: {
  truncateTags?: boolean;
}) => {
  const clip = useNullableClipContext();
  const { effectiveTheme } = useThemeContext();

  if (!clip) return null;

  if (clip.metadata.type === 'studio_export') {
    return (
      <StudioMetadataBadge>
        <Tag variant={TagVariant.Studio}>Made with Studio</Tag>
      </StudioMetadataBadge>
    );
  }

  let displayName = clip.metadata?.model_badges?.songrow?.display_name;

  return displayName ? (
    <MetadataBadge
      backgroundColor={
        effectiveTheme === ThemeMode.Dark
          ? clip.metadata?.model_badges?.songrow?.dark?.background_color ||
            undefined
          : clip.metadata?.model_badges?.songrow?.light?.background_color ||
            undefined
      }
      textColor={
        effectiveTheme === ThemeMode.Dark
          ? clip.metadata?.model_badges?.songrow?.dark?.text_color || undefined
          : clip.metadata?.model_badges?.songrow?.light?.text_color || undefined
      }
      borderColor={
        effectiveTheme === ThemeMode.Dark
          ? clip.metadata?.model_badges?.songrow?.dark?.border_color ||
            undefined
          : clip.metadata?.model_badges?.songrow?.light?.border_color ||
            undefined
      }
    >
      {isUpload(clip) && <UploadIcon className='inline h-3 w-3' />}
      {!(isUpload(clip) && truncateTags) && displayName}
    </MetadataBadge>
  ) : null;
};

export const ClipKey = () => {
  const clip = useNullableClipContext();

  if (!clip?.metadata?.key) return null;

  return (
    <MetadataBadge>{clip.metadata.key.replaceAll('_', ' ')}</MetadataBadge>
  );
};
