import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { vi } from 'vitest';
import JoinGame from './JoinGame';
import { httpsCallable } from 'firebase/functions';
import { ensureAnonymousAuth } from '../../firebase/auth/auth';
import usePlayerStore from '../../store/usePlayerStore';

// Mock the dependencies
vi.mock('firebase/functions');
vi.mock('../../firebase/auth/auth');
vi.mock('../../store/usePlayerStore');

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

describe('JoinGame Component', () => {

    const mockJoinGame = vi.fn();

    beforeEach(() => {
        vi.clearAllMocks();
        (usePlayerStore as unknown as vi.Mock).mockReturnValue('TestPlayer');
        (httpsCallable as unknown as vi.Mock).mockReturnValue(mockJoinGame);
        (ensureAnonymousAuth as unknown as vi.Mock).mockResolvedValue(null);
    });

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

        expect(screen.getByText('Join a Game')).toBeInTheDocument();
        expect(screen.getByLabelText('Game Code')).toBeInTheDocument();
        expect(screen.getByRole('button', { name: 'Join Game' })).toBeInTheDocument();
    });

    it('validates game code format', async () => {
        render(
            <BrowserRouter>
                <JoinGame />
            </BrowserRouter>
        );

        const input = screen.getByLabelText('Game Code');
        const submitButton = screen.getByRole('button', { name: 'Join Game' });

        fireEvent.change(input, { target: { value: 'ABC12' } });
        fireEvent.click(submitButton);

        await waitFor(() => {
            expect(screen.getByText('Invalid game code. Please enter a 6-character alphanumeric code.')).toBeInTheDocument();
        });
    });

    it('successfully joins a game', async () => {
        render(
            <BrowserRouter>
                <JoinGame />
            </BrowserRouter>
        );

        const input = screen.getByLabelText('Game Code');
        const submitButton = screen.getByRole('button', { name: 'Join Game' });

        fireEvent.change(input, { target: { value: 'ABC123' } });
        fireEvent.click(submitButton);

        await waitFor(() => {
            expect(ensureAnonymousAuth).toHaveBeenCalled();
            expect(mockJoinGame).toHaveBeenCalledWith({ gameCode: 'ABC123', playerName: 'TestPlayer' });
            expect(mockNavigate).toHaveBeenCalledWith('/game-lobby/testGameId');
        });
    });

    it('handles join game error', async () => {
        (httpsCallable as unknown as vi.Mock).mockReturnValue(() => Promise.reject(new Error('Game not found')));

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

        const input = screen.getByLabelText('Game Code');
        const submitButton = screen.getByRole('button', { name: 'Join Game' });

        fireEvent.change(input, { target: { value: 'ABC123' } });
        fireEvent.click(submitButton);

        await waitFor(() => {
            expect(screen.getByText('Game not found')).toBeInTheDocument();
        });
    });
});

===

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';

const JoinGame: React.FC = () => {
  const [gameCode, setGameCode] = useState('');
  const [error, setError] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const navigate = useNavigate();
  const playerName = usePlayerStore((state) => state.name);

  const validateGameCode = (code: string): boolean => {
    // Game code should be 6 characters long and alphanumeric
    const gameCodeRegex = /^[A-Za-z0-9]{6}$/;
    return gameCodeRegex.test(code);
  };

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

    if (!validateGameCode(gameCode)) {
      setError('Invalid game code. Please enter a 6-character alphanumeric code.');
      return;
    }

    if (!playerName) {
      setError('Please set your name before joining a game.');
      return;
    }

    setIsLoading(true);

    try {
      await ensureAnonymousAuth();
      const joinGameFunction = httpsCallable(functions, 'joinGame');
      const result = await joinGameFunction({ gameCode, playerName });
      const data = result.data as { gameId: string };
      navigate(`/game-lobby/${data.gameId}`, { state: { gameCode } });
    } catch (err: any) {
      console.error('Error joining game:', err);
      setError(err.message || 'An unexpected error occurred. Please try again.');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="max-w-md mx-auto mt-10 p-6 bg-white rounded shadow">
      <h2 className="text-2xl font-bold mb-4">Join a Game</h2>
      <form onSubmit={handleJoinGame}>
        <div className="mb-4">
          <label htmlFor="gameCode" className="block text-gray-700 mb-2">
            Game Code
          </label>
          <input
            type="text"
            id="gameCode"
            value={gameCode}
            onChange={(e) => setGameCode(e.target.value.toUpperCase())}
            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-blue-500"
            placeholder="Enter 6-character game code"
            required
          />
        </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 ? 'Joining Game...' : 'Join Game'}
        </button>
      </form>
    </div>
  );
};

export default JoinGame;

====

successfully submit test fails