import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { vi } from 'vitest';
import LobbyScreen from './LobbyScreen';
import useLobbyData from './useLobbyData';

// Mock the useLobbyData hook
vi.mock('./useLobbyData');

// Mock useParams
vi.mock('react-router-dom', async () => {
    const actual = await vi.importActual('react-router-dom');
    return {
        ...actual,
        useParams: () => ({ gameId: 'testGameId' }),
        useNavigate: () => vi.fn(),
    };
});

describe('LobbyScreen Component', () => {
    const mockLeaveGame = vi.fn();
    const mockUpdatePlayerStatus = vi.fn();
    const mockStartGame = vi.fn();

    beforeEach(() => {
        vi.clearAllMocks();
        (useLobbyData as jest.Mock).mockReturnValue({
            game: {
                id: 'testGameId',
                teams: [{ teamName: 'Team 1', players: [{ name: 'Player 1', isReady: false }] }],
                numberOfTeams: 2,
                playersPerTeam: 2,
                numberOfRounds: 3,
                jokerUsage: true,
            },
            players: [{ name: 'Player 1', isReady: false }],
            isHost: true,
            updatePlayerStatus: mockUpdatePlayerStatus,
            leaveGame: mockLeaveGame,
            startGame: mockStartGame,
        });
    });

    it('renders lobby screen correctly', () => {
        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        expect(screen.getByText('Game Lobby')).toBeInTheDocument();
        expect(screen.getByText('Players (1)')).toBeInTheDocument();
        expect(screen.getByText('Teams')).toBeInTheDocument();
        expect(screen.getByText('Game Settings')).toBeInTheDocument();
        expect(screen.getByText('Leave Game')).toBeInTheDocument();
    });

    it('calls leaveGame function when Leave Game button is clicked', async () => {
        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        const leaveButton = screen.getByText('Leave Game');
        fireEvent.click(leaveButton);

        await waitFor(() => {
            expect(mockLeaveGame).toHaveBeenCalledTimes(1);
        });
    });

    it('does not render Game Settings for non-host players', () => {
        (useLobbyData as jest.Mock).mockReturnValue({
            game: {
                id: 'testGameId',
                teams: [{ teamName: 'Team 1', players: [{ name: 'Player 1', isReady: false }] }],
            },
            players: [{ name: 'Player 1', isReady: false }],
            isHost: false,
            updatePlayerStatus: mockUpdatePlayerStatus,
            leaveGame: mockLeaveGame,
            startGame: mockStartGame,
        });

        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        expect(screen.queryByText('Game Settings')).not.toBeInTheDocument();
    });

    it('displays loading state when game data is not available', () => {
        (useLobbyData as jest.Mock).mockReturnValue({
            game: null,
            players: [],
            isHost: false,
            updatePlayerStatus: mockUpdatePlayerStatus,
            leaveGame: mockLeaveGame,
            startGame: mockStartGame,
        });

        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        expect(screen.getByText('Loading...')).toBeInTheDocument();
    });

    it('calls startGame function when Start Game button is clicked by host', async () => {
        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        const startButton = screen.getByText('Start Game');
        fireEvent.click(startButton);

        await waitFor(() => {
            expect(mockStartGame).toHaveBeenCalledTimes(1);
        });
    });

    it('updates player status when ready button is clicked', async () => {
        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        const readyButton = screen.getByText('Are you Ready?');
        fireEvent.click(readyButton);

        await waitFor(() => {
            expect(mockUpdatePlayerStatus).toHaveBeenCalledWith('Player 1', true);
        });
    });

    it('renders correct number of players and teams', () => {
        (useLobbyData as jest.Mock).mockReturnValue({
            game: {
                id: 'testGameId',
                teams: [
                    { teamName: 'Team 1', players: [{ name: 'Player 1', isReady: false }] },
                    { teamName: 'Team 2', players: [{ name: 'Player 2', isReady: true }] },
                ],
                numberOfTeams: 2,
                playersPerTeam: 2,
                numberOfRounds: 3,
                jokerUsage: true,
            },
            players: [
                { name: 'Player 1', isReady: false },
                { name: 'Player 2', isReady: true },
            ],
            isHost: true,
            updatePlayerStatus: mockUpdatePlayerStatus,
            leaveGame: mockLeaveGame,
            startGame: mockStartGame,
        });

        render(
            <BrowserRouter>
                <LobbyScreen />
            </BrowserRouter>
        );

        expect(screen.getByText('Players (2)')).toBeInTheDocument();
        expect(screen.getAllByRole('listitem')).toHaveLength(4); // 2 in PlayerList + 2 in TeamManagement
        expect(screen.getByText('Team 1')).toBeInTheDocument();
        expect(screen.getByText('Team 2')).toBeInTheDocument();
    });
});

