/**
 * Tests pour CollaboratorList
 * T0483: Create Playlist Share Modal Component
 */

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 { CollaboratorList } from './CollaboratorList';
import * as playlistHooks from '../hooks/usePlaylist';
import type { PlaylistCollaborator } from '../services/playlistService';

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

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

// Mock window.confirm
const mockConfirm = vi.fn();
window.confirm = mockConfirm;

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

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

const mockCollaborators: PlaylistCollaborator[] = [
  {
    id: 1,
    playlist_id: 1,
    user_id: 2,
    permission: 'read',
    created_at: '2024-01-01T00:00:00Z',
    updated_at: '2024-01-01T00:00:00Z',
    user: {
      id: 2,
      username: 'collaborator1',
      email: 'collaborator1@example.com',
    },
  },
  {
    id: 2,
    playlist_id: 1,
    user_id: 3,
    permission: 'write',
    created_at: '2024-01-01T00:00:00Z',
    updated_at: '2024-01-01T00:00:00Z',
    user: {
      id: 3,
      username: 'collaborator2',
      email: 'collaborator2@example.com',
    },
  },
];

describe('CollaboratorList', () => {
  const mockRemoveMutateAsync = vi.fn();
  const mockUpdateMutateAsync = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    mockConfirm.mockReturnValue(true);

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

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

  it('should render empty state when no collaborators', () => {
    render(<CollaboratorList collaborators={[]} playlistId={1} />, {
      wrapper: createWrapper(),
    });

    expect(
      screen.getByText('Aucun collaborateur pour le moment'),
    ).toBeInTheDocument();
  });

  it('should render collaborators list', () => {
    render(
      <CollaboratorList collaborators={mockCollaborators} playlistId={1} />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('collaborator1')).toBeInTheDocument();
    expect(screen.getByText('collaborator2')).toBeInTheDocument();
  });

  it('should display permission for each collaborator when canManage is false', () => {
    render(
      <CollaboratorList
        collaborators={mockCollaborators}
        playlistId={1}
        canManage={false}
      />,
      { wrapper: createWrapper() },
    );

    expect(screen.getByText('Lecture')).toBeInTheDocument();
    expect(screen.getByText('Écriture')).toBeInTheDocument();
  });

  it('should display permission select when canManage is true', () => {
    render(
      <CollaboratorList
        collaborators={mockCollaborators}
        playlistId={1}
        canManage={true}
      />,
      { wrapper: createWrapper() },
    );

    // Le Select devrait être présent (mais difficile à tester sans accès au DOM interne)
    expect(screen.getByText('collaborator1')).toBeInTheDocument();
  });

  it('should call remove mutation when remove button is clicked', async () => {
    const user = userEvent.setup();
    mockRemoveMutateAsync.mockResolvedValue(undefined);

    // Utiliser un seul collaborateur pour simplifier le test
    const singleCollaborator = [mockCollaborators[0]];

    render(
      <CollaboratorList
        collaborators={singleCollaborator}
        playlistId={1}
        canManage={true}
      />,
      { wrapper: createWrapper() },
    );

    // Trouver tous les boutons - il devrait y avoir un Select et un bouton de suppression
    const buttons = screen.getAllByRole('button');
    expect(buttons.length).toBeGreaterThanOrEqual(2);

    // Le dernier bouton devrait être le bouton de suppression
    const removeButton = buttons[buttons.length - 1];
    await user.click(removeButton);

    await waitFor(() => {
      expect(mockConfirm).toHaveBeenCalled();
    });

    await waitFor(() => {
      expect(mockRemoveMutateAsync).toHaveBeenCalled();
      const callArgs = mockRemoveMutateAsync.mock.calls[0][0];
      expect(callArgs.playlistId).toBe(1);
      expect(callArgs.userId).toBe(2); // Le premier collaborateur a user_id: 2
    });
  });

  it('should not call remove mutation when confirm is cancelled', async () => {
    const user = userEvent.setup();
    mockConfirm.mockReturnValue(false);

    render(
      <CollaboratorList
        collaborators={mockCollaborators}
        playlistId={1}
        canManage={true}
      />,
      { wrapper: createWrapper() },
    );

    const removeButtons = screen.getAllByRole('button');
    const removeButton = removeButtons[removeButtons.length - 1];

    await user.click(removeButton);

    await waitFor(() => {
      expect(mockConfirm).toHaveBeenCalled();
    });
    expect(mockRemoveMutateAsync).not.toHaveBeenCalled();
  });
});
