import 'dart:convert';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:service_api/service_api.dart';
  import 'package:feature_common/feature_common.dart';
import '../controllers/spider_game_controller.dart';
import '../models/spider_difficulty.dart';
import '../models/spider_card.dart';
import '../widgets/tableau_pile_widget.dart';
import '../widgets/bottom_bar_widget.dart';
import '../widgets/card_widget.dart';

class SpiderGameScreen extends StatefulWidget {
  const SpiderGameScreen({super.key});

  @override
  State<SpiderGameScreen> createState() => _SpiderGameScreenState();
}

class _SpiderGameScreenState extends State<SpiderGameScreen> {
  bool _isDialogShowing = false;
  final List<GlobalKey> _tableauKeys = List.generate(10, (_) => GlobalKey());
  final GlobalKey _stockKey = GlobalKey(); 
  final GlobalKey _bodyStackKey = GlobalKey(); 
  final List<Widget> _animationOverlays = [];
  bool _showDimOverlay = false;

  VoidCallback? _controllerListener;

  bool _isDealAnimationRunning = false;
  bool _isStackAnimationRunning = false;

  // ( ... _buildGameAppBar, _showSurrenderDialog, initState, dispose ... )
  // ( ... build, _runDealAnimation, _runStackCompletionAnimation ... )
  // ( ... 이 메서드들은 모두 동일합니다 ... )
  AppBar _buildGameAppBar(BuildContext context, SpiderGameController controller) {
    return AppBar(
      leading: IconButton(icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop()),
      title: Consumer<SpiderGameController>(
        builder: (context, controller, child) {
          final seconds = controller.secondsElapsed;
          final timeStr = "${(seconds ~/ 60).toString().padLeft(2, '0')}:${(seconds % 60).toString().padLeft(2, '0')}";
          return Text(timeStr, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 22));
        },
      ),
      centerTitle: true,
      actions: [
        Consumer<SpiderGameController>(
          builder: (context, controller, child) {
            final bool canUndo = controller.canUndo; 
            return IconButton(
              icon: Icon(Icons.undo, color: canUndo ? null : Colors.grey),
              onPressed: canUndo ? () {
                final int currentCount = controller.undo();
                if (currentCount >= SpiderGameController.maxUndoCount) {
                  _showSurrenderDialog(context);
                }
              } : null,
            );
          },
        ),
        IconButton(
          icon: const Icon(Icons.refresh),
          onPressed: () {
            Provider.of<SpiderGameController>(context, listen: false).restartGame();
          },
        ),
      ],
    );
  }
  void _showSurrenderDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('게임 포기'),
        content: const Text('되돌리기 횟수를 모두 사용했습니다. 게임을 포기하고 로비로 돌아가시겠습니까?'),
        actions: [
          TextButton(child: const Text('취소'), onPressed: () => Navigator.of(ctx).pop()),
          TextButton(
            child: const Text('포기하기'),
            onPressed: () {
              Navigator.of(ctx).pop();
              Navigator.of(context).pop();
            },
          ),
        ],
      ),
    );
  }
  @override
  void initState() {
    super.initState();
    final controller = Provider.of<SpiderGameController>(context, listen: false);
    _controllerListener = () {
      final screenSize = MediaQuery.of(context).size;
      const double horizontalPadding = 10;
      const double cardGap = 5;
      final double cardWidth = (screenSize.width - (horizontalPadding * 2) - (cardGap * 9)) / 10;
      final double cardHeight = cardWidth * 1.45;
      if (controller.cardsToDealAnimate.isNotEmpty && !_isDealAnimationRunning) {
        _isDealAnimationRunning = true; 
        debugPrint("[LOG] initState Listener: Detected cardsToDealAnimate. Running animation...");
        _runDealAnimation(controller, cardWidth, cardHeight);
      }
      if (controller.cardsToAnimateStack.isNotEmpty && !_isStackAnimationRunning) {
        _isStackAnimationRunning = true; 
        final List<SpiderCard> cardsToAnimate = List.of(controller.cardsToAnimateStack);
        final int sourceIndex = controller.animationSourcePileIndex;
        final int targetIndex = controller.animationTargetFoundationIndex;
        controller.clearStackAnimationTrigger(); 
        debugPrint("[LOG] initState Listener: Detected cardsToAnimateStack (Source: $sourceIndex). Running animation...");
        _runStackCompletionAnimation(controller, cardWidth, cardHeight, cardsToAnimate, sourceIndex, targetIndex);
      }
    };
    controller.addListener(_controllerListener!);
  }
  @override
  void dispose() {
    if (_controllerListener != null) {
      final controller = Provider.of<SpiderGameController>(context, listen: false);
      controller.removeListener(_controllerListener!);
    }
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    debugPrint("[LOG] SpiderGameScreen: --- Main Build Method CALLED ---");
    final controller = context.read<SpiderGameController>();
    final screenSize = MediaQuery.of(context).size;
    const double horizontalPadding = 10;
    const double cardGap = 5;
    final double cardWidth = (screenSize.width - (horizontalPadding * 2) - (cardGap * 9)) / 10;
    final double cardHeight = cardWidth * 1.45;
    final double cardOverlap = cardHeight * 0.4;
    final bool isGameCompleted = context.select((SpiderGameController c) => c.isGameCompleted);
    if (isGameCompleted && !_isDialogShowing) {
      _isDialogShowing = true;
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          _runGameWinAnimation(context, controller, cardWidth, cardHeight);
        }
      });
    }
    return Scaffold(
      appBar: _buildGameAppBar(context, controller),
      backgroundColor: Theme.of(context).scaffoldBackgroundColor,
      body: Stack(
        key: _bodyStackKey,
        children: [
          Column(
            children: [
              Expanded(
                child: Container(
                  color: const Color(0xFF008000),
                  padding: EdgeInsets.symmetric(horizontal: horizontalPadding, vertical: 10),
                  child: Stack(
                    children: [
                      Consumer<SpiderGameController>(
                        builder: (context, controller, child) {
                          debugPrint("[LOG] Tableau Consumer: Rebuilding");
                          return Stack(
                            children: List.generate(10, (index) {
                              return Positioned(
                                left: index * (cardWidth + cardGap),
                                top: 0,
                                child: TableauPileWidget(
                                  key: _tableauKeys[index],
                                  pileIndex: index,
                                  cards: controller.currentState.tableau[index],
                                  cardWidth: cardWidth,
                                  cardHeight: cardHeight,
                                  cardOverlap: cardOverlap,
                                ),
                              );
                            }),
                          );
                        }
                      ),
                    ],
                  ),
                ),
              ),
              const AdBannerWidget(),
              BottomBarWidget(
                key: _stockKey,
                cardWidth: cardWidth,
                cardHeight: cardHeight,
              ),
            ],
          ),
          if (_showDimOverlay)
            Container(
              color: Colors.black.withOpacity(0.5),
            ),
          ..._animationOverlays,
        ],
      ),
      bottomNavigationBar: null,
    );
  }
  void _runDealAnimation(
    SpiderGameController controller,
    double cardWidth,
    double cardHeight,
  ) {
    final List<SpiderCard> cardsToDeal = List.of(controller.cardsToDealAnimate);
    controller.clearDealAnimationTrigger(); 
    debugPrint("[LOG] _runDealAnimation: Starting. ${cardsToDeal.length} cards.");
    final RenderBox? bodyStackBox = _bodyStackKey.currentContext?.findRenderObject() as RenderBox?;
    final RenderBox? stockBox = _stockKey.currentContext?.findRenderObject() as RenderBox?;
    if (bodyStackBox == null || stockBox == null) {
       debugPrint("[LOG] _runDealAnimation: FAILED (Keys not ready)");
       _isDealAnimationRunning = false; 
       return;
    }
    final Offset globalStartPos = stockBox.localToGlobal(Offset.zero);
    final Offset localStartPos = bodyStackBox.globalToLocal(globalStartPos);
    for (int i = 0; i < cardsToDeal.length; i++) {
      final card = cardsToDeal[i];
      final RenderBox? targetBox = _tableauKeys[i].currentContext?.findRenderObject() as RenderBox?;
      if (targetBox == null) continue;
      final Offset globalEndPos = targetBox.localToGlobal(Offset.zero);
      final double targetY = globalEndPos.dy + controller.currentState.tableau[i].length * (cardHeight * 0.4);
      final Offset localEndPos = bodyStackBox.globalToLocal(Offset(globalEndPos.dx, targetY));
      final animationDelayMs = i * 100;
      final animationDurationMs = 600;
      final overlayEntry = TweenAnimationBuilder<double>(
        key: ValueKey('deal_${card.id}'),
        tween: Tween(begin: 0.0, end: 1.0),
        duration: Duration(milliseconds: animationDurationMs),
        builder: (context, value, child) {
          final currentPos = Offset.lerp(localStartPos, localEndPos, value)!;
          final bool isFlipping = value > 0.5;
          final double rotationY = isFlipping ? (value - 0.5) * 2 * pi : 0;
          return Positioned(
            left: currentPos.dx,
            top: currentPos.dy,
            child: Transform(
              alignment: Alignment.center,
              transform: Matrix4.identity()
                ..setEntry(3, 2, 0.001)
                ..rotateY(rotationY),
              child: CardWidget(
                card: card..isFaceUp = (value > 0.5), 
                width: cardWidth,
                height: cardHeight,
                isDraggable: false,
              ),
            ),
          );
        },
      );
      Future.delayed(Duration(milliseconds: animationDelayMs), () {
        if (mounted) {
          setState(() { _animationOverlays.add(overlayEntry); });
          Future.delayed(Duration(milliseconds: animationDurationMs), () {
            if (mounted) {
              setState(() { _animationOverlays.remove(overlayEntry); });
              if (i == cardsToDeal.length - 1) {
                debugPrint("[LOG] _runDealAnimation: Animation FINISHED. Calling finalizeDealFromStock.");
                controller.finalizeDealFromStock(cardsToDeal);
                _isDealAnimationRunning = false; 
              }
            }
          });
        }
      });
    }
  }
  void _runStackCompletionAnimation(
    SpiderGameController controller,
    double cardWidth,
    double cardHeight,
    List<SpiderCard> cardsToAnimate,
    int sourceIndex,
    int targetIndex,
  ) {
    debugPrint("[LOG] _runStackCompletionAnimation: Starting. ${cardsToAnimate.length} cards from index $sourceIndex.");
    final RenderBox? bodyStackBox = _bodyStackKey.currentContext?.findRenderObject() as RenderBox?;
    final RenderBox? stockBox = _stockKey.currentContext?.findRenderObject() as RenderBox?;
    final RenderBox? startBox = _tableauKeys[sourceIndex].currentContext?.findRenderObject() as RenderBox?;
    if (bodyStackBox == null || stockBox == null || startBox == null) {
      debugPrint("[LOG] _runStackCompletionAnimation: FAILED (Keys not ready for index $sourceIndex)");
      _isStackAnimationRunning = false; 
      return;
    }
    final Offset globalStartPos = startBox.localToGlobal(Offset.zero);
    final Offset localStartPos = bodyStackBox.globalToLocal(globalStartPos);
    final double startY = localStartPos.dy + (controller.currentState.tableau[sourceIndex].length - cardsToAnimate.length) * (cardHeight * 0.4);
    final Offset globalEndPos = stockBox.localToGlobal(Offset( (targetIndex * (cardWidth * 0.15)) - cardWidth*3, 10));
    final Offset localEndPos = bodyStackBox.globalToLocal(globalEndPos);
    for (int i = 0; i < cardsToAnimate.length; i++) {
      final card = cardsToAnimate[i];
      final animationDelayMs = i * 80;
      final animationDurationMs = 400;
      final overlayEntry = TweenAnimationBuilder<double>(
        key: ValueKey('stack_${card.id}'),
        tween: Tween(begin: 0.0, end: 1.0),
        duration: Duration(milliseconds: animationDurationMs),
        builder: (context, value, child) {
          final currentPos = Offset.lerp(Offset(localStartPos.dx, startY + (i * cardHeight * 0.4)), localEndPos, value)!;
          return Positioned(
            left: currentPos.dx,
            top: currentPos.dy,
            child: CardWidget(
              card: card..isFaceUp = true,
              width: cardWidth,
              height: cardHeight,
              isDraggable: false,
            ),
          );
        },
      );
      Future.delayed(Duration(milliseconds: animationDelayMs), () {
        if (mounted) {
          setState(() { _animationOverlays.add(overlayEntry); });
          Future.delayed(Duration(milliseconds: animationDurationMs), () {
            if (mounted) {
              setState(() { _animationOverlays.remove(overlayEntry); });
              if (i == cardsToAnimate.length - 1) {
                debugPrint("[LOG] _runStackCompletionAnimation: Animation FINISHED. Calling finalizeStackCompletion for index $sourceIndex.");
                controller.finalizeStackCompletion(cardsToAnimate, sourceIndex);
                _isStackAnimationRunning = false; 
              }
            }
          });
        }
      });
    }
  }

  /// 🔽 [수정] _runGameWinAnimation (Navigation 로직 변경)
  void _runGameWinAnimation(
    BuildContext context,
    SpiderGameController controller,
    double cardWidth,
    double cardHeight,
  ) {
    final RenderBox? bodyStackBox = _bodyStackKey.currentContext?.findRenderObject() as RenderBox?;
    if (bodyStackBox == null) return;
    final screenSize = MediaQuery.of(context).size;
    final random = Random();
    final List<SpiderCard> allCards = controller.currentState.foundation.expand((pile) => pile).toList();
    final Offset globalStartPos = Offset(screenSize.width / 2, screenSize.height * 0.8);
    final Offset localStartPos = bodyStackBox.globalToLocal(globalStartPos);

    for (int i = 0; i < allCards.length; i++) {
      // ... (애니메이션 오버레이 생성 로직은 동일) ...
      final card = allCards[i];
      final animationDelay = Duration(milliseconds: i * 30);
      final animationDuration = const Duration(milliseconds: 1500);
      final Offset globalEndPos = Offset(random.nextDouble() * screenSize.width, -cardHeight - (AppBar().preferredSize.height));
      final Offset localEndPos = bodyStackBox.globalToLocal(globalEndPos);
      final overlayEntry = TweenAnimationBuilder<double>(
        key: ValueKey('win_${card.id}'),
        tween: Tween(begin: 0.0, end: 1.0),
        duration: animationDuration,
        builder: (context, value, child) {
          final currentPos = Offset.lerp(localStartPos, localEndPos, value)!;
          return Positioned(
            left: currentPos.dx,
            top: currentPos.dy,
            child: Transform.rotate(
              angle: value * pi * 2,
              child: CardWidget(
                card: card..isFaceUp=true,
                width: cardWidth,
                height: cardHeight,
                isDraggable: false,
              ),
            ),
          );
        },
      );
      Future.delayed(animationDelay, () {
        if (mounted) {
          setState(() { _animationOverlays.add(overlayEntry); });
          Future.delayed(animationDuration, () {
            if (mounted) {
              setState(() { _animationOverlays.remove(overlayEntry); });
            }
          });
        }
      });
    }

    Future.delayed(const Duration(milliseconds: 500), () {
      if (mounted && controller.isGameCompleted) {
        setState(() { _showDimOverlay = true; });
      }
    });

    final popupDelay = (allCards.length > 70) ? const Duration(seconds: 2) : const Duration(milliseconds: 500);
    Future.delayed(popupDelay, () async { // 👈 [수정] async 추가
      if (mounted && controller.isGameCompleted) {
        
        // 1. 점수 포맷터 정의
        String formatSpiderScore(int primary, int? secondary) {
          final moves = primary.toString();
          final time = (secondary ?? 0).toString();
          return '${moves}회 (${time}초)';
        }

        // 2. 레벨 저장 콜백 정의
        Future<void> saveSpiderProgress(String playerName) async {
          final identityService = IdentityService();
          final int currentMaxLevel = await identityService.getMaxUnlockedLevel(gameType: 'SPIDER');
          if (currentMaxLevel < 99) {
            if (controller.difficulty.levelIndex >= currentMaxLevel) {
              int nextLevel = controller.difficulty.levelIndex + 1;
              if (nextLevel > SpiderDifficulties.allDifficulties.length) {
                await identityService.saveMaxUnlockedLevel(99, gameType: 'SPIDER');
              } else {
                await identityService.saveMaxUnlockedLevel(nextLevel, gameType: 'SPIDER');
              }
            }
          }
        }

        // 3. [수정] 'pushReplacement' 대신 'await push' 사용
        await Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => GameCompletionScreen(
              args: GameResultArgs(
                gameType: 'SPIDER',
                contextId: controller.difficulty.contextId,
                primaryScore: controller.currentState.moves,
                secondaryScore: controller.secondsElapsed,
                userId: controller.userId,
                userName: controller.userName,
                scoreFormatter: formatSpiderScore,
                onProgressSave: saveSpiderProgress,
                // ❌ onScreenClose 제거
              ),
            ),
          ),
        );

        // 4. [추가] 랭킹 화면에서 돌아오면, 게임 화면(self)을 닫고 로비로 돌아감
        if (mounted && Navigator.canPop(context)) {
          Navigator.pop(context);
        }
      }
    });
  }

  // ❌ [삭제] _showGameCompletedDialog() 메서드 전체 (약 200줄) 삭제
}