import 'jugador.dart';
import 'partida.dart';

class SnapshotPartidaOnline {
  final String? roomId;
  final String fase;
  final int ronda;
  final String categoria;
  final String? palabraSecreta;
  final String? ganador;
  final List<Jugador> jugadores;
  final ResultadoVotacion? resultadoActual;
  final List<ResultadoVotacion> historialVotaciones;
  final List<String> impostores;
  final String? mensaje;

  const SnapshotPartidaOnline({
    required this.roomId,
    required this.fase,
    required this.ronda,
    required this.categoria,
    required this.jugadores,
    this.palabraSecreta,
    this.ganador,
    this.resultadoActual,
    this.historialVotaciones = const [],
    this.impostores = const [],
    this.mensaje,
  });

  factory SnapshotPartidaOnline.desdePartida(
    Partida partida, {
    String? roomId,
    String? fase,
    ResultadoVotacion? resultadoActual,
    String? mensaje,
    bool revelarImpostores = false,
    bool revelarPalabra = false,
  }) {
    return SnapshotPartidaOnline(
      roomId: roomId,
      fase: fase ?? partida.fase.name,
      ronda: partida.rondaActual,
      categoria: partida.categoriaReal,
      palabraSecreta: revelarPalabra ? partida.palabraSecreta : null,
      ganador: partida.ganador,
      jugadores: partida.jugadores,
      resultadoActual: resultadoActual ??
          (partida.historialVotaciones.isEmpty
              ? null
              : partida.historialVotaciones.last),
      historialVotaciones: partida.historialVotaciones,
      impostores: revelarImpostores
          ? partida.jugadores
              .where((jugador) => jugador.esImpostor)
              .map((jugador) => jugador.nombre)
              .toList()
          : const [],
      mensaje: mensaje,
    );
  }

  Map<String, dynamic> toJson() => {
        'roomId': roomId,
        'fase': fase,
        'round': ronda,
        'categoria': categoria,
        if (palabraSecreta != null) 'palabraSecreta': palabraSecreta,
        if (ganador != null) 'ganador': ganador,
        'jugadoresTodos': jugadores.map(_jugadorToJson).toList(),
        if (resultadoActual != null)
          'resultadoActual': _resultadoToJson(resultadoActual!),
        'historialVotaciones':
            historialVotaciones.map(_resultadoToJson).toList(),
        if (impostores.isNotEmpty) 'impostores': impostores,
        if (mensaje != null) 'mensaje': mensaje,
      };

  factory SnapshotPartidaOnline.fromJson(Map<String, dynamic> json) {
    final jugadoresData = json['jugadoresTodos'] as List<dynamic>? ?? const [];
    final historialData =
        json['historialVotaciones'] as List<dynamic>? ?? const [];
    final resultadoData = json['resultadoActual'] as Map<String, dynamic>?;

    return SnapshotPartidaOnline(
      roomId: json['roomId'] as String?,
      fase: json['fase'] as String? ?? '',
      ronda: (json['round'] as num?)?.toInt() ?? 1,
      categoria: json['categoria'] as String? ?? '',
      palabraSecreta: json['palabraSecreta'] as String?,
      ganador: json['ganador'] as String?,
      jugadores: jugadoresData
          .map((data) => Jugador.fromJson(data as Map<String, dynamic>))
          .toList(),
      resultadoActual:
          resultadoData == null ? null : _resultadoFromJson(resultadoData),
      historialVotaciones: historialData
          .map((data) => _resultadoFromJson(data as Map<String, dynamic>))
          .toList(),
      impostores: (json['impostores'] as List<dynamic>? ?? const [])
          .map((nombre) => nombre.toString())
          .toList(),
      mensaje: json['mensaje'] as String?,
    );
  }

  static Map<String, dynamic> _jugadorToJson(Jugador jugador) => {
        'id': jugador.id,
        'nombre': jugador.nombre,
        'esImpostor': jugador.esImpostor,
        'eliminado': jugador.eliminado,
      };

  static Map<String, dynamic> _resultadoToJson(ResultadoVotacion resultado) => {
        'eliminadoId': resultado.eliminadoId,
        'eliminadoNombre': resultado.eliminadoNombre,
        'eraImpostor': resultado.eraImpostor,
        'votos': resultado.votos,
      };

  static ResultadoVotacion _resultadoFromJson(Map<String, dynamic> json) {
    final votos = (json['votos'] as Map<dynamic, dynamic>? ?? const {}).map(
      (key, value) => MapEntry(key.toString(), value.toString()),
    );
    return ResultadoVotacion(
      eliminadoId: json['eliminadoId'] as String? ?? '',
      eliminadoNombre: json['eliminadoNombre'] as String? ?? '',
      eraImpostor: json['eraImpostor'] as bool? ?? false,
      votos: votos,
    );
  }
}
