import { describe, it, expect, vi, beforeEach } from 'vitest';

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

import {
  getNotifications,
  getUnreadCount,
  markNotificationRead,
  markAllNotificationsRead,
  clearAllNotifications,
} from '../notifications';
import apiClient from '../client';

describe('notifications API', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('getNotifications', () => {
    it('fetches all notifications without params', async () => {
      const mockNotifications = [
        { id: 1, verb: 'created', read: false, timestamp: '2024-01-01T00:00:00Z' },
        { id: 2, verb: 'updated', read: true, timestamp: '2024-01-02T00:00:00Z' },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockNotifications });

      const result = await getNotifications();

      expect(apiClient.get).toHaveBeenCalledWith('/notifications/');
      expect(result).toEqual(mockNotifications);
    });

    it('applies read filter', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      await getNotifications({ read: false });

      expect(apiClient.get).toHaveBeenCalledWith('/notifications/?read=false');
    });

    it('applies limit parameter', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      await getNotifications({ limit: 10 });

      expect(apiClient.get).toHaveBeenCalledWith('/notifications/?limit=10');
    });

    it('applies multiple parameters', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      await getNotifications({ read: true, limit: 5 });

      expect(apiClient.get).toHaveBeenCalledWith('/notifications/?read=true&limit=5');
    });
  });

  describe('getUnreadCount', () => {
    it('returns unread count', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: { count: 5 } });

      const result = await getUnreadCount();

      expect(apiClient.get).toHaveBeenCalledWith('/notifications/unread_count/');
      expect(result).toBe(5);
    });

    it('returns 0 when no unread notifications', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: { count: 0 } });

      const result = await getUnreadCount();

      expect(result).toBe(0);
    });
  });

  describe('markNotificationRead', () => {
    it('marks single notification as read', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({});

      await markNotificationRead(42);

      expect(apiClient.post).toHaveBeenCalledWith('/notifications/42/mark_read/');
    });
  });

  describe('markAllNotificationsRead', () => {
    it('marks all notifications as read', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({});

      await markAllNotificationsRead();

      expect(apiClient.post).toHaveBeenCalledWith('/notifications/mark_all_read/');
    });
  });

  describe('clearAllNotifications', () => {
    it('clears all read notifications', async () => {
      vi.mocked(apiClient.delete).mockResolvedValue({});

      await clearAllNotifications();

      expect(apiClient.delete).toHaveBeenCalledWith('/notifications/clear_all/');
    });
  });
});
