import 'package:equatable/equatable.dart';

import '../../../../core/network/ws_client.dart';
import '../../domain/entities/game_entities.dart';

/// یک بازیکن در اتاق انتظارِ میز خصوصی.
class LobbyPlayer {
  final String name;
  final String avatar; // seed آواتارِ انتخابیِ کاربر
  final bool host;
  final int seat; // جایگاهِ مطلق (۰..۳)
  final String avatarImg; // شخصیتِ آواتارِ انتخابی (<id>.<ext>؛ خالی ⇒ تصادفی)
  const LobbyPlayer(this.name, this.avatar, this.host, this.seat,
      {this.avatarImg = ''});

  /// seedِ آواتار برای نمایش: آواتارِ انتخابی، وگرنه نام.
  String get avatarSeed => avatar.isNotEmpty ? avatar : name;
}

/// وضعیت اتاق انتظارِ میز خصوصی (دورهمی).
class TableLobby {
  final String code;
  final List<LobbyPlayer> players;
  final bool isHost;
  final int youSeat; // جایگاهِ مطلقِ خودِ کاربر (برای چیدمانِ صحنه)
  final int remaining;
  final bool unlimited;
  final int stake; // شرطِ سکه‌ایِ هر بازیکن (۰ یعنی رایگان)
  const TableLobby({
    required this.code,
    required this.players,
    required this.isHost,
    required this.youSeat,
    required this.remaining,
    required this.unlimited,
    required this.stake,
  });

  factory TableLobby.fromJson(Map<String, dynamic> j) => TableLobby(
        code: (j['code'] ?? '') as String,
        players: ((j['players'] as List?) ?? [])
            .map((e) => LobbyPlayer(
                  (e['name'] ?? '') as String,
                  (e['avatar'] ?? '') as String,
                  (e['host'] ?? false) as bool,
                  (e['seat'] ?? 0) as int,
                  avatarImg: (e['avatar_img'] ?? '') as String,
                ))
            .toList(),
        isHost: (j['host'] ?? false) as bool,
        youSeat: (j['you_seat'] ?? 0) as int,
        remaining: (j['remaining'] ?? 0) as int,
        unlimited: (j['unlimited'] ?? false) as bool,
        stake: (j['stake'] ?? 0) as int,
      );

  String get sig => '$code|$isHost|$youSeat|$remaining|$unlimited|$stake|'
      '${players.map((p) => '${p.name}${p.host ? '*' : ''}@${p.seat}').join(',')}';
}

/// حبابِ پیام/شکلکِ یک بازیکن که کنارِ آواتارش نشان داده می‌شود.
/// id برای انقضای دقیق (پاک‌کردنِ همین حباب و نه حبابِ جدیدتر) به‌کار می‌رود.
class ChatBubble {
  final String? text;
  final String? emoji;
  final int id;
  const ChatBubble({this.text, this.emoji, required this.id});
}

class GameUiState extends Equatable {
  final WsStatus connection;
  final GameState? state;
  final HandResult? handResult;
  final GameOver? gameOver;
  final String? notice;
  final TableLobby? lobby;
  final int? countdown;
  final bool tableClosed;
  final Map<int, ChatBubble> chatBubbles; // جایگاه ⇒ حبابِ پیامِ فعال

  const GameUiState({
    this.connection = WsStatus.connecting,
    this.state,
    this.handResult,
    this.gameOver,
    this.notice,
    this.lobby,
    this.countdown,
    this.tableClosed = false,
    this.chatBubbles = const {},
  });

  GameUiState copyWith({
    WsStatus? connection,
    GameState? state,
    HandResult? handResult,
    GameOver? gameOver,
    String? notice,
    TableLobby? lobby,
    int? countdown,
    bool? tableClosed,
    Map<int, ChatBubble>? chatBubbles,
    bool clearHandResult = false,
    bool clearNotice = false,
  }) =>
      GameUiState(
        connection: connection ?? this.connection,
        state: state ?? this.state,
        handResult: clearHandResult ? null : (handResult ?? this.handResult),
        gameOver: gameOver ?? this.gameOver,
        notice: clearNotice ? null : (notice ?? this.notice),
        lobby: lobby ?? this.lobby,
        countdown: countdown ?? this.countdown,
        tableClosed: tableClosed ?? this.tableClosed,
        chatBubbles: chatBubbles ?? this.chatBubbles,
      );

  @override
  List<Object?> get props => [
        connection,
        state,
        handResult,
        gameOver,
        notice,
        lobby?.sig,
        countdown,
        tableClosed,
        chatBubbles.entries
            .map((e) => '${e.key}:${e.value.id}')
            .join(','),
      ];
}
