import 'dart:async';
import 'dart:collection';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter_svga/flutter_svga.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/shared/tools/sc_path_utils.dart';
import 'package:yumi/shared/data_sources/sources/local/file_cache_manager.dart';
import 'package:tancent_vap/utils/constant.dart';
import 'package:tancent_vap/widgets/vap_view.dart';

import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';

class SCGiftVapSvgaManager {
  Map<String, MovieEntity> videoItemCache = {};
  static SCGiftVapSvgaManager? _inst;
  static const int _maxPreloadConcurrency = 1;

  SCGiftVapSvgaManager._internal();

  factory SCGiftVapSvgaManager() => _inst ??= SCGiftVapSvgaManager._internal();

  final SCPriorityQueue<SCVapTask> _tq = SCPriorityQueue<SCVapTask>(
    (a, b) => a.compareTo(b), // 调用 SCVapTask 的 compareTo 方法
  );
  VapController? _rgc;
  SVGAAnimationController? _rsc;
  bool _play = false;
  bool _dis = false;
  SCVapTask? _currentTask;
  final Queue<String> _preloadQueue = Queue<String>();
  final Set<String> _queuedPreloadPaths = <String>{};
  final Map<String, Future<MovieEntity>> _svgaLoadTasks = {};
  final Map<String, Future<String>> _playablePathTasks = {};
  final Map<String, String> _playablePathCache = {};
  int _activePreloadCount = 0;

  bool _pause = false;

  //是否关闭礼物特效声音
  bool _mute = false;

  void setMute(bool muteMusic) {
    _mute = muteMusic;
    DataPersistence.setPlayGiftMusic(_mute);
  }

  bool getMute() {
    return _mute;
  }

  void _log(String message) {
    debugPrint('[GiftFX][Player] $message');
  }

  bool _needsSvgaController(String path) {
    return SCPathUtils.getFileExtension(path).toLowerCase() == ".svga";
  }

  bool _isControllerReady(SCVapTask task) {
    if (_needsSvgaController(task.path)) {
      return _rsc != null;
    }
    return _rgc != null;
  }

  bool _isPlayableFileReady(String path) {
    final cachedPath = _playablePathCache[path];
    if (cachedPath == null || cachedPath.isEmpty) {
      return false;
    }
    return File(cachedPath).existsSync();
  }

  bool _isPreloadedOrLoading(String path) {
    if (_needsSvgaController(path)) {
      return videoItemCache.containsKey(path) ||
          _svgaLoadTasks.containsKey(path);
    }
    final pathType = SCPathUtils.getPathType(path);
    if (pathType == PathType.asset || pathType == PathType.file) {
      return true;
    }
    return _isPlayableFileReady(path) || _playablePathTasks.containsKey(path);
  }

  Future<void> preload(String path, {bool highPriority = false}) async {
    if (path.isEmpty || _dis || _isPreloadedOrLoading(path)) {
      return;
    }
    if (highPriority) {
      _log('high priority preload path=$path');
      await _warmupPath(path);
      return;
    }
    if (_queuedPreloadPaths.contains(path)) {
      return;
    }
    _preloadQueue.add(path);
    _queuedPreloadPaths.add(path);
    _log('enqueue preload path=$path queue=${_preloadQueue.length}');
    _drainPreloadQueue();
  }

  void _drainPreloadQueue() {
    if (_dis ||
        _pause ||
        _play ||
        _activePreloadCount >= _maxPreloadConcurrency ||
        _preloadQueue.isEmpty) {
      return;
    }
    final path = _preloadQueue.removeFirst();
    _queuedPreloadPaths.remove(path);
    _activePreloadCount++;
    _log(
      'start preload path=$path active=$_activePreloadCount '
      'queueRemaining=${_preloadQueue.length}',
    );
    _warmupPath(path).whenComplete(() {
      _activePreloadCount--;
      _log(
        'finish preload path=$path active=$_activePreloadCount '
        'queueRemaining=${_preloadQueue.length}',
      );
      _drainPreloadQueue();
    });
  }

  Future<void> _warmupPath(String path) async {
    if (_needsSvgaController(path)) {
      await _loadSvgaEntity(path);
      return;
    }
    await _ensurePlayableFilePath(path);
  }

