// Author: fengshengxiong
// Date: 2024/5/30
// Description: 音乐播放器控制器

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

import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:get/get.dart';
import 'package:just_audio/just_audio.dart';
import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/data/cache/music_cache_manager.dart';
import 'package:tone_snap/utils/audio_util.dart';
import 'package:tone_snap/utils/date_util.dart';
import 'package:tone_snap/utils/log_util.dart';

class MusicPlayerController extends GetxController {
  static MusicPlayerController get to => Get.put(MusicPlayerController(), permanent: true);
  final _player = AudioPlayer();
  StreamSubscription<Duration>? _bufferedSubscription;
  StreamSubscription<Duration?>? _durationSubscription;
  StreamSubscription<Duration>? _positionSubscription;
  StreamSubscription<PlayerState>? _playerStateSubscription;

  /// 缓存管理器
  // final cacheManager = DefaultCacheManager();
  final cacheManager = MusicCacheManager.instance;
  var cacheKey = '';

  /// 是否正在从缓存播放中
  var _isPlayingFromCache = false;

  /// 当前播放的url
  var currentUrl = '';

  /// 是否正在播放
  var isPlaying = false.obs;

  /// 总时长、已播放的时长、缓冲时长
  var totalDuration = Duration.zero.obs;
  var positionDuration = Duration.zero.obs;
  var bufferedDuration = Duration.zero.obs;

  /// 记录进度条拖动前缓冲的位置
  Duration? bufferedPosition;

  /// 拖动前是否是播放状态
  var seekFrontPlaying = true;

  @override
  void onInit() {
    super.onInit();
    AudioUtil.configAudioSession();
  }

  @override
  void onClose() {
    _cancelListening();
    _player.dispose();
    super.onClose();
  }

  /// 播放新的 url
  Future<void> playNewUrl(String newUrl, String videoId) async {
    await _initializePlayer(newUrl, videoId);
    _player.play();

    // 使用的 music_$videoId 作为唯一的 key
    cacheKey = 'music_$videoId';
  }

  /// 设置 url 和监听器
  Future<void> _initializePlayer(String url, String videoId) async {
    try {
      currentUrl = url;
      // 检查是否有缓存
      FileInfo? fileInfo = await cacheManager.getFileFromMemory(cacheKey);
      if (fileInfo != null) {
        LogUtil.d('有缓存，文件路径=${fileInfo.file.path}');
        // 如果有缓存，使用缓存文件
        await _player.setFilePath(fileInfo.file.path);
        _isPlayingFromCache = true;
      } else {
        // 如果没有缓存，通过 url 加载音源并开始播放，同时启动缓存下载
        await _player.setUrl(currentUrl);
        _isPlayingFromCache = false;

        // 下载并缓存文件
        cacheManager.downloadFile(currentUrl, key: cacheKey).then((fileInfo) {
          // 如果缓存下载完成且当前不是从缓存播放，切换到缓存文件
          if (!_isPlayingFromCache) {
            LogUtil.d('新歌曲缓存路径=${fileInfo.file.path}');
            _player.setFilePath(fileInfo.file.path);
            _isPlayingFromCache = true;
          }
        });
      }
      _player.setLoopMode(LoopMode.off);
      _cancelListening();
      _addListening();
    } catch (e) {
      LogUtil.e('Error initializing player: $e');
      BaseEasyLoading.toast('Error initializing player');
    }
  }

  /// 播放/暂停
  Future<void> playPause() async {
    if (_player.playing) {
      _player.pause();
    } else {
      if (_player.processingState == ProcessingState.idle) {
        BaseEasyLoading.loading();
        await _player.load();
        BaseEasyLoading.dismiss();
      }
      _player.play();
    }
  }

  /// 停止播放
  void stopPlay() {
    _player.stop();
    _player.seek(Duration.zero);
    positionDuration.value = Duration.zero;
  }

  /// 将播放器的播放位置设置为指定的时间
  void seekToPosition(double value) {
    if (_player.processingState == ProcessingState.ready) {
      positionDuration.value = Duration(seconds: value.toInt());
      _player.seek(positionDuration.value);
    }
  }

  /// 开始/结束拖动进度条
  Future<void> seekStartEnd(int value) async {
    bufferedPosition = _player.bufferedPosition;
    if (_player.processingState == ProcessingState.ready) {
      if (value == 0) {
        seekFrontPlaying = _player.playing;
        if (_player.playing) {
          _player.pause();
        }
      } else {
        // 拖动前如果是播放状态，拖动完成后恢复播放，否则相反
        if (seekFrontPlaying) {
          _player.play();
        }
      }
    }
  }

  /// 上一首
  void seekToPrevious() {
    _player.seekToPrevious();
  }

  /// 下一首
  void seekToNext() {
    _player.seekToNext();
  }

  /// 监听
  void _addListening() {
    _bufferedSubscription = _player.bufferedPositionStream.listen((bufferedPosition) {
      bufferedDuration.value = bufferedPosition;
    });

    _durationSubscription = _player.durationStream.listen((duration) {
      totalDuration.value = duration ?? Duration.zero;
    });

    _positionSubscription = _player.positionStream.listen((position) {
      positionDuration.value = position;
    });

    _playerStateSubscription = _player.playerStateStream.listen((playerState) {
      isPlaying.value = _player.playing;
      switch (playerState.processingState) {
        case ProcessingState.idle:
          break;
        case ProcessingState.loading:
          break;
        case ProcessingState.buffering:
          break;
        case ProcessingState.ready:
          break;
        case ProcessingState.completed:
          stopPlay();
          break;
      }
    });
  }

  /// 取消监听
  void _cancelListening() {
    _bufferedSubscription?.cancel();
    _durationSubscription?.cancel();
    _positionSubscription?.cancel();
    _playerStateSubscription?.cancel();
  }

  /// 返回格式化后的总时长
  String getTotalDuration() {
    return DateUtil.playDuration(totalDuration.value);
  }

  /// 返回格式化后的已持续时间
  String getPositionDuration() {
    return DateUtil.playDuration(positionDuration.value);
  }

  /// 文件是否存在
  Future<bool> _fileExists(String path) async {
    if (await File(path).exists()) {
      return true;
    } else {
      BaseEasyLoading.toast('Local resource does not exist');
      return false;
    }
  }
}
