import 'package:flutter_test/flutter_test.dart';
import 'package:farolero/estado/estado_juego.dart';
import 'package:farolero/modelos/partida.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  group('EstadoJuego crearPartida with host local', () {
    late EstadoJuego estado;

    setUp(() async {
      estado = EstadoJuego();
      await estado.cargarBanco();
    });

    tearDown(() {
      estado.dispose();
    });

    test(
      'should include host in jugadores list when setHostJugador called',
      () {
        // Set host local player first
        estado.setHostJugador('HostJuan');

        // Create game with 3 client players + host (host is in the list)
        estado.crearPartida(
          config: ConfigPartida(
            modoMultimovil: true,
            categoria: 'objetos',
            numImpostores: 1,
            pistaImpostor: false,
          ),
          nombresJugadores: ['HostJuan', 'Cliente1', 'Cliente2', 'Cliente3'],
        );

        expect(estado.partida, isNotNull);
        expect(estado.partida!.jugadores.length, 4);

        // Verify host is in the list
        final hostJugador = estado.partida!.jugadores
            .where((j) => j.nombre == 'HostJuan')
            .firstOrNull;
        expect(hostJugador, isNotNull);
        expect(hostJugador!.endpointId, isNull);
      },
    );

    test('should assign word to host local player', () {
      estado.setHostJugador('HostJuan');

      estado.crearPartida(
        config: ConfigPartida(
          modoMultimovil: true,
          categoria: 'objetos',
          numImpostores: 1,
          pistaImpostor: false,
        ),
        nombresJugadores: ['HostJuan', 'Cliente1', 'Cliente2', 'Cliente3'],
      );

      final hostJugador = estado.partida!.jugadores
          .where((j) => j.nombre == 'HostJuan')
          .firstOrNull;

      // Host should receive a word if not impostor
      expect(hostJugador, isNotNull);
      if (!hostJugador!.esImpostor) {
        expect(hostJugador.palabra, isNotNull);
        expect(hostJugador.palabra!.isNotEmpty, isTrue);
      }
    });

    test('should include host in impostor selection pool', () async {
      // Run multiple times to increase chance of host being impostor
      bool hostWasImpostorAtLeastOnce = false;
      bool hostWasNormalAtLeastOnce = false;

      for (int i = 0; i < 20; i++) {
        final estado2 = EstadoJuego();
        await estado2.cargarBanco();
        estado2.setHostJugador('HostJuan');

        estado2.crearPartida(
          config: ConfigPartida(
            modoMultimovil: true,
            categoria: 'objetos',
            numImpostores: 1,
            pistaImpostor: false,
          ),
          nombresJugadores: ['HostJuan', 'Cliente1', 'Cliente2', 'Cliente3'],
        );

        final hostJugador = estado2.partida!.jugadores
            .where((j) => j.nombre == 'HostJuan')
            .firstOrNull;

        if (hostJugador!.esImpostor) {
          hostWasImpostorAtLeastOnce = true;
        } else {
          hostWasNormalAtLeastOnce = true;
        }
        estado2.dispose();

        if (hostWasImpostorAtLeastOnce && hostWasNormalAtLeastOnce) break;
      }

      // Host should have been impostor at least once and normal at least once
      // (statistically likely with 20 iterations)
      expect(hostWasImpostorAtLeastOnce, isTrue);
      expect(hostWasNormalAtLeastOnce, isTrue);
    });
  });
}