  Future<MovieEntity> _loadSvgaEntity(String path) async {
    final cached = videoItemCache[path];
    if (cached != null) {
      return cached;
    }
    final loadingTask = _svgaLoadTasks[path];
    if (loadingTask != null) {
      return loadingTask;
    }
    final future = () async {
      final pathType = SCPathUtils.getPathType(path);
      late final MovieEntity entity;
      if (pathType == PathType.asset) {
        entity = await SVGAParser.shared.decodeFromAssets(path);
      } else if (pathType == PathType.network) {
        entity = await SVGAParser.shared.decodeFromURL(path);
      } else if (pathType == PathType.file) {
        final bytes = await File(path).readAsBytes();
        entity = await SVGAParser.shared.decodeFromBuffer(bytes);
      } else {
        throw Exception('Unsupported SVGA path: $path');
      }
      entity.autorelease = false;
      videoItemCache[path] = entity;
      return entity;
    }();
    _svgaLoadTasks[path] = future;
    try {
      return await future;
    } finally {
      _svgaLoadTasks.remove(path);
    }
  }

  Future<String> _ensurePlayableFilePath(String path) async {
    final pathType = SCPathUtils.getPathType(path);
    if (pathType == PathType.asset || pathType == PathType.file) {
      return path;
    }
    final cachedPath = _playablePathCache[path];
    if (cachedPath != null &&
        cachedPath.isNotEmpty &&
        File(cachedPath).existsSync()) {
      return cachedPath;
    }
    final loadingTask = _playablePathTasks[path];
    if (loadingTask != null) {
      return loadingTask;
    }
    final future = () async {
      final file = await FileCacheManager.getInstance().getFile(url: path);
      _playablePathCache[path] = file.path;
      return file.path;
    }();
    _playablePathTasks[path] = future;
    try {
      return await future;
    } finally {
      _playablePathTasks.remove(path);
    }
  }

  void _scheduleNextTask({Duration delay = Duration.zero}) {
    if (_dis) {
      return;
    }
    if (delay == Duration.zero) {
      Future.microtask(_pn);
      return;
    }
    Future.delayed(delay, _pn);
  }

  void _finishCurrentTask({Duration delay = Duration.zero}) {
    if (_dis) {
      return;
    }
    _play = false;
    _currentTask = null;
    _scheduleNextTask(delay: delay);
    if (delay == Duration.zero) {
      Future.microtask(_drainPreloadQueue);
    } else {
      Future.delayed(delay, _drainPreloadQueue);
    }
  }

  // 绑定控制器
  void bindVapCtrl(VapController vapController) {
    _mute = DataPersistence.getPlayGiftMusic();
    _dis = false;
    _rgc = vapController;
    _log(
      'bindVapCtrl hasVapCtrl=${_rgc != null} '
      'hasSvgaCtrl=${_rsc != null} queue=${_tq.length} mute=$_mute',
    );
    _rgc?.setAnimListener(
      onVideoStart: () {
        _log('vap onVideoStart path=${_currentTask?.path}');
      },
      onVideoComplete: () {
        _log('vap onVideoComplete path=${_currentTask?.path}');
        _hcs();
      },
      onFailed: (code, type, msg) {
        _log(
          'vap onFailed path=${_currentTask?.path} code=$code type=$type msg=$msg',
        );
        _hcs();
      },
    );
    _scheduleNextTask();
    _drainPreloadQueue();
  }

  void bindSvgaCtrl(SVGAAnimationController svgaController) {
    _dis = false;
    _rsc = svgaController;
    _log(
      'bindSvgaCtrl hasSvgaCtrl=${_rsc != null} '
      'hasVapCtrl=${_rgc != null} queue=${_tq.length}',
    );
    _rsc?.addStatusListener((AnimationStatus status) {
      if (status.isCompleted) {
        _log('svga completed path=${_currentTask?.path}');
        _rsc?.reset();
        _play = false;
        _currentTask = null;
        _pn();
      }
    });
    _scheduleNextTask();
    _drainPreloadQueue();
  }

