import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:puzzleweave/config/device.dart';
import 'package:puzzleweave/models/download.dart';
import 'package:puzzleweave/models/items.dart';

final Logger _log = Logger('home_board');

enum HomeBoardStatus { loading, dealing, playing, done, unlocking }

class HomeBoard {
  final Device device;

  // 原合集图
  ui.Image? image;

  // 纸牌背面图
  ui.Image? cardImage;

  // board 的canvas绘制区域尺寸
  final double canvasWidth;
  final double canvasHeight;

  /// 一张合集分为几宫格，固定5x5
  final int rows = 5;
  final int cols = 5;

  int get count => rows * cols;

  // 每个piece的逻辑尺寸
  double get pieceLogicalWidth => canvasWidth / cols;
  double get pieceLogicalHeight => canvasHeight / rows;

  // 用于触发重绘的通知器
  final ValueNotifier<int> boardNotifier = ValueNotifier<int>(1);
  // 用于通知外部资源已准备就绪
  final ValueNotifier<bool> isReadyNotifier = ValueNotifier<bool>(false);

  HomeBoardStatus status = HomeBoardStatus.loading;

  ListItem? _currentCollectionItem;

  // 2. 优化：记录正在加载的 ID，解决异步竞态问题
  String? _loadingImageUrl;

  ListItem? get currentCollectionItem => _currentCollectionItem;

  set currentCollectionItem(ListItem? item) {
    if (item == null) return;
    if (_currentCollectionItem?.id != item.id) {
      _currentCollectionItem = item;
      _loadImage();
    }
  }

  Offset _unlockTargetOffset = Offset.zero;
  double _unlockTargetScale = 1.0;

  Offset get unlockTargetOffset => _unlockTargetOffset;
  double get unlockTargetScale => _unlockTargetScale;

  void setUnlockAnimationTarget({required Offset targetOffset, required double targetScale}) {
    _unlockTargetOffset = targetOffset;
    _unlockTargetScale = targetScale;
  }

  HomeBoard({required this.canvasWidth, required this.canvasHeight, required this.device}) {
    _loadCardImage();
  }

  void invalidate() {
    boardNotifier.value++;
  }

  // 3. 核心改进：带竞态检查和资源释放的图片加载
  Future<void> _loadImage() async {
    if (_currentCollectionItem == null) return;

    final String currentId = _currentCollectionItem!.id;
    _loadingImageUrl = currentId; // 记录当前请求的 ID

    // 如果需要切换时立即白屏，可以取消下面注释：
    // _clearImage();

    try {
      double dpr = device.devicePixelRatio;
      ItemLoader itemLoader = ItemLoader.load(_currentCollectionItem!);

      // 异步获取图片
      ui.Image? loadedImage = await itemLoader.getImageBySize((canvasWidth * dpr).round(), (canvasHeight * dpr).round());

      // --- 关键判断：竞态条件处理 ---
      // 如果图片回来时，用户已经切换到了下一个合集，则丢弃当前图片并释放内存
      if (_loadingImageUrl != currentId) {
        _log.info('丢弃已过时的图片加载结果: $currentId');
        loadedImage.dispose();
        return;
      }

      // 4. 修改：在赋值新图前，先安全释放旧图内存
      if (image != null) {
        image!.dispose();
      }

      image = loadedImage;
      isReadyNotifier.value = true;
      invalidate();
      _log.info('成功加载合集图片: $currentId');
    } catch (e) {
      _log.severe('加载合集图片失败: $e');
      isReadyNotifier.value = false;
    }
  }

  // 5. 修改：安全加载卡片背面图
  Future<void> _loadCardImage() async {
    try {
      double dpr = device.devicePixelRatio;
      final Size bestCardSize = Size(pieceLogicalWidth * dpr, pieceLogicalHeight * dpr);

      final ByteData cardData = await rootBundle.load('assets/images/backcard_green.png');
      final ui.Codec cardCodec = await ui.instantiateImageCodec(
        cardData.buffer.asUint8List(),
        targetWidth: bestCardSize.width.round(),
        targetHeight: bestCardSize.height.round(),
      );
      final ui.FrameInfo cardFrameInfo = await cardCodec.getNextFrame();

      cardImage = cardFrameInfo.image;
      invalidate();
    } catch (e) {
      _log.severe('加载卡片背面图失败: $e');
    }
  }

  // 6. 新增：彻底释放所有图片内存，防止 OOM
  void dispose() {
    _clearImage();
    if (cardImage != null) {
      cardImage!.dispose();
      cardImage = null;
    }
    boardNotifier.dispose();
    isReadyNotifier.dispose();
  }

  void _clearImage() {
    if (image != null) {
      image!.dispose();
      image = null;
    }
    isReadyNotifier.value = false;
  }

  void switchToNextCollection(ListItem newItem) {
    _log.info('切换到新的合集: ${newItem.id}');
    // 切换状态，让 UI 进入 loading
    status = HomeBoardStatus.loading;
    currentCollectionItem = newItem;
  }
}
