// memory_monitor.dart
// 强化版内存监控工具类

import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:puzzleweave/firebase/firebase_helper.dart';
import 'package:puzzleweave/models/download.dart';

final Logger _log = Logger('MemoryMonitor');

/// 内存阶段定义
enum MemoryState { normal, warning, critical }

class MemoryMonitor with WidgetsBindingObserver {
  static final MemoryMonitor _instance = MemoryMonitor._internal();
  factory MemoryMonitor() => _instance;
  MemoryMonitor._internal();

  Timer? _monitorTimer;
  int _warningCount = 0;

  // 防止系统内存压力信号死循环
  DateTime? _lastSystemPressureTime;
  static const _systemPressureCooldown = Duration(seconds: 10);

  // 动态生成的阈值
  double _warningThreshold = 180.0;
  double _criticalThreshold = 250.0;

  VoidCallback? _onHighMemory;
  VoidCallback? _onCriticalMemory;
  
  // Release模式下的内存显示
  static final ValueNotifier<String> memoryDisplay = ValueNotifier<String>('Memory: 0MB');

  /// 初始化并启动监控
  void startMonitoring({Duration interval = const Duration(seconds: 30), VoidCallback? onHighMemory, VoidCallback? onCriticalMemory}) {
    _onHighMemory = onHighMemory;
    _onCriticalMemory = onCriticalMemory;

    // 1. 注册系统内存压力监听 (WidgetsBindingObserver)
    WidgetsBinding.instance.addObserver(this);

    // 2. 根据设备情况初始化动态阈值
    _initializeDynamicThresholds();

    // 3. 启动定时轮询
    _monitorTimer?.cancel();
    _monitorTimer = Timer.periodic(interval, (_) => _checkMemory());

    _log.info('Memory monitoring started. Warning: ${_warningThreshold}MB, Critical: ${_criticalThreshold}MB');
  }

  /// 停止监控
  void stopMonitoring() {
    WidgetsBinding.instance.removeObserver(this);
    _monitorTimer?.cancel();
    _log.info('Memory monitoring stopped');
  }

  /// 这是进程被杀前的最后一次清理机会
  @override
  void didHaveMemoryPressure() {
    final now = DateTime.now();

    // 防止频繁触发，增加冷却时间
    if (_lastSystemPressureTime != null && now.difference(_lastSystemPressureTime!) < _systemPressureCooldown) {
      _log.info('System memory pressure ignored (cooldown)');
      return;
    }

    _lastSystemPressureTime = now;
    _log.severe('!!! SYSTEM MEMORY PRESSURE: ${getCurrentMemoryMB().toStringAsFixed(1)}MB !!!');

    _emergencyCleanup(reason: 'system_pressure');
    _reportMemoryEvent('system_low_memory_signal', getCurrentMemoryMB());
  }

  /// 动态计算阈值：防止在低端机上设置过高，或在高端机上太敏感
  void _initializeDynamicThresholds() {
    if (Platform.isAndroid) {
      if (kDebugMode) {
        // Debug模式更保守，避免频繁清理
        _warningThreshold = 400.0;
        _criticalThreshold = 500.0;
      } else {
        // Release模式预计内存减半
        _warningThreshold = 120.0;
        _criticalThreshold = 160.0;
      }
    } else if (Platform.isIOS) {
      if (kDebugMode) {
        _warningThreshold = 300.0;
        _criticalThreshold = 400.0;
      } else {
        _warningThreshold = 150.0;
        _criticalThreshold = 200.0;
      }
    } else {
      _warningThreshold = 500.0;
      _criticalThreshold = 700.0;
    }
  }

  void _checkMemory() {
    if (!Platform.isAndroid && !Platform.isIOS) return;

    try {
      final memoryMB = getCurrentMemoryMB();
      
      // 更新UI显示
      memoryDisplay.value = 'Memory: ${memoryMB.toStringAsFixed(1)}MB';

      // 只在超过warning时才记录，减少日志噪音
      if (memoryMB > _warningThreshold) {
        _log.info('Memory: ${memoryMB.toStringAsFixed(1)} MB');
      }

      if (memoryMB > _criticalThreshold) {
        _handleCriticalMemory(memoryMB);
      } else if (memoryMB > _warningThreshold) {
        _handleHighMemory(memoryMB);
      } else {
        _warningCount = 0;
      }
    } catch (e) {
      _log.warning('Memory check failed: $e');
    }
  }

  void _handleCriticalMemory(double memoryMB) {
    _log.severe('CRITICAL memory usage: ${memoryMB.toStringAsFixed(1)} MB');
    _warningCount++;
    _onCriticalMemory?.call();
    _emergencyCleanup(reason: 'critical_threshold');
    _reportMemoryEvent('critical_memory_usage', memoryMB);
  }

  void _handleHighMemory(double memoryMB) {
    _log.warning('HIGH memory usage: ${memoryMB.toStringAsFixed(1)} MB');
    _warningCount++;
    _onHighMemory?.call();
    _reportMemoryEvent('high_memory_usage', memoryMB);
  }

  /// 核心清理逻辑：物理释放显存和缓存
  void _emergencyCleanup({String reason = 'unknown'}) {
    final beforeMB = getCurrentMemoryMB();
    _log.warning('Emergency cleanup: ${beforeMB.toStringAsFixed(1)}MB ($reason)');

    try {
      // 清理顺序很重要，先清理大头
      Download().clearAllData();
      PaintingBinding.instance.imageCache.clear();
      PaintingBinding.instance.imageCache.clearLiveImages();
      PaintingBinding.instance.handleMemoryPressure();

      // 立即检查效果
      final afterMB = getCurrentMemoryMB();
      final freedMB = beforeMB - afterMB;
      _log.info('Cleanup result: ${afterMB.toStringAsFixed(1)}MB (${freedMB > 0 ? "freed" : "increased"}: ${freedMB.abs().toStringAsFixed(1)}MB)');
    } catch (e) {
      _log.severe('Emergency cleanup failed: $e');
    }
  }

  void _reportMemoryEvent(String eventName, double memoryMB) {
    if (kReleaseMode) {
      FirebaseHelper.logEvent(eventName, {'memory_mb': memoryMB.round(), 'warning_count': _warningCount, 'threshold_c': _criticalThreshold.round()});
    }
  }

  static double getCurrentMemoryMB() {
    try {
      // RSS 包含代码段、栈、堆以及共享库。
      // 在三星等低端机上，这是判断 OOM 最直接的指标。
      return ProcessInfo.currentRss / (1024 * 1024);
    } catch (e) {
      return 0;
    }
  }

  /// 供外部在关键节点（如播广告前）手动清理
  void manualCleanup() {
    _emergencyCleanup(reason: 'manual_call');
  }

  static void logMemoryUsage(String label) {
    final memoryMB = getCurrentMemoryMB();
    memoryDisplay.value = '[$label] ${memoryMB.toStringAsFixed(1)}MB';
    _log.info('[$label] RSS Memory: ${memoryMB.toStringAsFixed(1)} MB');
  }
  
  /// 获取内存显示组件（供Release模式使用）
  static Widget getMemoryWidget() {
    return ValueListenableBuilder<String>(
      valueListenable: memoryDisplay,
      builder: (context, value, child) {
        return Container(
          padding: EdgeInsets.all(4),
          decoration: BoxDecoration(
            color: Colors.black54,
            borderRadius: BorderRadius.circular(4),
          ),
          child: Text(
            value,
            style: TextStyle(color: Colors.white, fontSize: 12),
          ),
        );
      },
    );
  }
}
