import { useState, useEffect } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Button } from '@/components/ui/button';
import { Heart, Loader2 } from 'lucide-react';
import { cn } from '@/lib/utils';
import {
  likeTrack,
  unlikeTrack,
  getTrackLikes,
} from '../services/interactionService';
import { useToast } from '@/hooks/useToast';
import { useUser } from '@/features/auth/hooks/useUser';
import { useIsRateLimited } from '@/hooks/useIsRateLimited';

/**
 * FE-COMP-016: Like/Unlike button component for tracks with count display
 */

interface LikeButtonProps {
  trackId: string;
  initialLikeCount?: number;
  initialIsLiked?: boolean;
  onLikeChange?: (isLiked: boolean, count: number) => void;
  className?: string;
  size?: 'default' | 'sm' | 'lg' | 'icon';
  variant?: 'default' | 'outline' | 'ghost';
  showCount?: boolean;
  compact?: boolean;
}

export function LikeButton({
  trackId,
  initialLikeCount,
  initialIsLiked = false,
  onLikeChange,
  className,
  size = 'default',
  variant = 'ghost',
  showCount = true,
  compact = false,
}: LikeButtonProps) {
  const { data: user } = useUser();
  const { success: showSuccess, error: showError } = useToast();
  const queryClient = useQueryClient();
  const isRateLimited = useIsRateLimited();
  const [isLiked, setIsLiked] = useState(initialIsLiked);
  const [likeCount, setLikeCount] = useState(initialLikeCount ?? 0);
  const [isUpdating, setIsUpdating] = useState(false);
  const [animating, setAnimating] = useState(false);

  // Fetch like status from API
  const { data: likesData } = useQuery({
    queryKey: ['trackLikes', trackId],
    queryFn: () => getTrackLikes(trackId),
    enabled: !!trackId && !!user,
    staleTime: 30000, // 30 seconds
    retry: false,
  });

  // Update state from API response
  useEffect(() => {
    if (likesData) {
      setIsLiked(likesData.isLiked);
      setLikeCount(likesData.count);
    } else if (initialIsLiked !== undefined) {
      setIsLiked(initialIsLiked);
    }
    if (initialLikeCount !== undefined) {
      setLikeCount(initialLikeCount);
    }
  }, [likesData, initialIsLiked, initialLikeCount]);

  // Like mutation
  const likeMutation = useMutation({
    mutationFn: () => likeTrack(trackId),
    onMutate: async () => {
      // Optimistic update
      setIsLiked(true);
      setLikeCount((prev) => prev + 1);
      setIsUpdating(true);
    },
    onSuccess: () => {
      showSuccess('Ajouté aux favoris');
      onLikeChange?.(true, likeCount + 1);
      // Invalidate queries to refresh data
      queryClient.invalidateQueries({ queryKey: ['trackLikes', trackId] });
      queryClient.invalidateQueries({ queryKey: ['tracks'] });
    },
    onError: (error: any) => {
      // Revert optimistic update
      setIsLiked(false);
      setLikeCount((prev) => Math.max(0, prev - 1));
      const errorMessage =
        error.response?.data?.error?.message ||
        error.response?.data?.message ||
        error.message ||
        "Erreur lors de l'ajout aux favoris";
      showError(errorMessage);
    },
    onSettled: () => {
      setIsUpdating(false);
    },
  });

  // Unlike mutation
  const unlikeMutation = useMutation({
    mutationFn: () => unlikeTrack(trackId),
    onMutate: async () => {
      // Optimistic update
      setIsLiked(false);
      setLikeCount((prev) => Math.max(0, prev - 1));
      setIsUpdating(true);
    },
    onSuccess: () => {
      showSuccess('Retiré des favoris');
      onLikeChange?.(false, Math.max(0, likeCount - 1));
      // Invalidate queries to refresh data
      queryClient.invalidateQueries({ queryKey: ['trackLikes', trackId] });
      queryClient.invalidateQueries({ queryKey: ['tracks'] });
    },
    onError: (error: any) => {
      // Revert optimistic update
      setIsLiked(true);
      setLikeCount((prev) => prev + 1);
      const errorMessage =
        error.response?.data?.error?.message ||
        error.response?.data?.message ||
        error.message ||
        'Erreur lors du retrait des favoris';
      showError(errorMessage);
    },
    onSettled: () => {
      setIsUpdating(false);
    },
  });

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    if (isUpdating || !user || isRateLimited) return;

    // Trigger bounce animation on like (not unlike)
    if (!isLiked) {
      setAnimating(true);
      setTimeout(() => setAnimating(false), 400);
    }

    if (isLiked) {
      unlikeMutation.mutate();
    } else {
      likeMutation.mutate();
    }
  };

  // Don't show button if user is not logged in
  if (!user) {
    return null;
  }

  const isLoading =
    likeMutation.isPending || unlikeMutation.isPending || isUpdating;

  return (
    <Button
      onClick={handleClick}
      disabled={isLoading || isRateLimited}
      variant={variant}
      size={size}
      className={cn(
        'rounded-md transition-[color,transform] duration-[var(--sumi-duration-normal)]',
        className,
        isLiked && 'text-destructive hover:text-destructive/90',
        compact && 'h-auto p-1',
      )}
      aria-label={isLiked ? 'Retirer des favoris' : 'Ajouter aux favoris'}
      aria-pressed={isLiked}
    >
      {isLoading ? (
        <>
          <Loader2
            className={cn('h-4 w-4 animate-spin', showCount && 'mr-2')}
          />
          {!compact && showCount && (
            <span className="tabular-nums tracking-tight">{likeCount}</span>
          )}
        </>
      ) : (
        <>
          <Heart
            className={cn(
              'h-4 w-4 transition-colors duration-[var(--sumi-duration-normal)]',
              animating && 'animate-like-bounce drop-shadow-[0_0_8px_var(--sumi-vermillion)]',
              isLiked && 'fill-current',
              showCount && 'mr-2',
            )}
            aria-hidden="true"
          />
          {showCount && (
            <span
              className={cn(
                'tabular-nums tracking-tight',
                compact && 'text-xs',
              )}
            >
              {likeCount > 0 ? likeCount : ''}
            </span>
          )}
        </>
      )}
    </Button>
  );
}
