/**
 * Tests pour PlaylistActions
 * T0486: Create Playlist Collaboration UI 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 { PlaylistActions } from './PlaylistActions';
import { useUpdatePlaylist, useDeletePlaylist } from '../hooks/usePlaylist';
import { usePlaylistPermissions } from '../hooks/usePlaylistPermissions';
import type { Playlist } from '../types';

// Mock des hooks
vi.mock('../hooks/usePlaylist', () => ({
  useUpdatePlaylist: vi.fn(),
  useDeletePlaylist: vi.fn(),
}));

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

vi.mock('@/hooks/useToast', () => ({
  useToast: () => ({
    toast: vi.fn(),
  }),
}));

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 mockPlaylist: Playlist = {
  id: 1,
  user_id: 1,
  title: 'Test Playlist',
  description: 'Test Description',
  is_public: true,
  cover_url: null,
  track_count: 0,
  created_at: '2024-01-01T00:00:00Z',
  updated_at: '2024-01-01T00:00:00Z',
  tracks: [],
};

describe('PlaylistActions', () => {
  const mockUpdateMutateAsync = vi.fn();
  const mockDeleteMutateAsync = vi.fn();
  const mockOnUpdated = vi.fn();
  const mockOnShareClick = vi.fn();

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

    vi.mocked(useUpdatePlaylist).mockReturnValue({
      mutateAsync: mockUpdateMutateAsync,
      isPending: false,
      isSuccess: false,
      isError: false,
      error: null,
      data: undefined,
      reset: vi.fn(),
      mutate: vi.fn(),
      status: 'idle',
    } as any);

    vi.mocked(useDeletePlaylist).mockReturnValue({
      mutateAsync: mockDeleteMutateAsync,
      isPending: false,
      isSuccess: false,
      isError: false,
      error: null,
      data: undefined,
      reset: vi.fn(),
      mutate: vi.fn(),
      status: 'idle',
    } as any);

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

  it('should render edit and delete buttons when user has permissions', () => {
    render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('Modifier')).toBeInTheDocument();
    expect(screen.getByText('Supprimer')).toBeInTheDocument();
  });

  it('should render share button when canShare is true and onShareClick is provided', () => {
    render(
      <PlaylistActions
        playlist={mockPlaylist}
        onUpdated={mockOnUpdated}
        onShareClick={mockOnShareClick}
        canShare={true}
      />,
      { wrapper: createWrapper() },
    );

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

  it('should not render share button when canShare is false', () => {
    render(
      <PlaylistActions
        playlist={mockPlaylist}
        onUpdated={mockOnUpdated}
        onShareClick={mockOnShareClick}
        canShare={false}
      />,
      { wrapper: createWrapper() },
    );

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

  it('should call onShareClick when share button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistActions
        playlist={mockPlaylist}
        onUpdated={mockOnUpdated}
        onShareClick={mockOnShareClick}
        canShare={true}
      />,
      { wrapper: createWrapper() },
    );

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

    expect(mockOnShareClick).toHaveBeenCalledTimes(1);
  });

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

    render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    expect(screen.queryByText('Modifier')).not.toBeInTheDocument();
    expect(screen.getByText('Supprimer')).toBeInTheDocument();
  });

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

    render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('Modifier')).toBeInTheDocument();
    expect(screen.queryByText('Supprimer')).not.toBeInTheDocument();
  });

  it('should return null when user has no permissions', () => {
    vi.mocked(usePlaylistPermissions).mockReturnValue({
      canEdit: false,
      canDelete: false,
      canAddTracks: false,
      canRemoveTracks: false,
      canManageCollaborators: false,
      canRead: false,
      isOwner: false,
    });

    const { container } = render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    expect(container.firstChild).toBeNull();
  });

  it('should open edit dialog when edit button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    const editButton = screen.getByText('Modifier');
    await user.click(editButton);

    expect(screen.getByText('Modifier la playlist')).toBeInTheDocument();
  });

  it('should open delete dialog when delete button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <PlaylistActions playlist={mockPlaylist} onUpdated={mockOnUpdated} />,
      { wrapper: createWrapper() },
    );

    const deleteButton = screen.getByText('Supprimer');
    await user.click(deleteButton);

    expect(screen.getByText('Supprimer la playlist ?')).toBeInTheDocument();
  });
});
