import { useDynamicConfig } from '@statsig/react-bindings';
import clsx from 'clsx';
import React, { memo, useCallback } from 'react';
import { twMerge } from 'tailwind-merge';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { ClipLikeButton } from '@/components/button/ClipLikeButton';
import { AvatarMaskShape } from '@/components/image/Avatar';
import Avatar from '@/components/image/Avatar';
import Link from '@/components/link/Link';
import ProfileLink from '@/components/link/ProfileLink';
import MusicStyleTags from '@/components/tag/MusicStyleTags';
import VerifiedBadge from '@/components/timbaland/VerifiedBadge';
import { CommentIcon, PlayIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import {
  SMALL_IMAGE,
  TYPOGRAPHY_DISCOVER_FEED_BODY_1_CLASSNAME,
  TYPOGRAPHY_DISCOVER_FEED_BODY_2_CLASSNAME,
} from '@/utils/constants';
import { getCountString, isVerifiedProfile } from '@/utils/utils';

type SongFeedItemStatsProps = React.HTMLAttributes<HTMLDivElement> & {
  playCount: number;
  commentCount: number;
  onPlayClick: () => void;
  clipId: string;
  index: number;
  likeCount: number;
  listId: string;
  listTitle: string;
  listContextId?: string;
};

export const SongFeedItemStats: React.FC<SongFeedItemStatsProps> = memo(
  function SongFeedItemStats(props) {
    const {
      className,
      playCount,
      commentCount,
      onPlayClick,
      clipId,
      index,
      likeCount,
      listId,
      listTitle,
      listContextId,
      ...restProps
    } = props;

    const handleLikeClick = useCallback(
      ({ likeCount, isLiked }: { likeCount: number; isLiked: boolean }) => {
        logWebUserEvent({
          actionName: 'SongFeedItemLikeClicked',
          principalObjectType: 'song',
          principalObjectValue: clipId,
          context: {
            index: index,
            playCount: playCount,
            likeCount,
            commentCount: commentCount,
            sectionId: listId,
            sectionTitle: listTitle,
            isLiked,
            sectionContextId: listContextId,
          },
        });
      },
      [clipId, index, playCount, commentCount, listId, listTitle, listContextId]
    );

    const handleCommentsClick = useCallback(() => {
      logWebUserEvent({
        actionName: 'SongFeedItemCommentsClicked',
        principalObjectType: 'song',
        principalObjectValue: clipId,
        context: {
          index: index,
          playCount: playCount,
          likeCount: likeCount,
          commentCount: commentCount,
          sectionId: listId,
          sectionTitle: listTitle,
          sectionContextId: listContextId,
        },
      });
    }, [
      clipId,
      index,
      playCount,
      likeCount,
      commentCount,
      listId,
      listTitle,
      listContextId,
    ]);

    return (
      <div className={twMerge('flex flex-row gap-1', className)} {...restProps}>
        <Button
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Micro}
          shape={ButtonShape.Rounded}
          icon={PlayIcon}
          aria-label='Play Count'
          onClick={onPlayClick}
          active={false}
        >
          {getCountString(playCount)}
        </Button>
        <ClipLikeButton
          clipId={clipId}
          onClick={handleLikeClick}
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Micro}
          shape={ButtonShape.Rounded}
        />
        <Button
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Micro}
          shape={ButtonShape.Rounded}
          icon={CommentIcon}
          active={false}
          href={`/song/${clipId}?show_comments=true`}
          onClick={handleCommentsClick}
          aria-label='Comment Count'
        >
          {getCountString(commentCount)}
        </Button>
      </div>
    );
  }
);

export type SongFeedItemArtistTagProps =
  React.HTMLAttributes<HTMLDivElement> & {
    displayName?: string | null;
    handle: string;
    imageUrl?: string;
    showAvatar?: boolean;
    fontSize?: number;
    isVerified?: boolean;
    personaId?: string;
    personaImageUrl?: string;
    personaDisplayName?: string;
    clipId: string;
    index: number;
    playCount: number;
    likeCount: number;
    commentCount: number;
    listId: string;
    listTitle: string;
    listContextId?: string;
    artistId: string;
  };

