import 'dart:async';

import 'package:flame/game.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show HapticFeedback;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:random_avatar/random_avatar.dart';

import '../../../../core/locator/locator.dart';
import '../../../../core/network/ws_client.dart';
import '../../../../core/service/app_sounds.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/widgets/player_avatar.dart';
import '../../../shop/data/data_source/remote/frame_api_provider.dart';
import '../../../tournament/data/data_source/remote/tournament_api_provider.dart';
import '../../../tournament/domain/entities/tournament.dart';
import '../../../wallet/presentation/bloc/wallet_bloc.dart';
import '../../../wallet/presentation/bloc/wallet_event.dart';
import '../../../wallet/presentation/bloc/wallet_state.dart';
import '../../../wallet/presentation/bloc/wallet_status.dart';
import '../../domain/entities/game_entities.dart';
import '../bloc/game_bloc.dart';
import '../bloc/game_state.dart';
import '../../../chat/presentation/widgets/chat_panel.dart';
import '../widgets/confetti.dart';
import '../widgets/flame/hokm_game.dart';
import '../widgets/table_hud.dart';

part 'game_screen.parts.dart';

/// صفحه‌ی میز بازی: صحنه‌ی Flame + اوورلی‌های وضعیت.
class GameScreen extends StatefulWidget {
  final int prize;
  const GameScreen({super.key, this.prize = 0});

  @override
  State<GameScreen> createState() => _GameScreenState();
}

class _GameScreenState extends State<GameScreen> {
  late final HokmGame _game;
  Timer? _introTimer;
  bool _introHidden = false;
  int _countdown = 0; // شمارشِ معکوسِ شروعِ بازی پس از یافتنِ حریفان (۳…۲…۱)
  Tournament? _tournament; // تورنومنتِ فعالِ ثبت‌نام‌شده (اگر باشد) — برای نشانِ درون‌بازی

  @override
  void initState() {
    super.initState();
    final ws = context.read<WalletBloc>().state.walletStatus;
    final skin = ws is WalletLoaded ? ws.wallet.selectedCard : 'simple';
    // URL کاملِ فرش از سرور می‌آید (خالی ⇒ میزِ کلاسیک).
    final carpetUrl = ws is WalletLoaded ? ws.wallet.selectedCarpetImg : '';
    _game = HokmGame(
      context.read<GameBloc>(),
      skin: skin.isEmpty ? 'simple' : skin,
      carpetUrl: carpetUrl,
    );
    _loadTournament();
    locator<FrameApiProvider>().warmCache(); // رنگِ قاب‌ها برای HUD (best-effort)
  }

  /// بررسی می‌کند آیا کاربر در تورنومنتِ فعالی ثبت‌نام کرده تا نشانِ درون‌بازی و
  /// امتیازِ پایانِ بازی نمایش داده شود (این بازیِ عمومی به تورنومنت امتیاز می‌دهد).
  Future<void> _loadTournament() async {
    try {
      final list = await locator<TournamentApiProvider>().getTournaments();
      final active = list.where((t) => t.joined && t.isActive).toList();
      if (mounted && active.isNotEmpty) {
        setState(() => _tournament = active.first);
      }
    } catch (_) {/* بی‌اهمیت */}
  }

  @override
  void dispose() {
    _introTimer?.cancel();
    super.dispose();
  }

