import React from 'react';
import { render, screen, waitFor, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import CreateGame from './CreateGame';
import { BrowserRouter } from 'react-router-dom';
import { httpsCallable } from 'firebase/functions';
import { ensureAnonymousAuth } from '../../firebase/auth/auth';
import usePlayerStore from '../../store/usePlayerStore';

// Mock the usePlayerStore hook
vi.mock('../../store/usePlayerStore', () => ({
  default: vi.fn(),
}));

// Mock Firebase functions
vi.mock('firebase/functions', () => ({
  getFunctions: vi.fn(),
  httpsCallable: vi.fn(),
  connectFunctionsEmulator: vi.fn(),
}));

// Mock ensureAnonymousAuth
vi.mock('../../firebase/auth/auth', () => ({
  ensureAnonymousAuth: 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,
  };
});

describe('CreateGame Component', () => {
  const mockCreateGame = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    // Mock implementation of usePlayerStore
    (usePlayerStore as unknown as vi.Mock).mockReturnValue({
      name: 'TestUser',
    });
    // Mock implementation of httpsCallable
    (httpsCallable as unknown as vi.Mock).mockReturnValue(mockCreateGame);
    // Mock ensureAnonymousAuth to resolve successfully
    (ensureAnonymousAuth as unknown as vi.Mock).mockResolvedValue(null);
  });

  it('renders correctly', () => {
    render(
      <BrowserRouter>
        <CreateGame />
      </BrowserRouter>
    );

    expect(screen.getByText('Create a New Game')).toBeInTheDocument();
    expect(screen.getByLabelText('Number of Teams')).toBeInTheDocument();
    expect(screen.getByLabelText('Players per Team')).toBeInTheDocument();
    expect(screen.getByLabelText('Number of Rounds')).toBeInTheDocument();
    expect(screen.getByLabelText('Allow Joker Usage')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /Create Game/i })).toBeInTheDocument();
  });

  it('submits form with correct data and navigates to game lobby', async () => {
    const user = userEvent.setup();
    mockCreateGame.mockResolvedValue({
      data: { gameId: 'game123', gameCode: 'ABC123' },
    });

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

    const numberOfTeamsInput = screen.getByLabelText('Number of Teams');
    const playersPerTeamInput = screen.getByLabelText('Players per Team');
    const numberOfRoundsInput = screen.getByLabelText('Number of Rounds');
    const jokerUsageCheckbox = screen.getByLabelText('Allow Joker Usage');
    const submitButton = screen.getByRole('button', { name: /Create Game/i });

    // Change form inputs
    await act(async () => {
      await user.clear(numberOfTeamsInput);
      await user.type(numberOfTeamsInput, '3');
      await user.clear(playersPerTeamInput);
      await user.type(playersPerTeamInput, '4');
      await user.clear(numberOfRoundsInput);
      await user.type(numberOfRoundsInput, '5');
      await user.click(jokerUsageCheckbox); // Toggle to false
      await user.click(submitButton);
    });

    await waitFor(() => {
      expect(ensureAnonymousAuth).toHaveBeenCalled();
      expect(mockCreateGame).toHaveBeenCalledWith({
        name: 'TestUser',
        numberOfTeams: 3,
        playersPerTeam: 4,
        numberOfRounds: 5,
        jokerUsage: false,
      });
      expect(mockNavigate).toHaveBeenCalledWith('/game-lobby/game123', {
        state: { gameCode: 'ABC123' },
      });
    });
  });

  it('displays error message on backend failure', async () => {
    const user = userEvent.setup();
    mockCreateGame.mockRejectedValue(new Error('Failed to create game'));

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

    const submitButton = screen.getByRole('button', { name: /Create Game/i });

    await act(async () => {
      await user.click(submitButton);
    });

    await waitFor(() => {
      expect(screen.getByText('Failed to create game')).toBeInTheDocument();
      expect(mockNavigate).not.toHaveBeenCalled();
    });
  });

  it('disables submit button while loading', async () => {
    const user = userEvent.setup();
    // Make the createGame function return a promise that never resolves
    mockCreateGame.mockReturnValue(new Promise(() => {}));

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

    const submitButton = screen.getByRole('button', { name: /Create Game/i });

    await act(async () => {
      await user.click(submitButton);
    });

    expect(submitButton).toBeDisabled();
    expect(submitButton).toHaveTextContent('Creating Game...');
  });

  it('shows error when name is not provided', async () => {
    // Mock usePlayerStore to return empty name
    (usePlayerStore as unknown as vi.Mock).mockReturnValue({
      name: '',
    });

    const user = userEvent.setup();

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

    const submitButton = screen.getByRole('button', { name: /Create Game/i });

    await act(async () => {
      await user.click(submitButton);
    });

    await waitFor(() => {
      expect(screen.getByText('Please enter your name.')).toBeInTheDocument();
      expect(mockCreateGame).not.toHaveBeenCalled();
      expect(mockNavigate).not.toHaveBeenCalled();
    });
  });
});