export const SongFeedItemArtistTag = memo(function SongFeedItemArtistTag(
  props: SongFeedItemArtistTagProps
) {
  const {
    className,
    displayName,
    handle,
    imageUrl,
    isVerified = isVerifiedProfile({ handle: handle || '' }),
    personaId,
    personaImageUrl,
    personaDisplayName,
    index,
    playCount,
    likeCount,
    commentCount,
    listId,
    listTitle,
    clipId,
    listContextId,
    artistId,
    ...restProps
  } = props;

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

  const isVerifiedArtistProfile =
    isVerified || isVerifiedProfile({ handle: handle || '' }, handles);

  const showPersona = !!personaId;

  const handleArtistClick = useCallback(() => {
    logWebUserEvent({
      actionName: 'SongFeedItemArtistClicked',
      principalObjectType: 'song',
      principalObjectValue: clipId,
      context: {
        index: index,
        playCount: playCount,
        likeCount: likeCount,
        commentCount: commentCount,
        sectionId: listId,
        sectionTitle: listTitle,
        artistId: artistId,
        sectionContextId: listContextId,
      },
    });
  }, [
    clipId,
    index,
    playCount,
    likeCount,
    commentCount,
    listId,
    listTitle,
    artistId,
    listContextId,
  ]);

  const handlePersonaClick = useCallback(() => {
    logWebUserEvent({
      actionName: 'SongFeedItemPersonaClicked',
      principalObjectType: 'song',
      principalObjectValue: clipId,
      context: {
        index: index,
        playCount: playCount,
        likeCount: likeCount,
        commentCount: commentCount,
        sectionId: listId,
        sectionTitle: listTitle,
        personaId: personaId || '',
        personaDisplayName: personaDisplayName || '',
        sectionContextId: listContextId,
      },
    });
  }, [
    clipId,
    index,
    playCount,
    likeCount,
    commentCount,
    listId,
    listTitle,
    personaId,
    personaDisplayName,
    listContextId,
  ]);

  return (
    <div
      className={twMerge(
        'flex w-full flex-row items-center gap-1',
        'font-sans text-xs font-medium text-foreground-tertiary',
        className
      )}
      {...restProps}
    >
      {/* User avatar and name */}
      <ProfileLink
        className={clsx('flex flex-row items-center gap-1.5', {
          'min-w-1/2 shrink-[0.1]': showPersona,
        })}
        handle={handle}
        title={displayName || `@${handle}`}
        onClick={handleArtistClick}
      >
        <div className='relative block'>
          <Avatar
            className='h-3 w-3'
            src={imageUrl || null}
            imageSize={SMALL_IMAGE}
            alt='Profile avatar'
          />
          {isVerifiedArtistProfile && (
            <VerifiedBadge className='absolute end-0 bottom-0 h-2 w-2 drop-shadow-avatar-overlay' />
          )}
        </div>
        <div className='line-clamp-1 break-all text-ellipsis'>
          {displayName || `@${handle}`}
        </div>
      </ProfileLink>

      {/* Persona avatar and name */}
      {showPersona && (
        <>
          {'·'}
          <Link
            className='flex flex-row items-center gap-1.5 hover:underline'
            href={`/persona/${personaId}`}
            onClick={handlePersonaClick}
          >
            <Avatar
              imageSize={SMALL_IMAGE}
              className='h-4 w-4'
              src={personaImageUrl || ''}
              alt='Persona image'
              maskShape={AvatarMaskShape.Persona}
            />
            <div className='line-clamp-1 break-all text-ellipsis'>
              {personaDisplayName}
            </div>
          </Link>
        </>
      )}
    </div>
  );
});

type SongFeedItemDataProps = {
  index: number;
  listId: string;
  listTitle: string;
  title: string;
  titleExtra?: React.ReactNode;
  tags: string[];
  displayName: string;
  handle: string;
  imageUrl: string;
  personaId?: string;
  personaName?: string;
  personaImageUrl?: string;
  likeCount: number;
  playCount: number;
  commentCount: number;
  clipId: string;
  onPlayClick: () => void;
  hideAvatar?: boolean;
  listContextId?: string;
  artistId: string;
};