  bool _showSearch(GameUiState s) => s.state == null || !_introHidden;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (didPop, _) {
        if (!didPop) _confirmLeave(context);
      },
      child: SafeArea(
        top: false,
        child: Scaffold(
          body: BlocConsumer<GameBloc, GameUiState>(
            listenWhen:
                (a, b) =>
                    (a.notice != b.notice && b.notice != null) ||
                    (a.gameOver == null && b.gameOver != null) ||
                    (a.handResult == null && b.handResult != null),
            listener: (context, state) {
              // بازخوردِ لمسیِ بُردِ دست (کُت قوی‌تر) تا کاربر بی‌درنگ بفهمد بُرد.
              final hr = state.handResult;
              if (hr != null) {
                final myTeam = (state.state?.yourSeat ?? 0) % 2;
                if (hr.winnerTeam == myTeam) {
                  hr.kot
                      ? HapticFeedback.heavyImpact()
                      : HapticFeedback.mediumImpact();
                } else {
                  HapticFeedback.lightImpact(); // باختِ دست هم حس شود تا پایانِ دست معلوم باشد
                }
              }
              if (state.gameOver != null) {
                final won =
                    state.gameOver!.winnerTeam ==
                    (state.state?.yourSeat ?? 0) % 2;
                if (won) {
                  AppSounds.win();
                  HapticFeedback.mediumImpact();
                }
              }
              if (state.notice != null) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                    content: Text(state.notice!),
                    duration: const Duration(seconds: 2),
                  ),
                );
                context.read<GameBloc>().clearNotice();
                // خطا پیش از شروعِ بازی (مثلاً سکه‌ی ناکافی) ⇒ کاربر در دیالوگِ
                // «جستجوی حریف» گیر نکند؛ به لابی برگردد.
                if (state.state == null && state.gameOver == null) {
                  _exitToLobby(context);
                }
              }
            },
            builder: (context, state) {
              if (state.state != null && _introTimer == null) {
                // حریفان پیدا شدند ⇒ شمارشِ معکوسِ ۳…۲…۱ با صدا تا کاربر بداند
                // بازی در حالِ شروع است، سپس اوورلی کنار می‌رود و بُر زدن اجرا می‌شود.
                _countdown = 3; // داخلِ build هستیم؛ همین build مقدار را نشان می‌دهد
                AppSounds.tick();
                _introTimer = Timer.periodic(const Duration(seconds: 1), (t) {
                  if (!mounted) {
                    t.cancel();
                    return;
                  }
                  if (_countdown <= 1) {
                    t.cancel();
                    setState(() => _introHidden = true);
                    _game.endIntro();
                  } else {
                    setState(() => _countdown--);
                    AppSounds.tick();
                  }
                });
              }
              return Stack(
                children: [
                  // فرش به‌عنوانِ سطحِ میز داخلِ صحنه‌ی Flame (Felt) کشیده می‌شود.
                  GameWidget(game: _game),
                  if (!_showSearch(state) && state.state != null)
                    TableHud(
                      s: state.state!,
                      connection: state.connection,
                      chatBubbles: state.chatBubbles,
                      onExit: () => _confirmLeave(context),
                      onChat: () => _openChat(context),
                    ),
                  if (state.connection == WsStatus.disconnected) const _ConnBanner(),
                  if (_tournament != null && !_showSearch(state))
                    _TournamentBadge(title: _tournament!.title),
                  if (_showSearch(state))
                    _SearchPanel(state: state, countdown: _countdown),
                  // دیالوگِ انتخابِ حکم و بنرِ نوبت فقط پس از پایانِ انیمیشنِ
                  // پخشِ کارت نمایش داده می‌شوند (نه وسطِ بُر زدن/پخش).
                  if (!_showSearch(state))
                    ValueListenableBuilder<bool>(
                      valueListenable: _game.animating,
                      builder: (context, animating, _) {
                        if (animating) return const SizedBox.shrink();
                        return Stack(
                          children: [
                            if (_showTrumpPicker(state)) const _TrumpPicker(),
                            if (_isMyPlayTurn(state)) const _TurnBanner(),
                          ],
                        );
                      },
                    ),
                  if (state.handResult != null && state.gameOver == null)
                    Positioned.fill(child: _HandResult(state: state)),
                  if (state.gameOver != null)
                    _GameOver(
                      state: state,
                      prize: widget.prize,
                      tournamentTitle: _tournament?.title,
                      onExit: () => _exitToLobby(context),
                    ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }

  void _openChat(BuildContext context) {
    final bloc = context.read<GameBloc>();
    final wallet = context.read<WalletBloc>();
    ChatPanel.show(
      context,
      onText: bloc.sendChatText,
      onEmoji: bloc.sendChatEmoji,
      onWalletChanged: () => wallet.add(LoadWalletEvent()),
    );
  }

  bool _isMyPlayTurn(GameUiState s) =>
      s.state != null &&
      s.gameOver == null &&
      s.state!.phase == 'playing' &&
      s.state!.isMyTurn &&
      !s.state!.trickDone;

  bool _showTrumpPicker(GameUiState s) =>
      s.state != null &&
      s.state!.phase == 'choose_trump' &&
      s.state!.amHakem &&
      s.gameOver == null;

  Future<void> _confirmLeave(BuildContext context) async {
    if (context.read<GameBloc>().state.gameOver != null) {
      _exitToLobby(context);
      return;
    }
    final yes = await showDialog<bool>(
      context: context,
      builder:
          (_) => AlertDialog(
            backgroundColor: AppColors.panel,
            title: const Text('خروج از میز'),
            content: const Text(
              'از میز خارج می‌شوید؟ ورودی بازگردانده نمی‌شود.',
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context, false),
                child: const Text('ماندن'),
              ),
              TextButton(
                onPressed: () => Navigator.pop(context, true),
                child: const Text('خروج'),
              ),
            ],
          ),
    );
    if (yes == true && context.mounted) {
      context.read<GameBloc>().leave();
      _exitToLobby(context);
    }
  }

  void _exitToLobby(BuildContext context) {
    _game.silence(); // پس از خروج، صدای کارت‌های بات پخش نشود
    context.read<WalletBloc>().add(LoadWalletEvent());
    context.go('/lobby');
  }

}
