/**
 * Tests pour usePlaylistNotifications
 * T0508: Create Playlist Notifications
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { usePlaylistNotifications } from './usePlaylistNotifications';
import React from 'react';

// Mock apiClient
vi.mock('@/services/api/client', () => ({
  apiClient: {
    get: vi.fn(),
    post: vi.fn(),
  },
}));

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

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

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

describe('usePlaylistNotifications', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    queryClient.clear();
  });

  it('should fetch playlist notifications', async () => {
    const mockNotifications = [
      {
        id: 1,
        user_id: 1,
        type: 'playlist_track_added',
        title: 'Track ajouté',
        content: 'Un nouveau track a été ajouté',
        link: '/playlists/1',
        read: false,
        created_at: '2024-01-01T00:00:00Z',
      },
    ];

    const { apiClient } = await import('@/services/api/client');
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: mockNotifications,
    } as any);

    const { result } = renderHook(() => usePlaylistNotifications(), {
      wrapper,
    });

    await waitFor(() => {
      expect(result.current.notifications).toBeDefined();
    });

    expect(result.current.notifications.length).toBeGreaterThan(0);
  });

  it('should filter only playlist notifications', async () => {
    const mockNotifications = [
      {
        id: 1,
        user_id: 1,
        type: 'playlist_track_added',
        title: 'Track ajouté',
        content: 'Un nouveau track a été ajouté',
        read: false,
        created_at: '2024-01-01T00:00:00Z',
      },
      {
        id: 2,
        user_id: 1,
        type: 'other_notification',
        title: 'Other',
        content: 'Other notification',
        read: false,
        created_at: '2024-01-01T00:00:00Z',
      },
    ];

    const { apiClient } = await import('@/services/api/client');
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: mockNotifications,
    } as any);

    const { result } = renderHook(() => usePlaylistNotifications(), {
      wrapper,
    });

    await waitFor(() => {
      expect(result.current.notifications).toBeDefined();
    });

    expect(result.current.notifications.length).toBe(1);
    expect(result.current.notifications[0].type).toBe('playlist_track_added');
  });

  it('should calculate unread count correctly', async () => {
    const mockNotifications = [
      {
        id: 1,
        user_id: 1,
        type: 'playlist_track_added',
        title: 'Track ajouté',
        content: 'Un nouveau track a été ajouté',
        read: false,
        created_at: '2024-01-01T00:00:00Z',
      },
      {
        id: 2,
        user_id: 1,
        type: 'playlist_collaborator_added',
        title: 'Collaborateur ajouté',
        content: 'Vous avez été ajouté',
        read: true,
        created_at: '2024-01-01T00:00:00Z',
      },
    ];

    const { apiClient } = await import('@/services/api/client');
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: mockNotifications,
    } as any);

    const { result } = renderHook(() => usePlaylistNotifications(), {
      wrapper,
    });

    await waitFor(() => {
      expect(result.current.unreadCount).toBeDefined();
    });

    expect(result.current.unreadCount).toBe(1);
  });

  it('should mark notification as read', async () => {
    const { apiClient } = await import('@/services/api/client');
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: [],
    } as any);
    vi.mocked(apiClient.post).mockResolvedValueOnce({} as any);

    const { result } = renderHook(() => usePlaylistNotifications(), {
      wrapper,
    });

    await waitFor(() => {
      expect(result.current.markAsRead).toBeDefined();
    });

    await result.current.markAsRead(1);

    expect(apiClient.post).toHaveBeenCalledWith('/api/v1/notifications/1/read');
  });

  it('should mark all notifications as read', async () => {
    const { apiClient } = await import('@/services/api/client');
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: [],
    } as any);
    vi.mocked(apiClient.post).mockResolvedValueOnce({} as any);

    const { result } = renderHook(() => usePlaylistNotifications(), {
      wrapper,
    });

    await waitFor(() => {
      expect(result.current.markAllAsRead).toBeDefined();
    });

    await result.current.markAllAsRead();

    expect(apiClient.post).toHaveBeenCalledWith(
      '/api/v1/notifications/read-all',
    );
  });
});