export const SongFeedItemData: React.FC<
  Omit<React.HTMLAttributes<HTMLDivElement>, keyof SongFeedItemDataProps> &
    SongFeedItemDataProps
> = memo(function SongFeedItemData(props) {
  const {
    className,
    children,
    index,
    listId,
    listTitle,
    title,
    titleExtra,
    tags,
    displayName,
    handle,
    imageUrl,
    personaId,
    personaName,
    personaImageUrl,
    playCount,
    likeCount,
    commentCount,
    clipId,
    listContextId,
    onPlayClick,
    hideAvatar,
    artistId,
    ...restProps
  } = props;

  const handleTitleClick = useCallback(() => {
    logWebUserEvent({
      actionName: 'SongFeedItemTitleClicked',
      principalObjectType: 'song',
      principalObjectValue: clipId,
      context: {
        index: index,
        playCount: playCount,
        likeCount: likeCount,
        commentCount: commentCount,
        sectionId: listId,
        sectionTitle: listTitle,
        artistId: artistId,
        sectionContextId: listContextId,
      },
    });
  }, [
    clipId,
    index,
    playCount,
    likeCount,
    commentCount,
    listId,
    listTitle,
    artistId,
    listContextId,
  ]);

  return (
    <div className={clsx('flex flex-col gap-1', className)} {...restProps}>
      <div className='flex flex-row items-start justify-stretch gap-1 px-1'>
        <div className='flex min-w-0 flex-1 flex-col gap-1'>
          <div className='flex flex-row items-center justify-start gap-2'>
            <Link
              className={clsx(
                TYPOGRAPHY_DISCOVER_FEED_BODY_1_CLASSNAME,
                'cursor-pointer text-foreground-primary hover:underline',
                // 'min-w-0 line-clamp-1 break-words' // Truncation has a gap
                'min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap'
              )}
              href={`/song/${clipId}`}
              title={title}
              onClick={handleTitleClick}
            >
              {title || 'Untitled'}
            </Link>
            {titleExtra}
          </div>
          <div
            className={clsx('flex flex-row justify-between gap-1', {
              'flex-col items-start': !hideAvatar,
              'items-center': hideAvatar,
            })}
          >
            <MusicStyleTags
              className={clsx(
                TYPOGRAPHY_DISCOVER_FEED_BODY_2_CLASSNAME,
                'line-clamp-1 text-foreground-tertiary'
              )}
              tags={tags}
              renderTag={tags.length ? undefined : null}
            />
            {hideAvatar && (
              <SongFeedItemStats
                playCount={playCount}
                commentCount={commentCount}
                onPlayClick={onPlayClick}
                clipId={clipId}
                index={index}
                likeCount={likeCount}
                listId={listId}
                listTitle={listTitle}
                listContextId={listContextId}
              />
            )}
          </div>
        </div>
        {children}
      </div>
      {!hideAvatar && (
        <div className='flex flex-row items-center justify-stretch gap-1 overflow-x-clip px-1'>
          <SongFeedItemArtistTag
            clipId={clipId}
            index={index}
            playCount={playCount}
            likeCount={likeCount}
            commentCount={commentCount}
            listId={listId}
            listTitle={listTitle}
            listContextId={listContextId}
            className={clsx(
              TYPOGRAPHY_DISCOVER_FEED_BODY_2_CLASSNAME,
              'text-foreground-primary'
            )}
            displayName={displayName}
            handle={handle}
            imageUrl={imageUrl}
            personaId={personaId}
            personaDisplayName={personaName}
            personaImageUrl={personaImageUrl}
            artistId={artistId}
          />
          <SongFeedItemStats
            playCount={playCount}
            commentCount={commentCount}
            onPlayClick={onPlayClick}
            clipId={clipId}
            index={index}
            likeCount={likeCount}
            listId={listId}
            listTitle={listTitle}
            listContextId={listContextId}
          />
        </div>
      )}
    </div>
  );
});
