/**
 * Tests pour SharePlaylistModal
 * 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 { SharePlaylistModal } from './SharePlaylistModal';
import * as playlistHooks from '../hooks/usePlaylist';
import { apiClient } from '@/services/api/client';

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

// Mock CollaboratorList pour éviter les dépendances
vi.mock('./CollaboratorList', () => ({
  CollaboratorList: ({ collaborators }: { collaborators: any[] }) => (
    <div data-testid="collaborator-list">
      {collaborators.map((c) => (
        <div key={c.id}>{c.user?.username}</div>
      ))}
    </div>
  ),
}));

vi.mock('@/services/api/client', () => ({
  apiClient: {
    get: 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}>{children}</QueryClientProvider>
  );
}

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

const mockUsers = [
  {
    id: 3,
    username: 'user1',
    email: 'user1@example.com',
    avatar: undefined,
  },
  {
    id: 4,
    username: 'user2',
    email: 'user2@example.com',
    avatar: undefined,
  },
];

describe('SharePlaylistModal', () => {
  const mockMutateAsync = vi.fn();
  const mockToast = vi.fn();

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

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

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

    vi.mocked(apiClient.get).mockResolvedValue({
      data: { data: mockUsers },
    } as any);
  });

  it('should render modal when open', () => {
    render(
      <SharePlaylistModal open={true} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

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

  it('should not render modal when closed', () => {
    render(
      <SharePlaylistModal open={false} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

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

  it('should display search input', () => {
    render(
      <SharePlaylistModal open={true} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

    expect(
      screen.getByPlaceholderText(
        "Rechercher par nom d'utilisateur ou email...",
      ),
    ).toBeInTheDocument();
  });

  it('should search users when query is entered', async () => {
    const user = userEvent.setup();
    render(
      <SharePlaylistModal open={true} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

    const searchInput = screen.getByPlaceholderText(
      "Rechercher par nom d'utilisateur ou email...",
    );
    await user.type(searchInput, 'user1');

    await waitFor(
      () => {
        expect(apiClient.get).toHaveBeenCalled();
      },
      { timeout: 1000 },
    );
  });

  it('should display users after search', async () => {
    const user = userEvent.setup();
    render(
      <SharePlaylistModal open={true} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

    const searchInput = screen.getByPlaceholderText(
      "Rechercher par nom d'utilisateur ou email...",
    );
    await user.type(searchInput, 'user');

    await waitFor(() => {
      expect(screen.getByText('user1')).toBeInTheDocument();
    });
  });

  it('should display collaborators list', () => {
    render(
      <SharePlaylistModal open={true} onClose={vi.fn()} playlistId={1} />,
      { wrapper: createWrapper() },
    );

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

  it('should call onClose when close button is clicked', async () => {
    const user = userEvent.setup();
    const onClose = vi.fn();
    render(
      <SharePlaylistModal open={true} onClose={onClose} playlistId={1} />,
      { wrapper: createWrapper() },
    );

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

    expect(onClose).toHaveBeenCalled();
  });
});
