import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'logger.dart';
import 'dart:async';

/// 메모리 관리를 위한 헬퍼 클래스
class MemoryManager {
  static final MemoryManager _instance = MemoryManager._internal();
  factory MemoryManager() => _instance;
  MemoryManager._internal();

  // 캐시 관리
  final Map<String, _CacheEntry> _cache = {};
  final int _maxCacheSize = 100;
  final Duration _defaultTTL = const Duration(minutes: 5);

  // 이미지 캐시 관리
  static const int maxImageCacheSize = 50 * 1024 * 1024; // 50MB
  static const int maxImageCacheCount = 100;

  // 위젯 참조 추적
  final Map<String, WeakReference<State>> _widgetReferences = {};

  /// 캐시에 데이터 저장
  void cacheData<T>({
    required String key,
    required T data,
    Duration? ttl,
  }) {
    _cleanupExpiredCache();

    if (_cache.length >= _maxCacheSize) {
      _evictOldestEntry();
    }

    _cache[key] = _CacheEntry(
      data: data,
      timestamp: DateTime.now(),
      ttl: ttl ?? _defaultTTL,
    );
  }

  /// 캐시에서 데이터 가져오기
  T? getCachedData<T>(String key) {
    final entry = _cache[key];
    if (entry == null) return null;

    if (entry.isExpired) {
      _cache.remove(key);
      return null;
    }

    entry.lastAccess = DateTime.now();
    return entry.data as T?;
  }

  /// 캐시 비우기
  void clearCache() {
    _cache.clear();
    if (kDebugMode) {
      Log.d('🧹 메모리 캐시가 비워졌습니다.');
    }
  }

  /// 특정 패턴의 캐시 제거
  void clearCacheByPattern(String pattern) {
    final keysToRemove =
        _cache.keys.where((key) => key.contains(pattern)).toList();

    for (final key in keysToRemove) {
      _cache.remove(key);
    }
  }

  /// 만료된 캐시 정리
  void _cleanupExpiredCache() {
    final expiredKeys = _cache.entries
        .where((entry) => entry.value.isExpired)
        .map((entry) => entry.key)
        .toList();

    for (final key in expiredKeys) {
      _cache.remove(key);
    }
  }

  /// 가장 오래된 캐시 항목 제거
  void _evictOldestEntry() {
    if (_cache.isEmpty) return;

    var oldestKey = _cache.keys.first;
    var oldestTime = _cache[oldestKey]!.lastAccess;

    for (final entry in _cache.entries) {
      if (entry.value.lastAccess.isBefore(oldestTime)) {
        oldestKey = entry.key;
        oldestTime = entry.value.lastAccess;
      }
    }

    _cache.remove(oldestKey);
  }

  /// 이미지 캐시 최적화
  static void optimizeImageCache() {
    PaintingBinding.instance.imageCache.maximumSize = maxImageCacheCount;
    PaintingBinding.instance.imageCache.maximumSizeBytes = maxImageCacheSize;
  }

  /// 이미지 캐시 상태 확인
  static ImageCacheStatus getImageCacheStatus() {
    final cache = PaintingBinding.instance.imageCache;
    return ImageCacheStatus(
      currentSize: cache.currentSize,
      maximumSize: cache.maximumSize,
      currentSizeBytes: cache.currentSizeBytes,
      maximumSizeBytes: cache.maximumSizeBytes,
    );
  }

  /// 이미지 캐시 비우기
  static void clearImageCache() {
    PaintingBinding.instance.imageCache.clear();
    PaintingBinding.instance.imageCache.clearLiveImages();
    if (kDebugMode) {
      Log.d('🖼️ 이미지 캐시가 비워졌습니다.');
    }
  }

  /// 위젯 참조 추적
  void trackWidget(String key, State widget) {
    _widgetReferences[key] = WeakReference(widget);
  }

  /// 위젯 참조 제거
  void untrackWidget(String key) {
    _widgetReferences.remove(key);
  }

  /// 살아있는 위젯 수 확인
  int getAliveWidgetCount() {
    return _widgetReferences.values.where((ref) => ref.target != null).length;
  }

