import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { I18nextProvider } from 'react-i18next';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import '@testing-library/jest-dom';
import { useNotificationRealtime } from '@/features/notifications/hooks/useNotificationRealtime';
import { unreadCountQueryKey } from '@/features/notifications/hooks/useUnreadCount';
import { useAuthStore } from '@/features/auth/store/authStore';
import { realtimeEvents } from '@/shared/realtime/realtimeChannels';
import i18n from '@/locales/i18n';
import { LocaleProvider } from '@/app/providers/LocaleProvider';

const listenHandlers: Record<string, (payload: unknown) => void> = {};
const mockChannel = {
  listen: vi.fn((event: string, handler: (payload: unknown) => void) => {
    listenHandlers[event] = handler;
  }),
  stopListening: vi.fn(),
};

const mockEcho = {
  private: vi.fn(() => mockChannel),
  leave: vi.fn(),
  disconnect: vi.fn(),
};

vi.mock('@/shared/realtime/echoClient', () => ({
  getEcho: () => mockEcho,
  isRealtimeEnabled: () => true,
  leaveChannel: vi.fn(),
}));

vi.mock('react-hot-toast', () => ({
  default: vi.fn(),
}));

function TestHarness() {
  useNotificationRealtime();
  return null;
}

function renderHarness(queryClient: QueryClient) {
  return render(
    <QueryClientProvider client={queryClient}>
      <I18nextProvider i18n={i18n}>
        <LocaleProvider>
          <TestHarness />
        </LocaleProvider>
      </I18nextProvider>
    </QueryClientProvider>,
  );
}

describe('useNotificationRealtime', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    Object.keys(listenHandlers).forEach((key) => delete listenHandlers[key]);
    useAuthStore.setState({
      user: {
        id: 'user-1',
        name: 'Agent',
        email: 'agent@test.com',
        locale: 'en',
        company_id: 'co-1',
        company: {
          id: 'co-1',
          name: 'ACME',
          domain: 'acme.test',
          is_active: true,
          created_at: '',
          updated_at: '',
        },
        departments: [],
        roles: [],
        permissions: [],
        is_active: true,
        created_at: '',
        updated_at: '',
      },
      token: 'token',
      isAuthenticated: true,
      isLoading: false,
    });
  });

  it('registers echo listener for user notifications', async () => {
    const queryClient = new QueryClient();
    const { unmount } = renderHarness(queryClient);

    await waitFor(() => {
      expect(mockEcho.private).toHaveBeenCalledWith('user.user-1');
    });

    expect(mockChannel.listen).toHaveBeenCalledWith(
      realtimeEvents.notificationReceived,
      expect.any(Function),
    );

    unmount();
    expect(mockChannel.stopListening).toHaveBeenCalledWith(realtimeEvents.notificationReceived);
    expect(mockEcho.leave).toHaveBeenCalledWith('user.user-1');
  });

  it('updates unread count cache when notification is received', async () => {
    const queryClient = new QueryClient();
    queryClient.setQueryData(unreadCountQueryKey, 2);

    renderHarness(queryClient);

    await waitFor(() => {
      expect(listenHandlers[realtimeEvents.notificationReceived]).toBeDefined();
    });

    listenHandlers[realtimeEvents.notificationReceived]({
      id: 'n-1',
      title: 'New ticket',
      message: 'Ticket created',
    });

    expect(queryClient.getQueryData(unreadCountQueryKey)).toBe(3);
  });
});
