/**
 * Tests pour PlaylistDetailPage
 * T0460: Create Playlist Detail Page
 * T0475: Create Playlist Track Management Integration
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router-dom';
import { PlaylistDetailPage } from './PlaylistDetailPage';
import { usePlaylist, useCollaborators } from '../hooks/usePlaylist';
import { usePlaylistPermissions } from '../hooks/usePlaylistPermissions';
import type { Playlist } from '../types';
import type { Track } from '@/features/tracks/types/track';

// Mock usePlaylist hook
vi.mock('../hooks/usePlaylist', () => ({
  usePlaylist: vi.fn(),
  useCollaborators: vi.fn(),
}));

// Mock usePlaylistPermissions hook
vi.mock('../hooks/usePlaylistPermissions', () => ({
  usePlaylistPermissions: vi.fn(),
}));

// Mock player store
const mockPlay = vi.fn();
vi.mock('@/features/player/store/playerStore', () => ({
  usePlayerStore: vi.fn(() => ({
    play: mockPlay,
    currentTrack: null,
    isPlaying: false,
  })),
}));

// Mock PlaylistTrackList
vi.mock('../components/PlaylistTrackList', () => ({
  PlaylistTrackList: ({ tracks, onTrackPlay, onTrackRemoved }: any) => (
    <div data-testid="playlist-track-list">
      {tracks.map((track: Track) => (
        <div key={track.id} data-testid={`track-${track.id}`}>
          {track.title}
          <button onClick={() => onTrackPlay?.(track)}>Play</button>
          <button onClick={() => onTrackRemoved?.()}>Remove</button>
        </div>
      ))}
    </div>
  ),
}));

// Mock AddTrackToPlaylistModal
const mockOnClose = vi.fn();
const mockOnTrackAdded = vi.fn();
vi.mock('../components/AddTrackToPlaylistModal', () => ({
  AddTrackToPlaylistModal: ({ open, onClose, onTrackAdded }: any) => {
    if (open) {
      return (
        <div data-testid="add-track-modal">
          <button onClick={onClose}>Close</button>
          <button onClick={onTrackAdded}>Add Track</button>
        </div>
      );
    }
    return null;
  },
}));

// Mock PlaylistHeader
vi.mock('../components/PlaylistHeader', () => ({
  PlaylistHeader: ({ playlist }: any) => (
    <div data-testid="playlist-header">{playlist.title}</div>
  ),
}));

// Mock PlaylistActions
vi.mock('../components/PlaylistActions', () => ({
  PlaylistActions: ({ onShareClick }: any) => (
    <div data-testid="playlist-actions">
      Actions
      {onShareClick && <button onClick={onShareClick}>Share</button>}
    </div>
  ),
}));

// Mock SharePlaylistModal
vi.mock('../components/SharePlaylistModal', () => ({
  SharePlaylistModal: ({ open, onClose }: any) => {
    if (open) {
      return (
        <div data-testid="share-playlist-modal">
          <button onClick={onClose}>Close Share</button>
        </div>
      );
    }
    return null;
  },
}));

// Mock CollaboratorList
vi.mock('../components/CollaboratorList', () => ({
  CollaboratorList: ({ collaborators }: any) => (
    <div data-testid="collaborator-list">
      {collaborators.map((c: any) => (
        <div key={c.id}>{c.user?.username || 'Collaborator'}</div>
      ))}
    </div>
  ),
}));

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

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

const mockTrack: Track = {
  id: 1,
  user_id: 1,
  title: 'Test Track',
  artist: 'Test Artist',
  duration: 180,
  file_path: '/tracks/1.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',
};

const mockPlaylist: Playlist = {
  id: 1,
  user_id: 1,
  title: 'Test Playlist',
  description: 'Test Description',
  is_public: true,
  track_count: 1,
  created_at: '2024-01-01T00:00:00Z',
  updated_at: '2024-01-01T00:00:00Z',
  tracks: [
    {
      id: 1,
      playlist_id: 1,
      track_id: 1,
      position: 1,
      added_at: '2024-01-01T00:00:00Z',
      track: mockTrack,
    },
  ],
};

describe('PlaylistDetailPage', () => {
  const mockRefetch = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(usePlaylist).mockReturnValue({
      data: mockPlaylist,
      isLoading: false,
      error: null,
      refetch: mockRefetch,
    } as any);

    vi.mocked(useCollaborators).mockReturnValue({
      data: [],
      isLoading: false,
      isError: false,
      error: null,
      refetch: vi.fn(),
    } as any);

    vi.mocked(usePlaylistPermissions).mockReturnValue({
      canEdit: true,
      canDelete: true,
      canAddTracks: true,
      canRemoveTracks: true,
      canManageCollaborators: true,
      canRead: true,
      isOwner: true,
    });
  });

  it('should render playlist header', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByTestId('playlist-header')).toBeInTheDocument();
    expect(screen.getByText('Test Playlist')).toBeInTheDocument();
  });

  it('should render playlist actions', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByTestId('playlist-actions')).toBeInTheDocument();
  });

  it('should render tracks list', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByTestId('playlist-track-list')).toBeInTheDocument();
    expect(screen.getByText('Test Track')).toBeInTheDocument();
  });

  it('should show add track button', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByText('Ajouter des tracks')).toBeInTheDocument();
  });

  it('should open add track modal when button is clicked', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const addButton = screen.getByText('Ajouter des tracks');
    await user.click(addButton);

    expect(screen.getByTestId('add-track-modal')).toBeInTheDocument();
  });

  it('should close add track modal when close button is clicked', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const addButton = screen.getByText('Ajouter des tracks');
    await user.click(addButton);

    expect(screen.getByTestId('add-track-modal')).toBeInTheDocument();

    const closeButton = screen.getByText('Close');
    await user.click(closeButton);

    await waitFor(() => {
      expect(screen.queryByTestId('add-track-modal')).not.toBeInTheDocument();
    });
  });

  it('should call play when track play button is clicked', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const playButton = screen.getByText('Play');
    await user.click(playButton);

    expect(mockPlay).toHaveBeenCalledWith({
      id: mockTrack.id,
      title: mockTrack.title,
      artist: mockTrack.artist,
      album: mockTrack.album,
      duration: mockTrack.duration,
      file_path: mockTrack.file_path,
      cover: mockTrack.cover_art_path,
    });
  });

  it('should refetch playlist when track is removed', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const removeButton = screen.getByText('Remove');
    await user.click(removeButton);

    expect(mockRefetch).toHaveBeenCalled();
  });

  it('should refetch playlist when track is added', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const addButton = screen.getByText('Ajouter des tracks');
    await user.click(addButton);

    const addTrackButton = screen.getByText('Add Track');
    await user.click(addTrackButton);

    expect(mockRefetch).toHaveBeenCalled();
  });

  it('should show loading state', () => {
    vi.mocked(usePlaylist).mockReturnValue({
      data: undefined,
      isLoading: true,
      error: null,
      refetch: mockRefetch,
    } as any);

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

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

  it('should show error state', () => {
    vi.mocked(usePlaylist).mockReturnValue({
      data: undefined,
      isLoading: false,
      error: new Error('Failed to load playlist'),
      refetch: mockRefetch,
    } as any);

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByText('Error loading playlist')).toBeInTheDocument();
  });

  it('should show not found state', () => {
    vi.mocked(usePlaylist).mockReturnValue({
      data: undefined,
      isLoading: false,
      error: null,
      refetch: mockRefetch,
    } as any);

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByText('Playlist not found')).toBeInTheDocument();
  });

  it('should show share button when user can manage collaborators', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

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

  it('should open share modal when share button is clicked', async () => {
    const user = userEvent.setup();
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    const shareButton = screen.getByText('Partager');
    await user.click(shareButton);

    expect(screen.getByTestId('share-playlist-modal')).toBeInTheDocument();
  });

  it('should show collaborators section when user can read', () => {
    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.getByText('Collaborateurs')).toBeInTheDocument();
    expect(screen.getByTestId('collaborator-list')).toBeInTheDocument();
  });

  it('should not show add track button when user cannot add tracks', () => {
    vi.mocked(usePlaylistPermissions).mockReturnValue({
      canEdit: false,
      canDelete: false,
      canAddTracks: false,
      canRemoveTracks: false,
      canManageCollaborators: false,
      canRead: true,
      isOwner: false,
    });

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.queryByText('Ajouter des tracks')).not.toBeInTheDocument();
  });

  it('should not show collaborators section when user cannot read', () => {
    vi.mocked(usePlaylistPermissions).mockReturnValue({
      canEdit: false,
      canDelete: false,
      canAddTracks: false,
      canRemoveTracks: false,
      canManageCollaborators: false,
      canRead: false,
      isOwner: false,
    });

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    expect(screen.queryByText('Collaborateurs')).not.toBeInTheDocument();
  });

  it('should not show share button when user cannot manage collaborators', () => {
    vi.mocked(usePlaylistPermissions).mockReturnValue({
      canEdit: false,
      canDelete: false,
      canAddTracks: false,
      canRemoveTracks: false,
      canManageCollaborators: false,
      canRead: true,
      isOwner: false,
    });

    render(<PlaylistDetailPage />, { wrapper: createWrapper() });

    // Le bouton share dans la section collaborateurs ne devrait pas être visible
    const shareButtons = screen.queryAllByText('Partager');
    expect(shareButtons.length).toBe(0);
  });
});
