/**
 * Tests pour PlaylistTrackItem
 * T0473: Create Playlist Track List Component
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { PlaylistTrackItem } from './PlaylistTrackItem';
import type { PlaylistTrack } from '../types';
import type { Track } from '@/features/tracks/types/track';

// Mock RemoveTrackButton
vi.mock('./RemoveTrackButton', () => ({
  RemoveTrackButton: ({ trackTitle, onRemoved }: any) => (
    <button onClick={onRemoved} data-testid="remove-button">
      Remove {trackTitle}
    </button>
  ),
}));

function createWrapper() {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

  return ({ children }: { children: React.ReactNode }) => (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
}

const mockPlaylistTrack: PlaylistTrack = {
  id: 1,
  playlist_id: 1,
  track_id: 10,
  position: 1,
  added_at: '2024-01-01T00:00:00Z',
};

const mockTrack: Track = {
  id: 10,
  user_id: 1,
  title: 'Test Track',
  artist: 'Test Artist',
  album: 'Test Album',
  duration: 180,
  file_path: '/tracks/10.mp3',
  file_size: 5000000,
  format: 'MP3',
  is_public: true,
  play_count: 0,
  like_count: 0,
  created_at: '2024-01-01T00:00:00Z',
  updated_at: '2024-01-01T00:00:00Z',
};

describe('PlaylistTrackItem', () => {
  const mockOnTrackClick = vi.fn();
  const mockOnTrackPlay = vi.fn();
  const mockOnTrackRemoved = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should render track information', () => {
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
      />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('Test Track')).toBeInTheDocument();
    expect(screen.getByText(/Test Artist/)).toBeInTheDocument();
    expect(screen.getByText('1')).toBeInTheDocument(); // Position
    expect(screen.getByText('3:00')).toBeInTheDocument(); // Duration
  });

  it('should display position number', () => {
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={5}
      />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('5')).toBeInTheDocument();
  });

  it('should call onTrackClick when item is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        onTrackClick={mockOnTrackClick}
      />,
      { wrapper: createWrapper() },
    );

    const item = screen.getByRole('listitem');
    await user.click(item);

    expect(mockOnTrackClick).toHaveBeenCalledWith(mockTrack);
  });

  it('should show play button on hover', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        onTrackPlay={mockOnTrackPlay}
      />,
      { wrapper: createWrapper() },
    );

    const item = screen.getByRole('listitem');
    await user.hover(item);

    // Le bouton play devrait apparaître à la place du numéro
    const playButton = screen.getByLabelText(/lire/i);
    expect(playButton).toBeInTheDocument();
  });

  it('should call onTrackPlay when play button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        onTrackPlay={mockOnTrackPlay}
      />,
      { wrapper: createWrapper() },
    );

    const item = screen.getByRole('listitem');
    await user.hover(item);

    const playButton = screen.getByLabelText(/lire/i);
    await user.click(playButton);

    expect(mockOnTrackPlay).toHaveBeenCalledWith(mockTrack);
  });

  it('should show pause button when track is playing', () => {
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        isPlaying={true}
        onTrackPlay={mockOnTrackPlay}
      />,
      { wrapper: createWrapper() },
    );

    const pauseButton = screen.getByLabelText(/mettre en pause/i);
    expect(pauseButton).toBeInTheDocument();
  });

  it('should show remove button on hover', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        onTrackRemoved={mockOnTrackRemoved}
      />,
      { wrapper: createWrapper() },
    );

    const item = screen.getByRole('listitem');
    await user.hover(item);

    const removeButton = screen.getByTestId('remove-button');
    expect(removeButton).toBeInTheDocument();
  });

  it('should call onTrackRemoved when remove button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={mockTrack}
        playlistId={1}
        position={1}
        onTrackRemoved={mockOnTrackRemoved}
      />,
      { wrapper: createWrapper() },
    );

    const item = screen.getByRole('listitem');
    await user.hover(item);

    const removeButton = screen.getByTestId('remove-button');
    await user.click(removeButton);

    expect(mockOnTrackRemoved).toHaveBeenCalled();
  });

  it('should format duration correctly', () => {
    const longTrack: Track = {
      ...mockTrack,
      duration: 3661, // 1h 1m 1s
    };

    render(
      <PlaylistTrackItem
        playlistTrack={mockPlaylistTrack}
        track={longTrack}
        playlistId={1}
        position={1}
      />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('61:01')).toBeInTheDocument();
  });
});
