import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ChatMessages } from './ChatMessages';
import type { ChatMessage, Conversation } from '../store/chatStore';

const mockUseChatStore = vi.fn();
vi.mock('../store/chatStore', () => ({
  useChatStore: (...args: unknown[]) => mockUseChatStore(...args),
}));

const CONV_ID = 'conv-123';

const mockMessages: ChatMessage[] = [
  {
    id: '1',
    conversation_id: CONV_ID,
    sender_id: 'user-1',
    sender_username: 'user1',
    content: 'Hello, world!',
    created_at: '2024-01-01T10:00:00Z',
  },
  {
    id: '2',
    conversation_id: CONV_ID,
    sender_id: 'user-2',
    sender_username: 'user2',
    content: 'How are you?',
    created_at: '2024-01-01T10:01:00Z',
  },
];

const mockConversation: Conversation = {
  id: CONV_ID,
  name: 'Test Room',
  type: 'public',
  participants: ['user-1', 'user-2'],
  unread_count: 0,
};


vi.mock('@/features/auth/hooks/useUser', () => ({
  useUser: () => ({
    data: { id: 'user-1', username: 'user1' },
  }),
}));

const createTestQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

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

describe('ChatMessages Component', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    Element.prototype.scrollIntoView = vi.fn();
    mockUseChatStore.mockReturnValue({
      currentConversationId: CONV_ID,
      conversations: [mockConversation],
      messages: { [CONV_ID]: mockMessages },
      typingUsers: {},
    });
  });

  it('renders messages correctly', () => {
    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText('Hello, world!')).toBeInTheDocument();
    expect(screen.getByText('How are you?')).toBeInTheDocument();
    // Current user (user-1) shows "Vous", others show "Utilisateur {sender_id}"
    expect(screen.getByText('Vous')).toBeInTheDocument();
    expect(screen.getByText(/Utilisateur user-2/)).toBeInTheDocument();
  });

  it('displays message timestamps', () => {
    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    // Locale may format as 10:00 or 11:00 AM - multiple messages have timestamps
    const timestamps = screen.getAllByText(/\d{1,2}:\d{2}/);
    expect(timestamps.length).toBeGreaterThanOrEqual(1);
  });

  it('shows empty state when no messages', () => {
    mockUseChatStore.mockReturnValue({
      currentConversationId: CONV_ID,
      conversations: [mockConversation],
      messages: { [CONV_ID]: [] },
      typingUsers: {},
    });

    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText(/Aucun message dans cette conversation/)).toBeInTheDocument();
  });

  it('shows select conversation when no current conversation', () => {
    mockUseChatStore.mockReturnValue({
      currentConversationId: null,
      conversations: [],
      messages: {},
      typingUsers: {},
    });

    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText(/Sélectionnez une conversation/)).toBeInTheDocument();
  });

  it('displays conversation header with participant count', () => {
    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText('Test Room')).toBeInTheDocument();
    expect(screen.getByText(/2 participant/)).toBeInTheDocument();
  });

  it('shows typing indicator when typingUsers present', () => {
    mockUseChatStore.mockReturnValue({
      currentConversationId: CONV_ID,
      conversations: [mockConversation],
      messages: { [CONV_ID]: mockMessages },
      typingUsers: { [CONV_ID]: ['user-2'] },
    });

    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText(/est en train d'écrire/)).toBeInTheDocument();
  });

  it('scrolls to bottom when messages change', async () => {
    const scrollIntoViewMock = vi.fn();
    Element.prototype.scrollIntoView = scrollIntoViewMock;

    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    await waitFor(() => {
      expect(scrollIntoViewMock).toHaveBeenCalled();
    });
  });

  it('displays message reactions when present', () => {
    const msgsWithReactions: ChatMessage[] = [
      {
        ...mockMessages[0],
        reactions: { '👍': ['user-1'], '❤️': ['user-2'] },
      },
    ];

    mockUseChatStore.mockReturnValue({
      currentConversationId: CONV_ID,
      conversations: [mockConversation],
      messages: { [CONV_ID]: msgsWithReactions },
      typingUsers: {},
    });

    render(
      <TestWrapper>
        <ChatMessages />
      </TestWrapper>,
    );

    expect(screen.getByText(/👍 1/)).toBeInTheDocument();
    expect(screen.getByText(/❤️ 1/)).toBeInTheDocument();
  });
});