  // 播放任务
  void play(
    String path, {
    int priority = 0,
    Map<String, VAPContent>? customResources,
    int type = 0,
  }) {
    if (path.isEmpty) {
      _log('play ignored because path is empty');
      return;
    }
    _log(
      'play request path=$path ext=${SCPathUtils.getFileExtension(path)} '
      'priority=$priority type=$type '
      'sdkInt=${SCGlobalConfig.sdkInt} maxSdkNoAnim=${SCGlobalConfig.maxSdkNoAnim} '
      'disposed=$_dis playing=$_play queueBefore=${_tq.length} '
      'hasSvgaCtrl=${_rsc != null} hasVapCtrl=${_rgc != null}',
    );
    if (SCGlobalConfig.sdkInt > SCGlobalConfig.maxSdkNoAnim) {
      if (_dis) {
        _log('play ignored because manager is disposed path=$path');
        return;
      }
      final task = SCVapTask(
        path: path,
        priority: priority,
        customResources: customResources,
      );

      _tq.add(task);
      _log('task enqueued path=$path queueAfter=${_tq.length}');
      if (!_play) {
        _pn();
      }
    } else {
      _log(
        'play ignored because sdkInt <= maxSdkNoAnim '
        'sdkInt=${SCGlobalConfig.sdkInt} maxSdkNoAnim=${SCGlobalConfig.maxSdkNoAnim}',
      );
    }
  }

  // 播放下一个任务
  Future<void> _pn() async {
    if (_pause) {
      _log('skip _pn because paused queue=${_tq.length}');
      return;
    }
    if (_dis || _tq.isEmpty || _play) return;

    final task = _tq.first;
    if (task == null || !_isControllerReady(task)) {
      _log(
        'controller not ready for path=${task?.path} '
        'needSvga=${task != null ? _needsSvgaController(task.path) : "unknown"} '
        'hasSvgaCtrl=${_rsc != null} hasVapCtrl=${_rgc != null} '
        'queue=${_tq.length}',
      );
      return;
    }

    _tq.removeFirst();
    _play = true;
    _currentTask = task;
    try {
      final pathType = SCPathUtils.getPathType(task.path);
      _log(
        'start task path=${task.path} '
        'pathType=$pathType '
        'queueRemaining=${_tq.length} '
        'needSvga=${_needsSvgaController(task.path)}',
      );
      if (pathType == PathType.asset) {
        await _pa(task);
      } else if (pathType == PathType.file) {
        await _pf(task);
      } else if (pathType == PathType.network) {
        await _pnw(task);
      } else {
        debugPrint('VAP_SVGA不支持的路径类型: ${task.path}');
        _finishCurrentTask();
      }
    } catch (e, s) {
      debugPrint('VAP_SVGA播放失败: $e\n$s');
      _finishCurrentTask();
    }
  }

  // 播放资源文件
  Future<void> _pa(SCVapTask task) async {
    if (_dis) return;
    if (SCPathUtils.getFileExtension(task.path).toLowerCase() == ".svga") {
      _log('play asset svga path=${task.path}');
      final entity = await _loadSvgaEntity(task.path);
      _log('use prepared asset svga path=${task.path}');
      _rsc?.videoItem = entity;
      _rsc?.reset();
      _rsc?.forward();
      _log('forward asset svga path=${task.path}');
    } else {
      _log('play asset vap/mp4 path=${task.path}');
      if (task.customResources != null) {
        task.customResources?.forEach((k, v) async {
          await _rgc?.setVapTagContent(k, v);
        });
      }
      await _rgc?.playAsset(task.path);
    }
  }

  // 播放本地文件
  Future<void> _pf(SCVapTask task) async {
    if (_dis) {
      return;
    }
    if (SCPathUtils.getFileExtension(task.path).toLowerCase() == ".svga") {
      final entity = await _loadSvgaEntity(task.path);
      _log('play local svga file path=${task.path}');
      _rsc?.videoItem = entity;
      _rsc?.reset();
      _rsc?.forward();
      return;
    }
    if (_rgc == null) {
      _log('skip playFile because vap controller is null path=${task.path}');
      _finishCurrentTask();
      return;
    }
    _log('play local vap/mp4 file path=${task.path}');
    await _rgc?.setMute(_mute);
    if (task.customResources != null) {
      task.customResources?.forEach((k, v) async {
        await _rgc?.setVapTagContent(k, v);
      });
    }
    await _rgc!.playFile(task.path);
  }

