import clsx from 'clsx';
import { pick } from 'lodash-es';
import React, { useCallback, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import Link from '@/components/link/Link';
import ProfileLink from '@/components/link/ProfileLink';
import useFollowUser from '@/hooks/useFollowUser';
import {
  PlayIcon,
  PlusIcon,
  PulsingLinesIcon,
  UserAddIcon,
  UserAddedIcon,
} from '@/icons';
import { getCountString } from '@/utils/utils';

import { HookActionHandler } from './constants';

export type HookSongBarProps = {
  className?: string;
  backgroundClassName?: string;
  contentClassName?: string;
  thumbnailClassName?: string;
  titleClassName?: string;
  authorClassName?: string;
  id?: string;
  title?: string;
  displayName?: string;
  handle?: string;
  hookId?: string;
  clipId?: string;
  recommendationItemId?: string;
  clipTitle?: string;
  clipDisplayName?: string;
  clipHandle?: string;
  clipImageUrl?: string;
  clipPlayCount?: number;
  currentUserHandle?: string;
  showFollowButton?: boolean;
  isFollowingCreator?: boolean;
  isRemixDisabled?: boolean;
  isPlaying?: boolean;
  onAddToPlaylist?: HookActionHandler<{ clipId: string }> | null;
  onSongArtistClick?: HookActionHandler<{
    clipId: string;
    handle: string;
  }> | null;
  onSongThumbnailClick?: HookActionHandler<{ clipId: string }> | null;
  onSongTitleClick?: HookActionHandler<{ clipId: string }> | null;
  onRemix?: HookActionHandler<{ clipId: string }> | null;
};

export type Props = Omit<
  React.HTMLAttributes<HTMLDivElement>,
  keyof HookSongBarProps
> &
  HookSongBarProps;

const HookSongBar: React.FC<Props> = React.memo((props) => {
  const {
    children,
    className,
    backgroundClassName,
    contentClassName,
    thumbnailClassName,
    titleClassName,
    authorClassName,
    hookId,
    clipId,
    recommendationItemId,
    clipTitle,
    clipDisplayName,
    clipHandle,
    clipImageUrl,
    clipPlayCount,
    currentUserHandle,
    isFollowingCreator = false,
    showFollowButton = false,
    isRemixDisabled = false,
    isPlaying = false,
    onAddToPlaylist,
    onSongArtistClick,
    onSongThumbnailClick,
    onSongTitleClick,
    onRemix,
    ...restProps
  } = props;

  const { t } = useTranslation();
  const { isFollowing, setIsFollowing } = useFollowUser(
    clipHandle || '',
    isFollowingCreator,
    {
      recommendationItemId,
      hookId,
    }
  );

  const actionPayloadRef = useRef({
    hookId: hookId || '',
    clipId: clipId || '',
    recommendationItemId,
    isFollowing,
    handle: clipHandle || '',
  });
  useEffect(() => {
    actionPayloadRef.current.hookId = hookId || '';
    actionPayloadRef.current.clipId = clipId || '';
    actionPayloadRef.current.recommendationItemId = recommendationItemId;
    actionPayloadRef.current.handle = clipHandle || '';
    actionPayloadRef.current.isFollowing = isFollowing;
  }, [hookId, clipId, recommendationItemId, isFollowing, clipHandle]);

  const shouldShowFollowButton =
    showFollowButton &&
    clipHandle &&
    currentUserHandle &&
    currentUserHandle !== clipHandle;

  const handleAddToPlaylistClick = useCallback(
    (e: React.MouseEvent) => {
      onAddToPlaylist?.(
        pick(actionPayloadRef.current, [
          'clipId',
          'hookId',
          'recommendationItemId',
        ]),
        e
      );
    },
    [onAddToPlaylist]
  );
  const handleRemixClick = useCallback(
    (e: React.MouseEvent) => {
      onRemix?.(
        pick(actionPayloadRef.current, [
          'clipId',
          'hookId',
          'recommendationItemId',
        ]),
        e
      );
    },
    [onRemix]
  );

  const handleArtistClick = useCallback(
    (e: React.MouseEvent) => {
      onSongArtistClick?.(
        pick(actionPayloadRef.current, [
          'clipId',
          'hookId',
          'handle',
          'recommendationItemId',
        ]),
        e
      );
    },
    [onSongArtistClick]
  );

  const handleThumbnailClick = useCallback(
    (e: React.MouseEvent) => {
      onSongThumbnailClick?.(
        pick(actionPayloadRef.current, [
          'clipId',
          'hookId',
          'recommendationItemId',
        ]),
        e
      );
    },
    [onSongThumbnailClick]
  );

  const handleTitleClick = useCallback(
    (e: React.MouseEvent) => {
      onSongTitleClick?.(
        pick(actionPayloadRef.current, [
          'clipId',
          'hookId',
          'recommendationItemId',
        ]),
        e
      );
    },
    [onSongTitleClick]
  );

  return (
    <div
      className={twMerge('relative min-h-15', className)}
      style={
        clipImageUrl
          ? ({
              '--background-image': `url(${clipImageUrl})`,
            } as React.CSSProperties)
          : undefined
      }
      {...restProps}
    >
      <div
        className={twMerge(
          clsx(
            'absolute inset-0 overflow-clip rounded-full',
            '[background:var(--background-image,var(--color-background-fog-thin))]',
            {
              'before:absolute before:inset-0 before:rounded-full before:bg-dumbo-150/70 before:backdrop-blur-3xl':
                clipImageUrl,
            }
          ),
          backgroundClassName
        )}
      />
      <div
        className={twMerge(
          'relative flex flex-row items-center gap-2 p-2',
          contentClassName
        )}
      >
        <div className='flex w-full flex-row items-center gap-4'>
          <Link
            className={twMerge(
              'relative block size-11 overflow-clip rounded-full',
              thumbnailClassName
            )}
            href={`/song/${clipId}`}
            onClick={onSongThumbnailClick ? handleThumbnailClick : undefined}
          >
            <ImageWithFallback
              className={clsx(
                'absolute inset-0 h-full w-full object-cover',
                'animate-spin animate-duration-[6s]',
                { 'animate-pause': !isPlaying }
              )}
              src={clipImageUrl}
              alt={clipTitle || 'Untitled'}
            />
            <PulsingLinesIcon
              className={clsx(
                'absolute top-1/2 left-1/2 -translate-1/2 text-foreground-primary-glass',
                {
                  '--animation-play-state': isPlaying ? 'playing' : 'paused',
                }
              )}
              style={
                {
                  '--animation-play-state': isPlaying ? 'playing' : 'paused',
                } as React.CSSProperties
              }
            />
          </Link>

          <div className='flex min-w-0 flex-1 flex-col items-start gap-0.5'>
            <Link
              className={twMerge(
                'flex max-w-max flex-row items-center',
                'cursor-pointer hover:underline',
                'font-sans text-[14px] leading-[16px] font-medium',
                'text-foreground-primary-glass',
                titleClassName
              )}
              href={`/song/${clipId}`}
              onClick={onSongTitleClick ? handleTitleClick : undefined}
            >
              <span className='line-clamp-1'>{clipTitle || 'Untitled'}</span>
            </Link>
            {clipHandle ? (
              <div className='flex flex-row items-center gap-2 text-foreground-tertiary-glass'>
                {clipPlayCount == null ? null : (
                  <>
                    <Button
                      className='block px-0'
                      variant={ButtonVariant.Inherit}
                      size={ButtonSize.Micro}
                      shape={ButtonShape.Rounded}
                      icon={PlayIcon}
                      aria-label='Play Count'
                    >
                      {getCountString(clipPlayCount)}
                    </Button>
                    <i className='block size-1 rounded-full bg-current' />
                  </>
                )}
                <ProfileLink
                  className={twMerge(
                    'flex w-max max-w-max flex-row items-center',
                    'cursor-pointer hover:underline',
                    'font-sans text-[12px] leading-[16px] font-normal',
                    authorClassName
                  )}
                  handle={clipHandle}
                  onClick={onSongArtistClick ? handleArtistClick : undefined}
                >
                  <span className='line-clamp-1'>
                    {clipDisplayName || `@${clipHandle}`}
                  </span>
                </ProfileLink>
                {shouldShowFollowButton && (
                  <Button
                    variant={
                      isFollowing
                        ? ButtonVariant.Secondary
                        : ButtonVariant.Primary
                    }
                    size={ButtonSize.Mini}
                    shape={ButtonShape.Pill}
                    onClick={async (e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      try {
                        await setIsFollowing(!isFollowing);
                      } catch (error) {
                        console.error('Follow action failed:', error);
                      }
                    }}
                    icon={isFollowing ? UserAddedIcon : UserAddIcon}
                    className='ml-2 h-auto shrink-0 px-2 py-0 text-[14px] leading-[16px]'
                  >
                    {isFollowing ? t('profile.following') : t('profile.follow')}
                  </Button>
                )}
              </div>
            ) : null}
          </div>
        </div>
        <div className='flex flex-row items-center gap-2'>
          {children}
          {onAddToPlaylist ? (
            <div>
              <Button
                className='px-5 font-mono text-[12px] leading-[24px] font-medium uppercase'
                variant={ButtonVariant.LightGlass}
                size={ButtonSize.Medium}
                shape={ButtonShape.Pill}
                icon={PlusIcon}
                onClick={handleAddToPlaylistClick}
              >
                {t('songActions.save')}
              </Button>
            </div>
          ) : null}
          {onRemix ? (
            <div>
              <Button
                className='px-5 font-mono text-[12px] leading-[24px] font-medium uppercase'
                variant={ButtonVariant.LightGlass}
                size={ButtonSize.Medium}
                shape={ButtonShape.Pill}
                onClick={handleRemixClick}
                disabled={isRemixDisabled}
              >
                {t('songActions.remix')}
              </Button>
            </div>
          ) : null}
        </div>
      </div>
    </div>
  );
});
HookSongBar.displayName = 'HookSongBar';

export default HookSongBar;