-----

import '@testing-library/jest-dom';

import { vi } from 'vitest';

/**
 * Mock firebase/functions
 */
vi.mock('firebase/functions', async () => {
    const actual = await vi.importActual<typeof import('firebase/functions')>('firebase/functions');
    return {
        ...actual,
        getFunctions: vi.fn(() => {
            // Return a mock functions instance
            return {};
        }),
        httpsCallable: vi.fn(() => {
            // Return a mock callable function
            return vi.fn();
        }),
        connectFunctionsEmulator: vi.fn(),
    };
});

/**
 * Mock firebase/auth
 */
vi.mock('firebase/auth', async () => {
    const actual = await vi.importActual<typeof import('firebase/auth')>('firebase/auth');
    return {
        ...actual,
        getAuth: vi.fn(() => {
            // Return a mock auth instance with currentUser getter
            return {
                currentUser: null,
                onAuthStateChanged: vi.fn(),
            };
        }),
        signInAnonymously: vi.fn(),
        connectAuthEmulator: vi.fn(),
    };
});

/**
 * Mock firebase/firestore (if needed)
 */
vi.mock('firebase/firestore', async () => {
    const actual = await vi.importActual<typeof import('firebase/firestore')>('firebase/firestore');
    return {
        ...actual,
        getFirestore: vi.fn(() => {
            // Return a mock firestore instance
            return {};
        }),
        connectFirestoreEmulator: vi.fn(),
    };
});

// Mock useNavigate from react-router-dom
const mockNavigate = vi.fn();
vi.mock('react-router-dom', async () => {
    const actual = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
    return {
        ...actual,
        useNavigate: () => mockNavigate,
    };
});


setupTests.ts

----


import { useParams } from 'react-router-dom';
import PlayerList from './PLayerList';
import TeamManagement from './TeamManagement';
import GameSettings from './GameSettings';
import useLobbyData from './useLobbyData';

const LobbyScreen: React.FC = () => {
    const { gameId } = useParams<{ gameId: string }>();

    const { game, players, isHost, updatePlayerStatus, leaveGame, startGame } = useLobbyData(gameId);

    if (!game) {
        return <div>Loading...</div>;
    }

    return (
        <div className="container mx-auto p-4">
            <h1 className="text-2xl font-bold mb-4">Game Lobby</h1>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                <PlayerList players={players} updatePlayerStatus={updatePlayerStatus} />
                <TeamManagement teams={game.teams} />
            </div>
            {isHost && <GameSettings game={game} handleStartGame={startGame} />}
            <button
                onClick={leaveGame}
                className="mt-4 bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
            >
                Leave Game
            </button>
        </div>
    );
};

export default LobbyScreen;

----

tests failluures


 ❯ src/pages/lobbyScreen/LobbyScreen.test.tsx (7)
   ❯ LobbyScreen Component (7)
     × renders lobby screen correctly
       ⠸ [ beforeEach ]
     × calls leaveGame function when Leave Game button is clicked
       ⠸ [ beforeEach ]
     × does not render Game Settings for non-host players
       ⠸ [ beforeEach ]
     × displays loading state when game data is not available
       ⠸ [ beforeEach ]
     × calls startGame function when Start Game button is clicked by host
       ⠸ [ beforeEach ]
     × updates player status when ready button is clicked
       ⠸ [ beforeEach ]
     × renders correct number of players and teams
       ⠸ [ beforeEach ]
 ❯ src/pages/lobbyScreen/useLobbyData.test.tsx (0)

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/pages/lobbyScreen/useLobbyData.test.tsx [ src/pages/lobbyScreen/useLobbyData.test.tsx ]
Error: [vitest] No "getFirestore" export is defined on the "firebase/firestore" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("firebase/firestore"), async (importOriginal) => {
  const actual = await importOriginal()
  return {
    ...actual,
    // your mocked methods
  }
})

 ❯ src/firebase/config.ts:17:19
     15| 
     16| const app = initializeApp(fi…
     17| export const db = getFiresto…
       |                   ^
     18| export const functions = get…
     19| export const auth = getAuth(…
 ❯ src/pages/lobbyScreen/useLobbyData.tsx:3:31

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


----

Fix the lobbyScreen tests. explain why they fail