  // 播放网络资源
  Future<void> _pnw(SCVapTask task) async {
    if (_dis) return;
    if (SCPathUtils.getFileExtension(task.path).toLowerCase() == ".svga") {
      _log('play network svga path=${task.path}');
      late final MovieEntity entity;
      try {
        entity = await _loadSvgaEntity(task.path);
      } catch (e) {
        debugPrint('svga解析出错：$e');
        _finishCurrentTask();
        return;
      }
      _log('use prepared network svga path=${task.path}');
      _rsc?.videoItem = entity;
      _rsc?.reset();
      _rsc?.forward();
      _log('forward network svga path=${task.path}');
    } else {
      _log('download network vap/mp4 path=${task.path}');
      final playablePath = await _ensurePlayableFilePath(task.path);
      if (!_dis) {
        _log('use prepared network vap/mp4 local path=$playablePath');
        await _pf(
          SCVapTask(
            path: playablePath,
            priority: task.priority,
            customResources: task.customResources,
          ),
        );
      }
    }
  }

  // 处理控制器状态变化
  void _hcs() {
    if (_rgc != null && !_dis) {
      _log('finish vap task path=${_currentTask?.path}');
      _finishCurrentTask(delay: const Duration(milliseconds: 50));
    }
  }

  //暂停动画播放
  void pauseAnim() {
    _pause = true;
    _log('pauseAnim queue=${_tq.length}');
  }

  //恢复动画播放
  void resumeAnim() {
    _pause = false;
    _log('resumeAnim queue=${_tq.length}');
    _pn();
  }

  // 释放资源
  void dispose() {
    _log('dispose queue=${_tq.length} currentPath=${_currentTask?.path}');
    _dis = true;
    _play = false;
    _currentTask = null;
    _tq.clear();
    _preloadQueue.clear();
    _queuedPreloadPaths.clear();
    _activePreloadCount = 0;
    _rgc?.stop();
    _rgc?.dispose();
    _rgc = null;
    _rsc?.stop();
    _rsc?.dispose();
    _rsc = null;
  }

  // 清除所有任务
  void clearTasks() {
    _log(
      'clearTasks queueBefore=${_tq.length} currentPath=${_currentTask?.path}',
    );
    _play = false;
    _currentTask = null;
    _tq.clear();
    _preloadQueue.clear();
    _queuedPreloadPaths.clear();
    _activePreloadCount = 0;
    _pause = false;
  }
}

// 任务模型
// 1. 修改 SCVapTask 类，实现 Comparable

class SCVapTask implements Comparable<SCVapTask> {
  final String path;
  final int type;
  final int priority;
  final Map<String, VAPContent>? customResources;
  final int _seq;

  static int _nextSeq = 0;

  SCVapTask({
    required this.path,
    this.priority = 0,
    this.customResources,
    this.type = 0,
  }) : _seq = _nextSeq++;

  @override
  int compareTo(SCVapTask other) {
    // 先按优先级降序排列
    int priorityComparison = other.priority.compareTo(priority);
    if (priorityComparison != 0) {
      return priorityComparison;
    }
    // 相同优先级时，按序列号升序排列（先添加的先执行）
    return _seq.compareTo(other._seq);
  }

  @override
  String toString() {
    return 'SCVapTask{path: $path, priority: $priority, seq: $_seq}';
  }
}

// 优先队列实现
class SCPriorityQueue<E> {
  final List<E> _els = [];
  final Comparator<E> _cmp;

  SCPriorityQueue(this._cmp);

  void add(E element) {
    _els.add(element);
    _els.sort(_cmp);
  }

  E removeFirst() {
    if (isEmpty) throw StateError("No elements");
    return _els.removeAt(0);
  }

  E? get first => isEmpty ? null : _els.first;

  bool get isEmpty => _els.isEmpty;

  bool get isNotEmpty => _els.isNotEmpty;

  int get length => _els.length;

  void clear() => _els.clear();

  List<E> get unorderedElements => List.from(_els);

  // 实现 Iterable 接口
  Iterator<E> get iterator => _els.iterator;
}
