import 'dart:async';

import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../core/network/ws_client.dart';
import 'game_models.dart';

class GameUiState extends Equatable {
  final WsStatus connection;
  final GameState? state;
  final HandResult? handResult; // اوورلی نتیجه‌ی هَند (گذرا)
  final GameOver? gameOver; // اوورلی پایان بازی
  final String? notice; // پیام گذرا (خطا/خروج بازیکن)

  const GameUiState({
    this.connection = WsStatus.connecting,
    this.state,
    this.handResult,
    this.gameOver,
    this.notice,
  });

  GameUiState copyWith({
    WsStatus? connection,
    GameState? state,
    HandResult? handResult,
    GameOver? gameOver,
    String? notice,
    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),
      );

  @override
  List<Object?> get props => [connection, state, handResult, gameOver, notice];
}

class GameCubit extends Cubit<GameUiState> {
  final WsClient _ws;
  final String tier;
  late final StreamSubscription _msgSub;
  late final StreamSubscription _statusSub;

  GameCubit(this._ws, this.tier) : super(const GameUiState()) {
    _msgSub = _ws.messages.listen(_onMessage);
    _statusSub = _ws.status.listen(_onStatus);
    _ws.connect();
  }

  void _onStatus(WsStatus s) {
    emit(state.copyWith(connection: s));
    // پس از برقراری اتصال، درخواست ورود به صف؛ در صورت reconnect سرور خودش
    // بازیکن را به میز برمی‌گرداند (این پیام را نادیده می‌گیرد).
    if (s == WsStatus.connected) {
      _ws.send({'type': 'join_queue', 'tier': tier});
    }
  }

  void _onMessage(Map<String, dynamic> msg) {
    switch (msg['type']) {
      case 'state':
        final gs = GameState.fromJson(msg);
        // با شروع دست/هَند جدید، اوورلی نتیجه پاک می‌شود.
        final clear = gs.phase == 'choose_trump' || gs.phase == 'playing';
        emit(state.copyWith(state: gs, clearHandResult: clear));
      case 'hand_over':
        emit(state.copyWith(handResult: HandResult.fromJson(msg)));
      case 'game_over':
        emit(state.copyWith(gameOver: GameOver.fromJson(msg)));
      case 'player_disconnected':
        emit(state.copyWith(notice: 'یک بازیکن قطع شد'));
      case 'player_reconnected':
        emit(state.copyWith(notice: 'بازیکن بازگشت'));
      case 'player_left':
        emit(state.copyWith(notice: 'یک بازیکن میز را ترک کرد'));
      case 'error':
        emit(state.copyWith(notice: (msg['message'] ?? 'خطا').toString()));
    }
  }

  void chooseTrump(String suit) => _ws.send({'type': 'choose_trump', 'suit': suit});

  void playCard(String card) => _ws.send({'type': 'play_card', 'card': card});

  void leave() => _ws.send({'type': 'leave'});

  void clearNotice() => emit(state.copyWith(clearNotice: true));

  @override
  Future<void> close() {
    _msgSub.cancel();
    _statusSub.cancel();
    _ws.dispose();
    return super.close();
  }
}
