// موجودیت‌های وضعیت بازی (نگاشت از پیام‌های WebSocket سرور).

class GamePlayer {
  final int seat;
  final String name;
  final bool bot;
  final bool connected;
  final int coins;
  final String rankTier; // bronze..king (خالی برای بات)
  final String avatar; // seed آواتارِ انتخابیِ کاربر (خالی برای بات)
  final String frame; // قابِ آواتارِ انتخابی (کازمتیک؛ خالی ⇒ قابِ رتبه)
  final String avatarImg; // شخصیتِ آواتارِ انتخابی (<id>.<ext>؛ خالی ⇒ تصادفی)

  GamePlayer.fromJson(Map<String, dynamic> j)
      : seat = (j['seat'] ?? 0) as int,
        name = (j['name'] ?? '') as String,
        bot = (j['bot'] ?? false) as bool,
        connected = (j['connected'] ?? false) as bool,
        coins = (j['coins'] ?? 0) as int,
        rankTier = (j['rank_tier'] ?? '') as String,
        avatar = (j['avatar'] ?? '') as String,
        frame = (j['frame'] ?? '') as String,
        avatarImg = (j['avatar_img'] ?? '') as String;

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

class TrickCard {
  final int seat;
  final String card;
  TrickCard(this.seat, this.card);
  factory TrickCard.fromJson(Map<String, dynamic> j) =>
      TrickCard((j['seat'] ?? 0) as int, (j['card'] ?? '') as String);
}

/// نمای وضعیت بازی برای بازیکن جاری (پیام type=state).
class GameState {
  final String room;
  final String phase; // choose_trump | playing | hand_over | game_over
  final int yourSeat;
  final int hakem;
  final int turn;
  final String? trump;
  final bool trickDone;
  final List<String> yourHand;
  final List<int> handCounts;
  final List<TrickCard> trick;
  final String? leadSuit;
  final List<int> tricksWon;
  final List<int> scores;
  final int targetScore;
  final int turnTimeoutMs; // مهلتِ نوبتِ انسان (برای شمارنده‌ی نوبت)
  final List<GamePlayer> players;

  GameState({
    required this.room,
    required this.phase,
    required this.yourSeat,
    required this.hakem,
    required this.turn,
    required this.trump,
    required this.trickDone,
    required this.yourHand,
    required this.handCounts,
    required this.trick,
    required this.leadSuit,
    required this.tricksWon,
    required this.scores,
    required this.targetScore,
    required this.turnTimeoutMs,
    required this.players,
  });

  factory GameState.fromJson(Map<String, dynamic> j) {
    List<int> ints(dynamic v) =>
        ((v as List?) ?? []).map((e) => (e as num).toInt()).toList();
    return GameState(
      room: (j['room'] ?? '') as String,
      phase: (j['phase'] ?? '') as String,
      yourSeat: (j['your_seat'] ?? 0) as int,
      hakem: (j['hakem'] ?? 0) as int,
      turn: (j['turn'] ?? 0) as int,
      trump: j['trump'] as String?,
      trickDone: (j['trick_done'] ?? false) as bool,
      yourHand:
          ((j['your_hand'] as List?) ?? []).map((e) => e as String).toList(),
      handCounts: ints(j['hand_counts']),
      trick: ((j['trick'] as List?) ?? [])
          .map((e) => TrickCard.fromJson(Map<String, dynamic>.from(e as Map)))
          .toList(),
      leadSuit: j['lead_suit'] as String?,
      tricksWon: ints(j['tricks_won']),
      scores: ints(j['scores']),
      targetScore: (j['target_score'] ?? 7) as int,
      turnTimeoutMs: (j['turn_timeout_ms'] ?? 0) as int,
      players: ((j['players'] as List?) ?? [])
          .map((e) => GamePlayer.fromJson(Map<String, dynamic>.from(e as Map)))
          .toList(),
    );
  }

  bool get isMyTurn => turn == yourSeat;
  bool get amHakem => hakem == yourSeat;
  GamePlayer? playerAt(int seat) =>
      players.where((p) => p.seat == seat).cast<GamePlayer?>().firstOrNull;
}

/// نتیجه‌ی یک هَند (پیام type=hand_over).
class HandResult {
  final int winnerTeam;
  final bool kot;
  final bool hakemKot;
  final int points;
  final List<int> scores;
  HandResult.fromJson(Map<String, dynamic> j)
      : winnerTeam = (j['winner_team'] ?? 0) as int,
        kot = (j['kot'] ?? false) as bool,
        hakemKot = (j['hakem_kot'] ?? false) as bool,
        points = (j['points'] ?? 0) as int,
        scores =
            ((j['scores'] as List?) ?? []).map((e) => (e as num).toInt()).toList();
}

/// نتیجه‌ی پایان بازی (پیام type=game_over).
class GameOver {
  final int winnerTeam;
  final List<int> scores;
  GameOver.fromJson(Map<String, dynamic> j)
      : winnerTeam = (j['winner_team'] ?? 0) as int,
        scores =
            ((j['scores'] as List?) ?? []).map((e) => (e as num).toInt()).toList();
}

extension FirstOrNullExt<E> on Iterable<E> {
  E? get firstOrNull {
    final it = iterator;
    return it.moveNext() ? it.current : null;
  }
}
