import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { MemoryRouter } from 'react-router';
import type { ReactNode } from 'react';
import { useEnvironmentStore } from '../api/environment-store';

vi.mock('../api/client', () => ({ api: { GET: vi.fn() } }));

import { api as apiClient } from '../api/client';
import { NotificationBell } from './NotificationBell';

function wrapper({ children }: { children: ReactNode }) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return (
    <QueryClientProvider client={qc}>
      <MemoryRouter>{children}</MemoryRouter>
    </QueryClientProvider>
  );
}

function mockResponse(total: number, bySeverity: Record<string, number> = {}) {
  (apiClient.GET as any).mockResolvedValue({
    data: { total, bySeverity },
    error: null,
  });
}

describe('NotificationBell', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    useEnvironmentStore.setState({ environment: 'dev' });
  });

  it('renders bell with no badge when zero unread', async () => {
    mockResponse(0, { CRITICAL: 0, WARNING: 0, INFO: 0 });
    render(<NotificationBell />, { wrapper });
    expect(await screen.findByRole('button', { name: /notifications/i })).toBeInTheDocument();
    expect(screen.queryByText(/^\d+$/)).toBeNull();
  });

  it('shows unread total in badge', async () => {
    mockResponse(3, { CRITICAL: 1, WARNING: 2, INFO: 0 });
    render(<NotificationBell />, { wrapper });
    expect(await screen.findByText('3')).toBeInTheDocument();
  });

  it('colours badge as CRITICAL when any critical unread present', async () => {
    mockResponse(5, { CRITICAL: 1, WARNING: 4, INFO: 0 });
    render(<NotificationBell />, { wrapper });
    const badge = await screen.findByText('5');
    expect(badge.className).toMatch(/badgeCritical/);
  });

  it('colours badge as WARNING when only warnings+info unread', async () => {
    mockResponse(3, { CRITICAL: 0, WARNING: 2, INFO: 1 });
    render(<NotificationBell />, { wrapper });
    const badge = await screen.findByText('3');
    expect(badge.className).toMatch(/badgeWarning/);
    expect(badge.className).not.toMatch(/badgeCritical/);
  });

  it('colours badge as INFO when only info unread', async () => {
    mockResponse(2, { CRITICAL: 0, WARNING: 0, INFO: 2 });
    render(<NotificationBell />, { wrapper });
    const badge = await screen.findByText('2');
    expect(badge.className).toMatch(/badgeInfo/);
  });
});
