'use client';

import { TinyColor } from '@ctrl/tinycolor';
import clsx from 'clsx';
import { useRouter } from 'next/navigation';
import { useMemo } 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 Link from '@/components/link/Link';
import usePlaySourceContext from '@/hooks/usePlaySource';
import {
  CommentIcon,
  PlayIcon,
  StatefulPlayPauseIcon,
  ThumbsUpIcon,
} from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { generateLinkUrl } from '@/utils/embeds';
import { fnv1a, getCountString } from '@/utils/utils';

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

export const PLAYLIST_DEFAULT_BACKGROUND_COLORS = [
  '#fd429b',
  '#1f8bff',
  '#ff6a00',
  '#02d95c',
  '#f5da07',
  '#8b6fff',
];

export function getFallbackColor(id?: string) {
  if (!id) {
    return '#000';
  }
  const hash = fnv1a(id);
  return PLAYLIST_DEFAULT_BACKGROUND_COLORS[
    hash % PLAYLIST_DEFAULT_BACKGROUND_COLORS.length
  ];
}

export type DiscoverPlaylistCardProps = DiscoverCardProps & {
  index: number;
  playlistId?: string;
  playlistImage?: string;
  playlistTitle?: string | null;
  playlistDescription?: string | null;
  playlistAuthorAvatar?: string;
  playlistAuthorDisplayName?: string;
  playlistAuthorHandle?: string;
  playlistAuthorHref?: string;
  songCount?: number;
  playCount?: number;
  likeCount?: number;
  commentCount?: number;
  isPlaying?: boolean;
  onPlayPauseClick?: (
    payload: {
      index?: number;
      id: string;
    },
    e?: Event | React.MouseEvent
  ) => void;
  onLikeClick?: (
    payload: {
      index?: number;
      id: string;
    },
    e?: Event | React.MouseEvent
  ) => 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> &
  DiscoverPlaylistCardProps;

const DiscoverPlaylistCard: React.FC<Props> = (props) => {
  const {
    className: explicitClassName,
    backgroundImageClassName,
    backgroundOverlayClassName,
    playlistId,
    playlistImage,
    playlistTitle,
    playlistDescription,
    playlistAuthorAvatar,
    playlistAuthorDisplayName,
    playlistAuthorHandle,
    playlistAuthorHref,
    songCount,
    playCount,
    likeCount,
    commentCount,
    isPlaying,
    index,
    onPlayPauseClick,
    onLikeClick,
    onPlayCountClick,
    onCommentClick,
    ...restProps
  } = props;

  const { t } = useTranslation();
  const router = useRouter();
  const playSource = usePlaySourceContext();
  const playlistUrl = playlistId && generateLinkUrl(playlistId, 'playlist');

  const className = twMerge('group w-[386px] 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'>
        {songCount && (
          <Button
            variant={ButtonVariant.Inherit}
            shape={ButtonShape.Rounded}
            size={ButtonSize.Micro}
          >
            {songCount == null
              ? null
              : t('card.numSongs', {
                  count: songCount,
                  formattedCount: getCountString(songCount),
                })}
          </Button>
        )}
        {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: playlistId || '',
                  },
                  e
                ))
            }
            aria-label={
              playCount == null
                ? undefined
                : t('card.numPlays', {
                    count: playCount,
                    formattedCount: getCountString(playCount),
                  })
            }
          >
            {playCount == null ? null : getCountString(playCount)}
          </Button>
        ) : null}
        <Button
          variant={ButtonVariant.Inherit}
          shape={ButtonShape.Rounded}
          size={ButtonSize.Micro}
          icon={ThumbsUpIcon}
          iconClassName='w-4 h-4'
          href={undefined}
          onClick={
            onLikeClick &&
            ((e) =>
              onLikeClick(
                {
                  id: playlistId || '',
                },
                e
              ))
          }
          aria-label={
            likeCount == null
              ? undefined
              : t('card.numLikes', {
                  count: likeCount,
                  formattedCount: getCountString(likeCount),
                })
          }
        >
          {likeCount == null ? null : getCountString(likeCount)}
        </Button>
        {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: playlistId || '',
                  },
                  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,
      songCount,
      onCommentClick,
      onLikeClick,
      onPlayCountClick,
      playlistId,
      t,
    ]
  );

  const playlistTitleWithLink = useMemo(
    () =>
      playlistUrl
        ? ({ className: innerClassName }: { className?: string }) => (
            <Link
              href={playlistUrl}
              onClick={() => {
                logWebUserEvent({
                  actionName: 'DiscoverPlaylistCardTitleClicked',
                  principalObjectType: 'playlist',
                  principalObjectValue: playlistId || '',
                  context: {
                    title: playlistTitle || '',
                    description: playlistDescription || '',
                    artistDisplayName: playlistAuthorDisplayName || '',
                    artistHandle: playlistAuthorHandle || '',
                    songCount: songCount,
                    likeCount: likeCount,
                    playCount: playCount,
                    playSourceType: playSource.playSourceType,
                    playSourceId: playSource.playSourceId,
                    index,
                  },
                });
              }}
            >
              <h2 className={twMerge(innerClassName, 'hover:underline')}>
                {playlistTitle}
              </h2>
            </Link>
          )
        : playlistTitle,
    [
      playlistUrl,
      playlistTitle,
      playlistId,
      playlistDescription,
      playlistAuthorDisplayName,
      playlistAuthorHandle,
      songCount,
      likeCount,
      playCount,
      playSource,
      index,
    ]
  );

  const backgroundContent = useMemo(() => {
    const handleCardClick = playlistUrl
      ? () => {
          router.push(playlistUrl);
        }
      : undefined;
    const backgroundImage = playlistImage;
    const overlayColor = backgroundImage
      ? undefined
      : getFallbackColor(playlistId);
    const backgroundColor =
      overlayColor && new TinyColor(overlayColor).darken(50).toHexString();
    return function DiscoverPlaylistCardBackground({
      className: backgroundClassName,
    }: {
      className?: string;
    }) {
      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(
            'bg-size-[calc(100%*var(--image-background-scale,1))]',
            'transition-[background-size] duration-300'
          )}
          backgroundImage={backgroundImage}
          backgroundColor={backgroundColor}
          overlayColor={overlayColor}
          onClick={handleCardClick}
        />
      );
    };
  }, [playlistId, playlistImage, playlistUrl, router]);

  return (
    <DiscoverCard
      data-media-playing={isPlaying}
      className={className}
      contentClassName='flex flex-col justify-between items-stretch gap-2 pointer-events-none'
      backgroundContent={backgroundContent}
      {...restProps}
    >
      {actions}
      <div className='flex min-h-0 flex-row items-end justify-between gap-3'>
        <DiscoverCardMeta
          className='max-w-max min-w-0 flex-1 *:pointer-events-auto'
          title={playlistTitleWithLink}
          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={playlistDescription}
          subtitleClassName='line-clamp-2'
          content={
            !(playlistAuthorDisplayName || playlistAuthorHandle) ? null : (
              <AvatarTag
                className='max-w-max py-2 font-sans text-[14px] leading-[16px] font-normal text-foreground-primary-glass'
                avatarClassName='w-4 h-4'
                imageUrl={playlistAuthorAvatar}
                displayName={playlistAuthorDisplayName}
                handle={playlistAuthorHandle}
                href={playlistAuthorHref}
                onClick={() => {
                  logWebUserEvent({
                    actionName: 'DiscoverPlaylistCardArtistClicked',
                    principalObjectType: 'playlist',
                    principalObjectValue: playlistId || '',
                    context: {
                      title: playlistTitle || '',
                      description: playlistDescription || '',
                      artistDisplayName: playlistAuthorDisplayName || '',
                      artistHandle: playlistAuthorHandle || '',
                      songCount: songCount,
                      likeCount: likeCount,
                      playCount: playCount,
                      playSourceType: playSource.playSourceType,
                      playSourceId: playSource.playSourceId,
                      index,
                    },
                  });
                }}
              />
            )
          }
        />
        {onPlayPauseClick && (
          <div className='pointer-events-auto'>
            <Button
              className='group'
              variant={ButtonVariant.Fog}
              shape={ButtonShape.Pill}
              size={ButtonSize.Medium}
              icon={StatefulPlayPauseIcon}
              iconClassName='w-5 h-5'
              href={undefined}
              onClick={(e) => {
                onPlayPauseClick(
                  {
                    id: playlistId || '',
                  },
                  e
                );
              }}
              aria-label={isPlaying ? t('media.pause') : t('media.play')}
            />
          </div>
        )}
      </div>
    </DiscoverCard>
  );
};

export default DiscoverPlaylistCard;
