import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'dart:io';
import '../../services/puzzle_service.dart';
import '../../models/puzzle_models.dart';

class WordlePage extends StatefulWidget {
  final String? targetWord;
  final DailyChallenge? dailyChallenge;

  const WordlePage({Key? key, this.targetWord, this.dailyChallenge})
    : super(key: key);

  @override
  _WordlePageState createState() => _WordlePageState();
}

class _WordlePageState extends State<WordlePage> with TickerProviderStateMixin {
  late String TARGET_WORD;
  static const int MAX_ATTEMPTS = 6;
  static const int WORD_LENGTH = 5;
  DateTime? gameStartTime;

  List<List<String>> grid = List.generate(
    MAX_ATTEMPTS,
    (_) => List.filled(WORD_LENGTH, ''),
  );
  List<List<LetterState>> gridStates = List.generate(
    MAX_ATTEMPTS,
    (_) => List.filled(WORD_LENGTH, LetterState.empty),
  );
  Map<String, LetterState> keyboardStates = {};

  int currentRow = 0;
  int currentCol = 0;
  int animatingRow = -1;
  bool gameWon = false;
  bool gameLost = false;

  late AnimationController _revealController;
  late List<Animation<double>> _tileAnimations;
  late FocusNode _focusNode;
  Set<LogicalKeyboardKey> _pressedKeys = <LogicalKeyboardKey>{};

