import 'dart:async';
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:aesthetica_wallpaper/models/puzzle_game.dart';

class PuzzleProvider extends ChangeNotifier {
  PuzzleGame? _currentGame;
  Timer? _timer;
  List<GameRecord> _records = [];

  PuzzleGame? get currentGame => _currentGame;
  List<GameRecord> get records => _records;

  /// 创建新游戏
  Future<void> createGame({
    required String imagePath,
    required GameDifficulty difficulty,
    GameMode mode = GameMode.classic,
  }) async {
    // 停止之前的计时器
    _timer?.cancel();

    // 加载并分割图片
    final pieces = await _splitImage(imagePath, difficulty.gridSize);

    // 打乱拼图
    _shufflePieces(pieces, difficulty.gridSize);

    // 创建游戏
    _currentGame = PuzzleGame(
      pieces: pieces,
      difficulty: difficulty,
      mode: mode,
      emptyPosition: mode == GameMode.classic ? pieces.length - 1 : null,
    );

    // 开始计时
    _startTimer();

    notifyListeners();
  }

  /// 分割图片为拼图块
  Future<List<PuzzlePiece>> _splitImage(String imagePath, int gridSize) async {
    final pieces = <PuzzlePiece>[];

    // 加载图片
    final ByteData data = await rootBundle.load(imagePath);
    final codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    final frame = await codec.getNextFrame();
    final image = frame.image;

    final pieceWidth = image.width ~/ gridSize;
    final pieceHeight = image.height ~/ gridSize;

    // 分割图片
    for (int row = 0; row < gridSize; row++) {
      for (int col = 0; col < gridSize; col++) {
        final position = row * gridSize + col;

        // 创建图片块
        final recorder = ui.PictureRecorder();
        final canvas = Canvas(recorder);

        canvas.drawImageRect(
          image,
          Rect.fromLTWH(
            col * pieceWidth.toDouble(),
            row * pieceHeight.toDouble(),
            pieceWidth.toDouble(),
            pieceHeight.toDouble(),
          ),
          Rect.fromLTWH(0, 0, pieceWidth.toDouble(), pieceHeight.toDouble()),
          Paint(),
        );

        final picture = recorder.endRecording();
        final pieceImage = await picture.toImage(pieceWidth, pieceHeight);

        pieces.add(
          PuzzlePiece(
            id: position,
            correctPosition: position,
            currentPosition: position,
            image: MemoryImage(
              (await pieceImage.toByteData(
                format: ui.ImageByteFormat.png,
              ))!.buffer.asUint8List(),
            ),
          ),
        );
      }
    }

    return pieces;
  }

  /// 打乱拼图
  void _shufflePieces(List<PuzzlePiece> pieces, int gridSize) {
    final random = math.Random();

    // 执行多次随机交换
    for (int i = 0; i < pieces.length * 10; i++) {
      final index1 = random.nextInt(pieces.length);
      final index2 = random.nextInt(pieces.length);

      final temp = pieces[index1].currentPosition;
      pieces[index1].currentPosition = pieces[index2].currentPosition;
      pieces[index2].currentPosition = temp;
    }

    // 确保拼图是可解的（对于滑动模式）
    // TODO: 实现可解性检查
  }

  /// 移动拼图块
  void movePiece(int pieceIndex) {
    if (_currentGame == null || _currentGame!.isComplete) return;

    final piece = _currentGame!.pieces[pieceIndex];
    final gridSize = _currentGame!.gridSize;

    if (_currentGame!.mode == GameMode.classic) {
      // 滑动模式：只能移动到空格
      if (!_canMoveToEmpty(piece.currentPosition, gridSize)) return;

      final emptyPos = _currentGame!.emptyPosition!;
      piece.currentPosition = emptyPos;
      _currentGame = _currentGame!.copyWith(emptyPosition: pieceIndex);
    }

    // 增加步数
    _currentGame = _currentGame!.copyWith(moves: _currentGame!.moves + 1);

    // 检查是否完成
    if (_currentGame!.checkComplete()) {
      _completeGame();
    }

    notifyListeners();
  }

  /// 交换两个拼图块（交换模式）
  void swapPieces(int index1, int index2) {
    if (_currentGame == null || _currentGame!.isComplete) return;
    if (_currentGame!.mode == GameMode.classic) return;

    final piece1 = _currentGame!.pieces[index1];
    final piece2 = _currentGame!.pieces[index2];

    final temp = piece1.currentPosition;
    piece1.currentPosition = piece2.currentPosition;
    piece2.currentPosition = temp;

    _currentGame = _currentGame!.copyWith(moves: _currentGame!.moves + 1);

    if (_currentGame!.checkComplete()) {
      _completeGame();
    }

    notifyListeners();
  }

  /// 检查是否可以移动到空格
  bool _canMoveToEmpty(int position, int gridSize) {
    final emptyPos = _currentGame!.emptyPosition!;
    final row = position ~/ gridSize;
    final col = position % gridSize;
    final emptyRow = emptyPos ~/ gridSize;
    final emptyCol = emptyPos % gridSize;

    // 检查是否相邻
    return (row == emptyRow && (col - emptyCol).abs() == 1) ||
        (col == emptyCol && (row - emptyRow).abs() == 1);
  }

  /// 开始计时
  void _startTimer() {
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (_currentGame != null && !_currentGame!.isComplete) {
        _currentGame = _currentGame!.copyWith(
          elapsedTime: _currentGame!.elapsedTime + const Duration(seconds: 1),
        );
        notifyListeners();
      }
    });
  }

  /// 完成游戏
  void _completeGame() {
    _timer?.cancel();
    _currentGame = _currentGame!.copyWith(isComplete: true);

    // 保存记录
    final record = GameRecord(
      imageId: 'temp', // TODO: 使用实际图片ID
      difficulty: _currentGame!.difficulty,
      time: _currentGame!.elapsedTime,
      moves: _currentGame!.moves,
      stars: _currentGame!.getStarRating(),
      completedAt: DateTime.now(),
    );

    _records.add(record);
    // TODO: 持久化保存记录
  }

  /// 重新开始游戏
  void restartGame() {
    if (_currentGame == null) return;

    _timer?.cancel();
    _shufflePieces(_currentGame!.pieces, _currentGame!.gridSize);

    _currentGame = _currentGame!.copyWith(
      moves: 0,
      elapsedTime: Duration.zero,
      isComplete: false,
    );

    _startTimer();
    notifyListeners();
  }

  /// 使用提示
  void useHint() {
    if (_currentGame == null || _currentGame!.isComplete) return;

    // TODO: 实现提示逻辑
    // 找到一个不在正确位置的块，并高亮显示其正确位置
  }

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