----

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { httpsCallable } from 'firebase/functions';
import { functions } from '../../firebase/config';
import { ensureAnonymousAuth } from '../../firebase/auth/auth';
import usePlayerStore from '../../store/usePlayerStore';
import NameEntry from '../shared/NameEntry/NameEntry';

interface CreateGameProps { }

const CreateGame: React.FC<CreateGameProps> = () => {
    const [numberOfTeams, setNumberOfTeams] = useState(2);
    const [playersPerTeam, setPlayersPerTeam] = useState(2);
    const [numberOfRounds, setNumberOfRounds] = useState(3);
    const [jokerUsage, setJokerUsage] = useState(true);
    const [error, setError] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const navigate = useNavigate();
    const name = usePlayerStore((state) => state.name);

    const sanitizeInput = (input: string): string => {
        const div = document.createElement('div');
        div.textContent = input;
        return div.innerHTML;
    };

    const handleGameCreate = async (event: React.FormEvent) => {
        event.preventDefault();
        setError('');

        if (!name.trim()) {
            setError('Please enter your name.');
            return;
        }

        setIsLoading(true);

        try {
            await ensureAnonymousAuth();
            const createGameFunction = httpsCallable(functions, 'createGame');
            const result = await createGameFunction({
                name: sanitizeInput(name),
                numberOfTeams,
                playersPerTeam,
                numberOfRounds,
                jokerUsage,
            });
            const data = result.data as { gameId: string; gameCode: string };
            navigate(`/game-lobby/${data.gameId}`, { state: { gameCode: data.gameCode } });
        } catch (err: any) {
            console.error('Error creating game:', err);
            setError(err.message || 'An unexpected error occurred. Please try again later.');
        } finally {
            setIsLoading(false);
        }
    };

    const handleNameValid = () => {
        // Optionally handle actions after the name is validated and set
        // For example, you can automatically submit the form or enable the create game form
    };

    return (
        <div className="max-w-md mx-auto mt-10 p-6 bg-white rounded shadow">
            {!name ? (
                <NameEntry onNameValid={handleNameValid} />
            ) : (
                <form noValidate onSubmit={handleGameCreate}>
                    <h2 className="text-2xl font-bold mb-4">Create a New Game</h2>
                    <div className="mb-4">
                        <label className="block text-gray-700 mb-2" htmlFor="numberOfTeams">
                            Number of Teams
                        </label>
                        <input
                            type="number"
                            id="numberOfTeams"
                            value={numberOfTeams}
                            onChange={(e) => setNumberOfTeams(Number(e.target.value))}
                            min="2"
                            max="10"
                            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-blue-500"
                            required
                        />
                    </div>
                    <div className="mb-4">
                        <label className="block text-gray-700 mb-2" htmlFor="playersPerTeam">
                            Players per Team
                        </label>
                        <input
                            type="number"
                            id="playersPerTeam"
                            value={playersPerTeam}
                            onChange={(e) => setPlayersPerTeam(Number(e.target.value))}
                            min="1"
                            max="10"
                            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-blue-500"
                            required
                        />
                    </div>
                    <div className="mb-4">
                        <label className="block text-gray-700 mb-2" htmlFor="numberOfRounds">
                            Number of Rounds
                        </label>
                        <input
                            type="number"
                            id="numberOfRounds"
                            value={numberOfRounds}
                            onChange={(e) => setNumberOfRounds(Number(e.target.value))}
                            min="1"
                            max="20"
                            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-blue-500"
                            required
                        />
                    </div>
                    <div className="mb-4">
                        <label className="flex items-center">
                            <input
                                type="checkbox"
                                checked={jokerUsage}
                                onChange={(e) => setJokerUsage(e.target.checked)}
                                className="mr-2"
                            />
                            <span className="text-gray-700">Allow Joker Usage</span>
                        </label>
                    </div>
                    {error && <p className="text-red-500 mb-4">{error}</p>}
                    <button
                        type="submit"
                        className="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
                        disabled={isLoading}
                    >
                        {isLoading ? 'Creating Game...' : 'Create Game'}
                    </button>
                </form>
            )}
        </div>
    );
};

export default CreateGame;



----

fix the tests. return the full file