  @override
  void initState() {
    super.initState();
    TARGET_WORD = widget.targetWord ?? "HELLO";
    gameStartTime = DateTime.now();
    _initializeAnimations();
    _initializeKeyboardStates();
    _focusNode = FocusNode();
    _loadGameState();

    // Request focus for keyboard input on web/desktop
    if (kIsWeb || (!kIsWeb && !Platform.isIOS && !Platform.isAndroid)) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _focusNode.requestFocus();
      });
    }
  }

  Future<void> _loadGameState() async {
    final gameState = await PuzzleService.loadGameState();
    if (gameState != null && gameState.targetWord == TARGET_WORD) {
      setState(() {
        // Restore game state
        for (int i = 0; i < gameState.guesses.length; i++) {
          if (i < MAX_ATTEMPTS && gameState.guesses[i].isNotEmpty) {
            for (int j = 0; j < WORD_LENGTH; j++) {
              if (j < gameState.guesses[i].length) {
                grid[i][j] = gameState.guesses[i][j];
              }
            }
            // Evaluate the guess to set proper states
            List<LetterState> states = _evaluateGuess(gameState.guesses[i]);
            gridStates[i] = states;
            _updateKeyboardStates(gameState.guesses[i], states);
          }
        }
        currentRow = gameState.currentAttempt;
        currentCol = 0;
        gameWon = gameState.isWon;
        gameLost = gameState.isGameComplete && !gameState.isWon;
        if (gameState.solveTime != null) {
          gameStartTime = gameState.solveTime;
        }
      });

      // If game is already completed, show the completed state
      if (gameState.isGameComplete) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          _showCompletedGameUI();
        });
      }
    }
  }

  Future<void> _saveGameState() async {
    final guesses = <String>[];
    for (int i = 0; i <= currentRow && i < MAX_ATTEMPTS; i++) {
      if (grid[i].any((cell) => cell.isNotEmpty)) {
        guesses.add(grid[i].join(''));
      }
    }

    final gameState = GameState(
      targetWord: TARGET_WORD,
      guesses: guesses,
      currentAttempt: currentRow,
      isGameComplete: gameWon || gameLost,
      isWon: gameWon,
      solveTime: gameWon ? DateTime.now() : null,
      gameDate: PuzzleService.getTodayDateString(),
    );

    await PuzzleService.saveGameState(gameState);
  }

  void _initializeAnimations() {
    _revealController = AnimationController(
      duration: Duration(milliseconds: 1500),
      vsync: this,
    );

    _tileAnimations = List.generate(
      WORD_LENGTH,
      (index) => Tween<double>(begin: 0.0, end: 1.0).animate(
        CurvedAnimation(
          parent: _revealController,
          curve: Interval(
            index * 0.1,
            (index * 0.1) + 0.5,
            curve: Curves.elasticOut,
          ),
        ),
      ),
    );
  }

  void _initializeKeyboardStates() {
    for (int i = 65; i <= 90; i++) {
      keyboardStates[String.fromCharCode(i)] = LetterState.empty;
    }
  }

  @override
  void dispose() {
    _revealController.dispose();
    _focusNode.dispose();
    super.dispose();
  }

  void _addLetter(String letter) {
    if (currentCol < WORD_LENGTH &&
        currentRow < MAX_ATTEMPTS &&
        !gameWon &&
        !gameLost) {
      setState(() {
        grid[currentRow][currentCol] = letter;
        currentCol++;
      });
      _saveGameState();
      HapticFeedback.lightImpact();
    }
  }

  void _deleteLetter() {
    if (currentCol > 0 && !gameWon && !gameLost) {
      setState(() {
        currentCol--;
        grid[currentRow][currentCol] = '';
      });
      _saveGameState();
      HapticFeedback.lightImpact();
    }
  }

  Future<void> _submitWord() async {
    if (currentCol == WORD_LENGTH && !gameWon && !gameLost) {
      String guess = grid[currentRow].join('');
      List<LetterState> newStates = _evaluateGuess(guess);

      // Set the states and start animating the current row
      setState(() {
        gridStates[currentRow] = newStates;
        _updateKeyboardStates(guess, newStates);
        animatingRow = currentRow;
      });

      // Start the reveal animation
      _revealController.reset();
      await _revealController.forward();

      // Clear the animating row and move to next row
      setState(() {
        animatingRow = -1;
      });

      if (guess == TARGET_WORD) {
        setState(() {
          gameWon = true;
        });
        await _saveGameState();
        await _submitAttempt(currentRow + 1, true);
        HapticFeedback.heavyImpact();
        _showCompletedGameUI();
      } else if (currentRow == MAX_ATTEMPTS - 1) {
        setState(() {
          gameLost = true;
        });
        await _saveGameState();
        await _submitAttempt(MAX_ATTEMPTS, false);
        HapticFeedback.heavyImpact();
        _showCompletedGameUI();
      } else {
        setState(() {
          currentRow++;
          currentCol = 0;
        });
        await _saveGameState();
      }
    }
  }

  List<LetterState> _evaluateGuess(String guess) {
    List<LetterState> states = List.filled(WORD_LENGTH, LetterState.absent);
    List<String> targetLetters = TARGET_WORD.split('');
    List<bool> used = List.filled(WORD_LENGTH, false);

    // First pass: check for correct positions
    for (int i = 0; i < WORD_LENGTH; i++) {
      if (guess[i] == targetLetters[i]) {
        states[i] = LetterState.correct;
        used[i] = true;
      }
    }

    // Second pass: check for present letters
    for (int i = 0; i < WORD_LENGTH; i++) {
      if (states[i] != LetterState.correct) {
        for (int j = 0; j < WORD_LENGTH; j++) {
          if (!used[j] && guess[i] == targetLetters[j]) {
            states[i] = LetterState.present;
            used[j] = true;
            break;
          }
        }
      }
    }

    return states;
  }

  void _updateKeyboardStates(String guess, List<LetterState> states) {
    for (int i = 0; i < guess.length; i++) {
      String letter = guess[i];
      LetterState currentState = keyboardStates[letter] ?? LetterState.empty;
      LetterState newState = states[i];

      if (currentState == LetterState.correct) continue;
      if (currentState == LetterState.present && newState == LetterState.absent)
        continue;

      keyboardStates[letter] = newState;
    }
  }

  Future<void> _submitAttempt(int attempts, bool solved) async {
    try {
      await PuzzleService.submitAttempt(attempts: attempts, solved: solved);
    } catch (e) {
      print('Failed to submit attempt: $e');
    }
  }

  void _showCompletedGameUI() {
    // Remove the old dialog and show a new completed game state
    // This will be handled in the UI by showing a different keyboard/message area
  }

  void _goToLeaderboard() {
    Navigator.pop(
      context,
    ); // Go back to puzzles page which will show leaderboard option
  }

  void _showGameEndDialog(bool won) {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(won ? 'Congratulations!' : 'Game Over'),
          content: Text(
            won ? 'You solved today\'s puzzle!' : 'The word was: $TARGET_WORD',
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
                _resetGame();
              },
              child: Text(
                'Play Again',
                style: TextStyle(color: Color(0xFF6A4C93)),
              ),
            ),
          ],
        );
      },
    );
  }

  void _resetGame() {
    setState(() {
      grid = List.generate(MAX_ATTEMPTS, (_) => List.filled(WORD_LENGTH, ''));
      gridStates = List.generate(
        MAX_ATTEMPTS,
        (_) => List.filled(WORD_LENGTH, LetterState.empty),
      );
      currentRow = 0;
      currentCol = 0;
      animatingRow = -1;
      gameWon = false;
      gameLost = false;
      _initializeKeyboardStates();
    });
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      child: GestureDetector(
        onTap: () {
          // Prevent mobile keyboard from showing up
          FocusScope.of(context).unfocus();
          // Only request focus on web/desktop platforms
          if (kIsWeb || (!kIsWeb && !Platform.isIOS && !Platform.isAndroid)) {
            _focusNode.requestFocus();
          }
        },
        child: RawKeyboardListener(
          focusNode: _focusNode,
          onKey: _handleRawKeyEvent,
          child: Scaffold(
            backgroundColor: Colors.white,
            appBar: AppBar(
              backgroundColor: Colors.white,
              elevation: 0,
              leading: IconButton(
                icon: Icon(Icons.arrow_back, color: Color(0xFF6A4C93)),
                onPressed: () => Navigator.pop(context),
              ),
              centerTitle: true,
              title: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    'وصال',
                    style: TextStyle(
                      fontSize: 28,
                      fontWeight: FontWeight.w200,
                      fontFamily: 'Blaka',
                      color: Color(0xFF6A4C93),
                    ),
                  ),
                  SizedBox(width: 8),
                  Text(
                    'Daily Challenge',
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                      color: Colors.grey[600],
                    ),
                  ),
                ],
              ),
              bottom: PreferredSize(
                preferredSize: Size.fromHeight(1),
                child: Container(height: 1, color: Colors.grey[200]),
              ),
            ),
            body: SafeArea(
              child: LayoutBuilder(
                builder: (context, constraints) {
                  double screenHeight = constraints.maxHeight;
                  double keyboardHeight = (gameWon || gameLost) ? 200 : 200; // Estimated heights
                  double availableHeight = screenHeight - keyboardHeight;
                  
                  return Column(
                    children: [
                      // Game Grid Section
                      Expanded(
                        child: Container(
                          height: availableHeight,
                          child: Center(
                            child: Container(
                              constraints: BoxConstraints(maxWidth: 350),
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  // Game Grid
                                  Container(
                                    padding: EdgeInsets.all(16),
                                    child: Column(
                                      children: List.generate(MAX_ATTEMPTS, (row) {
                                        return Padding(
                                          padding: EdgeInsets.symmetric(vertical: 2),
                                          child: Row(
                                            mainAxisAlignment: MainAxisAlignment.center,
                                            children: List.generate(WORD_LENGTH, (col) {
                                              bool shouldAnimate =
                                                  row == animatingRow &&
                                                  gridStates[row][col] !=
                                                      LetterState.empty;

                                              return Container(
                                                margin: EdgeInsets.all(2),
                                                width: 62,
                                                height: 62,
                                                child: shouldAnimate
                                                    ? AnimatedBuilder(
                                                        animation: _tileAnimations[col],
                                                        builder: (context, child) {
                                                          double scale =
                                                              0.8 +
                                                              (0.2 *
                                                                  _tileAnimations[col]
                                                                      .value);
                                                          return Transform.scale(
                                                            scale: scale,
                                                            child: Container(
                                                              width: 62,
                                                              height: 62,
                                                              decoration: BoxDecoration(
                                                                border: Border.all(
                                                                  color:
                                                                      _getBorderColor(
                                                                        row,
                                                                        col,
                                                                      ),
                                                                  width: 2,
                                                                ),
                                                                color:
                                                                    _getAnimatedTileColor(
                                                                      row,
                                                                      col,
                                                                      _tileAnimations[col]
                                                                          .value,
                                                                    ),
                                                                borderRadius:
                                                                    BorderRadius.circular(
                                                                      4,
                                                                    ),
                                                              ),
                                                              child: Center(
                                                                child: Text(
                                                                  grid[row][col],
                                                                  style: TextStyle(
                                                                    fontSize: 32,
                                                                    fontWeight:
                                                                        FontWeight.bold,
                                                                    color: _getAnimatedTextColor(
                                                                      row,
                                                                      col,
                                                                      _tileAnimations[col]
                                                                          .value,
                                                                    ),
                                                                  ),
                                                                ),
                                                              ),
                                                            ),
                                                          );
                                                        },
                                                      )
                                                    : Container(
                                                        width: 62,
                                                        height: 62,
                                                        decoration: BoxDecoration(
                                                          border: Border.all(
                                                            color: _getBorderColor(
                                                              row,
                                                              col,
                                                            ),
                                                            width: 2,
                                                          ),
                                                          color: _getTileColor(
                                                            row,
                                                            col,
                                                          ),
                                                          borderRadius:
                                                              BorderRadius.circular(4),
                                                        ),
                                                        child: Center(
                                                          child: Text(
                                                            grid[row][col],
                                                            style: TextStyle(
                                                              fontSize: 32,
                                                              fontWeight:
                                                                  FontWeight.bold,
                                                              color: _getTextColor(
                                                                row,
                                                                col,
                                                              ),
                                                            ),
                                                          ),
                                                        ),
                                                      ),
                                              );
                                            }),
                                          ),
                                        );
                                      }),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
                      // Spacer between grid and keyboard
                      SizedBox(height: 16),
                      // Keyboard or completion message section
                      Container(
                        constraints: BoxConstraints(
                          minHeight: 200,
                          maxHeight: 250,
                        ),
                        padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
                        child: (gameWon || gameLost)
                            ? _buildCompletionMessage()
                            : _buildKeyboard(),
                      ),
                      // Bottom padding to ensure keyboard isn't at the very bottom
                      SizedBox(height: MediaQuery.of(context).padding.bottom + 8),
                    ],
                  );
                },
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildCompletionMessage() {
    String message;
    String buttonText = 'Go to Leaderboard';
    Color messageColor;
    IconData messageIcon;

    if (gameWon) {
      if (widget.dailyChallenge?.solved == true &&
          widget.dailyChallenge?.solveTime != null) {
        // Already completed today
        message =
            'You solved this at ${PuzzleService.formatSolveTime(widget.dailyChallenge!.solveTime!)} in ${widget.dailyChallenge!.attempts} attempts!';
      } else {
        // Just completed now
        message = 'You got it!\nSolved in ${currentRow + 1} attempts!';
      }
      messageColor = Colors.green;
      messageIcon = Icons.celebration;
    } else {
      if (widget.dailyChallenge?.attempted == true) {
        // Already attempted today
        message =
            'You attempted this challenge but didn\'t solve it in ${widget.dailyChallenge!.attempts} attempts.\nThe word was: $TARGET_WORD';
      } else {
        // Just failed now
        message = 'Better luck next time!\nThe word was: $TARGET_WORD';
      }
      messageColor = Colors.orange;
      messageIcon = Icons.sentiment_neutral;
    }

    return Column(
      children: [
        Container(
          padding: EdgeInsets.all(24),
          margin: EdgeInsets.symmetric(horizontal: 16),
          decoration: BoxDecoration(
            color: messageColor.withOpacity(0.1),
            borderRadius: BorderRadius.circular(20),
            border: Border.all(color: messageColor.withOpacity(0.3), width: 2),
          ),
          child: Column(
            children: [
              Icon(messageIcon, color: messageColor, size: 48),
              SizedBox(height: 16),
              Text(
                message,
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                  color: Colors.black87,
                ),
                textAlign: TextAlign.center,
              ),
            ],
          ),
        ),
        SizedBox(height: 24),
        ElevatedButton(
          onPressed: _goToLeaderboard,
          style: ElevatedButton.styleFrom(
            backgroundColor: Color(0xFF6A4C93),
            foregroundColor: Colors.white,
            padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(25),
            ),
            elevation: 4,
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.leaderboard, size: 20),
              SizedBox(width: 8),
              Text(
                buttonText,
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildKeyboard() {
    List<List<String>> keyboardLayout = [
      ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
      ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
      ['ENTER', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '⌫'],
    ];

    return Column(
      children: keyboardLayout.map((row) {
        return Padding(
          padding: EdgeInsets.symmetric(vertical: 2),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: row.map((key) {
              bool isSpecial = key == 'ENTER' || key == '⌫';
              double width = isSpecial ? 65 : 35;

              return Container(
                margin: EdgeInsets.symmetric(horizontal: 1.5),
                width: width,
                height: 58,
                child: Material(
                  color: _getKeyColor(key),
                  borderRadius: BorderRadius.circular(4),
                  child: InkWell(
                    borderRadius: BorderRadius.circular(4),
                    onTap: () => _handleKeyTap(key),
                    child: Container(
                      alignment: Alignment.center,
                      child: Text(
                        key,
                        style: TextStyle(
                          fontSize: isSpecial ? 12 : 14,
                          fontWeight: FontWeight.bold,
                          color: _getKeyTextColor(key),
                        ),
                      ),
                    ),
                  ),
                ),
              );
            }).toList(),
          ),
        );
      }).toList(),
    );
  }

  void _handleKeyTap(String key) {
    if (key == 'ENTER') {
      _submitWord();
    } else if (key == '⌫') {
      _deleteLetter();
    } else {
      _addLetter(key);
    }
  }

  void _handleRawKeyEvent(RawKeyEvent event) {
    if (event is RawKeyDownEvent) {
      if (event.logicalKey == LogicalKeyboardKey.enter) {
        _submitWord();
      } else if (event.logicalKey == LogicalKeyboardKey.backspace) {
        _deleteLetter();
      } else if (event.character != null && event.character!.isNotEmpty) {
        String key = event.character!.toUpperCase();
        if (key.codeUnitAt(0) >= 65 && key.codeUnitAt(0) <= 90) {
          _addLetter(key);
        }
      }
    }
  }

  Color _getBorderColor(int row, int col) {
    if (row >= MAX_ATTEMPTS || col >= WORD_LENGTH) return Colors.grey[300]!;
    if (row < currentRow || (row == currentRow && gameWon)) {
      return Colors.transparent;
    } else if (row == currentRow && col < currentCol) {
      return Colors.grey[600]!;
    } else {
      return Colors.grey[300]!;
    }
  }

  Color _getTileColor(int row, int col) {
    if (row >= MAX_ATTEMPTS || col >= WORD_LENGTH) return Colors.white;
    if (row >= currentRow && !gameWon) return Colors.white;

    switch (gridStates[row][col]) {
      case LetterState.correct:
        return Color(0xFF6AAE7C);
      case LetterState.present:
        return Color(0xFFC9B037);
      case LetterState.absent:
        return Color(0xFF787C7E);
      default:
        return Colors.white;
    }
  }

  Color _getTextColor(int row, int col) {
    if (row >= MAX_ATTEMPTS || col >= WORD_LENGTH) return Colors.black;
    if (row >= currentRow && !gameWon) return Colors.black;
    return gridStates[row][col] == LetterState.empty
        ? Colors.black
        : Colors.white;
  }

  Color _getAnimatedTileColor(int row, int col, double animationValue) {
    if (row >= MAX_ATTEMPTS || col >= WORD_LENGTH) return Colors.white;
    if (row != animatingRow || gridStates[row][col] == LetterState.empty) {
      return _getTileColor(row, col);
    }

    // Show color based on animation progress
    Color targetColor;
    switch (gridStates[row][col]) {
      case LetterState.correct:
        targetColor = Color(0xFF6AAE7C);
        break;
      case LetterState.present:
        targetColor = Color(0xFFC9B037);
        break;
      case LetterState.absent:
        targetColor = Color(0xFF787C7E);
        break;
      default:
        targetColor = Colors.white;
    }

    return Color.lerp(Colors.white, targetColor, animationValue) ??
        Colors.white;
  }

  Color _getAnimatedTextColor(int row, int col, double animationValue) {
    if (row >= MAX_ATTEMPTS || col >= WORD_LENGTH) return Colors.black;
    if (row != animatingRow || gridStates[row][col] == LetterState.empty) {
      return _getTextColor(row, col);
    }

    // Text color changes with animation
    return Color.lerp(Colors.black, Colors.white, animationValue) ??
        Colors.black;
  }

  Color _getKeyColor(String key) {
    if (key == 'ENTER' || key == '⌫') {
      return Colors.grey[300]!;
    }

    LetterState state = keyboardStates[key] ?? LetterState.empty;
    switch (state) {
      case LetterState.correct:
        return Color(0xFF6AAE7C);
      case LetterState.present:
        return Color(0xFFC9B037);
      case LetterState.absent:
        return Color(0xFF787C7E);
      default:
        return Colors.grey[200]!;
    }
  }

  Color _getKeyTextColor(String key) {
    if (key == 'ENTER' || key == '⌫') {
      return Colors.black;
    }

    LetterState state = keyboardStates[key] ?? LetterState.empty;
    return state == LetterState.empty ? Colors.black : Colors.white;
  }
}

enum LetterState { empty, absent, present, correct }