  /// 메모리 압박 시 대응
  void handleMemoryPressure() {
    // 캐시 50% 제거
    final keysToRemove = _cache.keys.take(_cache.length ~/ 2).toList();
    for (final key in keysToRemove) {
      _cache.remove(key);
    }

    // 이미지 캐시 축소
    final imageCache = PaintingBinding.instance.imageCache;
    imageCache.maximumSize = maxImageCacheCount ~/ 2;
    imageCache.maximumSizeBytes = maxImageCacheSize ~/ 2;

    if (kDebugMode) {
      Log.w('메모리 압박 대응: 캐시 크기 감소');
    }
  }

  /// 자동 메모리 정리 시작
  Timer? _cleanupTimer;

  void startAutoCleanup({Duration interval = const Duration(minutes: 1)}) {
    _cleanupTimer?.cancel();
    _cleanupTimer = Timer.periodic(interval, (_) {
      _cleanupExpiredCache();

      // 죽은 위젯 참조 제거
      final deadKeys = _widgetReferences.entries
          .where((entry) => entry.value.target == null)
          .map((entry) => entry.key)
          .toList();

      for (final key in deadKeys) {
        _widgetReferences.remove(key);
      }
    });
  }

  /// 자동 메모리 정리 중지
  void stopAutoCleanup() {
    _cleanupTimer?.cancel();
    _cleanupTimer = null;
  }

  /// 메모리 사용량 리포트
  Map<String, dynamic> getMemoryReport() {
    return {
      'cacheSize': _cache.length,
      'maxCacheSize': _maxCacheSize,
      'aliveWidgets': getAliveWidgetCount(),
      'totalWidgetReferences': _widgetReferences.length,
      'imageCacheStatus': getImageCacheStatus().toJson(),
    };
  }
}

/// 캐시 항목 클래스
class _CacheEntry {
  final dynamic data;
  final DateTime timestamp;
  final Duration ttl;
  DateTime lastAccess;

  _CacheEntry({
    required this.data,
    required this.timestamp,
    required this.ttl,
  }) : lastAccess = timestamp;

  bool get isExpired => DateTime.now().difference(timestamp) > ttl;
}

/// 이미지 캐시 상태 클래스
class ImageCacheStatus {
  final int currentSize;
  final int maximumSize;
  final int currentSizeBytes;
  final int maximumSizeBytes;

  ImageCacheStatus({
    required this.currentSize,
    required this.maximumSize,
    required this.currentSizeBytes,
    required this.maximumSizeBytes,
  });

  double get sizeUsagePercentage => (currentSize / maximumSize) * 100;
  double get bytesUsagePercentage =>
      (currentSizeBytes / maximumSizeBytes) * 100;

  Map<String, dynamic> toJson() => {
        'currentSize': currentSize,
        'maximumSize': maximumSize,
        'currentSizeBytes': currentSizeBytes,
        'maximumSizeBytes': maximumSizeBytes,
        'sizeUsagePercentage': sizeUsagePercentage.toStringAsFixed(2),
        'bytesUsagePercentage': bytesUsagePercentage.toStringAsFixed(2),
      };
}

/// 메모리 효율적인 리스트 뷰
class MemoryEfficientListView<T> extends StatefulWidget {
  final List<T> items;
  final Widget Function(BuildContext, T) itemBuilder;
  final int cacheExtent;
  final ScrollPhysics? physics;

  const MemoryEfficientListView({
    super.key,
    required this.items,
    required this.itemBuilder,
    this.cacheExtent = 250,
    this.physics,
  });

  @override
  State<MemoryEfficientListView<T>> createState() =>
      _MemoryEfficientListViewState<T>();
}

class _MemoryEfficientListViewState<T> extends State<MemoryEfficientListView<T>>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => false;

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return ListView.builder(
      itemCount: widget.items.length,
      cacheExtent: widget.cacheExtent.toDouble(),
      physics: widget.physics ?? const BouncingScrollPhysics(),
      itemBuilder: (context, index) {
        return widget.itemBuilder(context, widget.items[index]);
      },
    );
  }
}
