'use client';

/* eslint jsx-a11y/click-events-have-key-events: warn */

/* eslint jsx-a11y/no-static-element-interactions: warn */
import clsx from 'clsx';
import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';

import AvatarTag from '@/components//tag/AvatarTag';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { ClipLikeButton } from '@/components/button/ClipLikeButton';
import Link from '@/components/link/Link';
import VideoLoopPlayer from '@/components/video/VideoLoopPlayer';
import usePlaySourceContext from '@/hooks/usePlaySource';
import { CommentIcon, PlayIcon, StatefulPlayPauseIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { generateLinkUrl } from '@/utils/embeds';
import { getCountString } from '@/utils/utils';

import DiscoverCard, {
  DiscoverCardBackground,
  type DiscoverCardProps,
} from './DiscoverCard';
import DiscoverCardActions from './DiscoverCardActions';
import DiscoverCardMeta from './DiscoverCardMeta';

export type DiscoverSongCardProps = DiscoverCardProps & {
  index: number;
  clipId?: string;
  clipImage?: string;
  clipVideo?: string;
  clipTitle?: string | null;
  clipCaption?: string | null;
  clipArtistAvatar?: string;
  clipArtistDisplayName?: string;
  clipArtistHandle?: string;
  clipArtistHref?: string;
  playCount?: number;
  likeCount?: number;
  commentCount?: number;
  isPlaying?: boolean;
  contestCard?: boolean;
  onPlayPauseClick?: (
    payload: {
      index?: number;
      id: string;
    },
    e?: Event | React.MouseEvent
  ) => void;
  onLikeClick?: ({ isLiked }: { isLiked: boolean }) => void;
  onPlayCountClick?: (
    payload: {
      index?: number;
      id: string;
    },
    e?: Event | React.MouseEvent
  ) => void;
  onCommentClick?: (
    payload: {
      index?: number;
      id: string;
    },
    e?: Event | React.MouseEvent
  ) => void;
};

export type Props = React.HTMLAttributes<HTMLDivElement> &
  DiscoverSongCardProps;

const DiscoverSongCard: React.FC<Props> = (props) => {
  const {
    children,
    className: explicitClassName,
    backgroundImageClassName,
    backgroundOverlayClassName,
    clipId,
    clipImage,
    clipVideo,
    clipTitle,
    clipCaption,
    clipArtistAvatar,
    clipArtistDisplayName,
    clipArtistHandle,
    clipArtistHref,
    playCount,
    likeCount,
    commentCount,
    isPlaying,
    index,
    onPlayPauseClick,
    onLikeClick,
    onPlayCountClick,
    onCommentClick,
    contestCard,
    ...restProps
  } = props;

  const { t } = useTranslation();
  const playSource = usePlaySourceContext();
  const clipUrl = clipId && generateLinkUrl(clipId, 'song');

  const className = twMerge('group w-[257px] h-[257px]', explicitClassName);

  const actions = useMemo(
    () => (
      // Negative x-margin to compensate for button padding
      <DiscoverCardActions className='pointer-events-auto -mx-1 -mt-1 max-w-max gap-2'>
        {playCount || onPlayCountClick ? (
          <Button
            variant={ButtonVariant.Inherit}
            shape={ButtonShape.Rounded}
            size={ButtonSize.Micro}
            icon={PlayIcon}
            iconClassName='w-4 h-4'
            href={undefined}
            onClick={
              onPlayCountClick &&
              ((e) =>
                onPlayCountClick(
                  {
                    id: clipId || '',
                  },
                  e
                ))
            }
            aria-label={
              playCount == null
                ? undefined
                : t('card.numPlays', {
                    count: playCount,
                    formattedCount: getCountString(playCount),
                  })
            }
          >
            {playCount == null ? null : getCountString(playCount)}
          </Button>
        ) : null}
        <ClipLikeButton
          clipId={clipId || ''}
          variant={ButtonVariant.Inherit}
          shape={ButtonShape.Rounded}
          size={ButtonSize.Micro}
          iconClassName='w-4 h-4'
          href={undefined}
          onClick={onLikeClick}
          aria-label={
            likeCount == null
              ? undefined
              : t('card.numLikes', {
                  count: likeCount,
                  formattedCount: getCountString(likeCount),
                })
          }
          showCount={likeCount != null}
        />
        {commentCount || onCommentClick ? (
          <Button
            variant={ButtonVariant.Inherit}
            shape={ButtonShape.Rounded}
            size={ButtonSize.Micro}
            icon={CommentIcon}
            iconClassName='w-4 h-4'
            href={undefined}
            onClick={
              onCommentClick &&
              ((e) =>
                onCommentClick(
                  {
                    id: clipId || '',
                  },
                  e
                ))
            }
            aria-label={
              commentCount == null
                ? undefined
                : t('card.numComments', {
                    count: commentCount,
                    formattedCount: getCountString(commentCount),
                  })
            }
          >
            {commentCount == null ? null : getCountString(commentCount)}
          </Button>
        ) : null}
      </DiscoverCardActions>
    ),
    [
      commentCount,
      likeCount,
      playCount,
      onCommentClick,
      onLikeClick,
      onPlayCountClick,
      clipId,
      t,
    ]
  );

  const clipTitleWithLink = useMemo(
    () =>
      clipUrl
        ? ({ className: innerClassName }: { className?: string }) => (
            <Link
              href={clipUrl}
              onClick={() => {
                logWebUserEvent({
                  actionName: 'DiscoverSongCardTitleClicked',
                  principalObjectType: 'clip',
                  principalObjectValue: clipId || '',
                  context: {
                    title: clipTitle || '',
                    caption: clipCaption || '',
                    artistDisplayName: clipArtistDisplayName || '',
                    artistHandle: clipArtistHandle || '',
                    likeCount: likeCount,
                    playCount: playCount,
                    playSourceType: playSource.playSourceType,
                    playSourceId: playSource.playSourceId,
                    index,
                  },
                });
              }}
            >
              <h2 className={twMerge(innerClassName, 'hover:underline')}>
                {clipTitle}
              </h2>
            </Link>
          )
        : clipTitle,
    [
      clipUrl,
      clipId,
      clipTitle,
      clipCaption,
      clipArtistDisplayName,
      clipArtistHandle,
      likeCount,
      playCount,
      playSource,
      index,
    ]
  );

  const backgroundContent = useMemo(() => {
    const handleCardClick = onPlayPauseClick
      ? (e: React.MouseEvent) => {
          onPlayPauseClick(
            {
              id: clipId || '',
            },
            e
          );
        }
      : undefined;
    const backgroundImage = clipImage;
    return function DiscoverSongCardBackground({
      className: backgroundClassName,
    }: {
      className?: string;
    }) {
      const [isHovered, setIsHovered] = useState(false);
      const handleMouseEnter: React.MouseEventHandler<HTMLDivElement> =
        useCallback(() => {
          setIsHovered(true);
        }, []);
      const handleMouseLeave: React.MouseEventHandler<HTMLDivElement> =
        useCallback(() => {
          setIsHovered(false);
        }, []);
      if (clipVideo) {
        return (
          <div
            className={twMerge(
              'cursor-pointer text-black',
              'after:absolute after:inset-0 after:bg-linear-to-t after:from-black after:to-opacity-black-20',
              backgroundClassName
            )}
            onClick={handleCardClick}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          >
            <VideoLoopPlayer
              videoUrl={clipVideo}
              className='absolute inset-0 h-full w-full object-cover'
              playing={isHovered}
            />
          </div>
        );
      }
      return (
        <DiscoverCardBackground
          className={twMerge(
            'cursor-pointer text-black',
            '[--image-background-scale:1] group-focus-within:[--image-background-scale:1.1] group-hover:[--image-background-scale:1.1]',
            backgroundClassName
          )}
          imageClassName={clsx(
            contestCard
              ? 'bg-cover'
              : 'bg-size-[auto_calc(100%*var(--image-background-scale,1))] transition-[background-size] duration-300',
            !contestCard &&
              'after:absolute after:inset-0 after:bg-linear-to-t after:from-black after:to-opacity-black-20'
          )}
          backgroundImage={backgroundImage}
          overlayColor={null}
          onClick={handleCardClick}
        />
      );
    };
  }, [clipImage, clipVideo, clipId, onPlayPauseClick]);

  const playButton = useMemo(() => {
    return (
      onPlayPauseClick && (
        <div className='pointer-events-auto'>
          <Button
            className={clsx(
              'group border border-border-secondary bg-background-glass-thin backdrop-blur-md hover:bg-background-glass-thick enabled:hover:bg-background-glass-thick',
              {
                'border-none bg-background-secondary/30 hover:bg-background-secondary/20':
                  contestCard,
              }
            )}
            variant={
              contestCard ? ButtonVariant.Secondary : ButtonVariant.Glass
            }
            shape={ButtonShape.Pill}
            size={contestCard ? ButtonSize.Small : ButtonSize.Medium}
            icon={StatefulPlayPauseIcon}
            iconClassName={contestCard ? 'w-[15px] h-[15px]' : 'w-5 h-5'}
            href={undefined}
            onClick={(e) => {
              onPlayPauseClick(
                {
                  id: clipId || '',
                },
                e
              );
            }}
            aria-label={isPlaying ? t('media.pause') : t('media.play')}
          />
        </div>
      )
    );
  }, [onPlayPauseClick, clipId, isPlaying]);

  return (
    <DiscoverCard
      data-media-playing={isPlaying}
      className={className}
      contentClassName='flex flex-col justify-between items-stretch gap-2 pointer-events-none'
      backgroundContent={backgroundContent}
      {...restProps}
    >
      {contestCard ? null : actions}
      <div className='flex-1' />
      <DiscoverCardMeta
        className={clsx(
          'min-w-0 flex-1 place-content-end *:pointer-events-auto',
          {
            '-mb-2': children,
          },
          {
            'place-content-start justify-start': contestCard,
          }
        )}
        title={contestCard ? null : clipTitleWithLink}
        titleClassName={clsx(
          'max-h-[2.4em] line-clamp-2',
          'transition-[max-height] duration-0 group-hover:duration-300',
          'group-hover:max-h-[4.8em] group-hover:line-clamp-4'
        )}
        subtitle={clipCaption}
        subtitleClassName='line-clamp-2'
        content={
          !(clipArtistDisplayName || clipArtistHandle) || contestCard ? null : (
            <AvatarTag
              className='max-w-max font-sans text-[14px] leading-[16px] font-normal text-foreground-primary-glass'
              avatarClassName='w-4 h-4'
              imageUrl={clipArtistAvatar}
              displayName={clipArtistDisplayName}
              handle={clipArtistHandle}
              href={clipArtistHref}
              onClick={() => {
                logWebUserEvent({
                  actionName: 'DiscoverSongCardArtistClicked',
                  principalObjectType: 'clip',
                  principalObjectValue: clipId || '',
                  context: {
                    title: clipTitle || '',
                    caption: clipCaption || '',
                    artistDisplayName: clipArtistDisplayName || '',
                    artistHandle: clipArtistHandle || '',
                    likeCount: likeCount,
                    commentCount: commentCount,
                    playCount: playCount,
                    playSourceType: playSource.playSourceType,
                    playSourceId: playSource.playSourceId,
                    index,
                  },
                });
              }}
            />
          )
        }
        action={!children || contestCard ? playButton : undefined}
      />
      {children && !contestCard && (
        <div className='flex min-h-0 flex-row items-end justify-between gap-3'>
          <div className='min-w-0 flex-1'>{children}</div>
          {playButton}
        </div>
      )}
    </DiscoverCard>
  );
};

export default DiscoverSongCard;
