import 'dart:async';
import 'dart:io';
import 'package:floating/floating.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:ns_danmaku/ns_danmaku.dart';
import 'package:pilipala/http/constants.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/http/video.dart';
import 'package:pilipala/models/common/reply_type.dart';
import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/models/video/later.dart';
import 'package:pilipala/models/video/play/quality.dart';
import 'package:pilipala/models/video/play/url.dart';
import 'package:pilipala/models/video/reply/item.dart';
import 'package:pilipala/pages/video/detail/reply_reply/index.dart';
import 'package:pilipala/plugin/pl_player/index.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart';
import 'package:pilipala/utils/video_utils.dart';
import 'package:screen_brightness/screen_brightness.dart';

import '../../../models/video/subTitile/content.dart';
import '../../../http/danmaku.dart';
import '../../../plugin/pl_player/models/bottom_control_type.dart';
import '../../../utils/id_utils.dart';
import 'introduction/controller.dart';
import 'reply/controller.dart';
import 'widgets/header_control.dart';
import 'widgets/watch_later_list.dart';

class VideoDetailController extends GetxController
    with GetSingleTickerProviderStateMixin {
  /// 路由传参
  String bvid = Get.parameters['bvid']!;
  RxInt cid = int.parse(Get.parameters['cid']!).obs;
  RxInt danmakuCid = 0.obs;
  String heroTag = Get.arguments['heroTag'];
  // 视频详情
  Map videoItem = {};
  // 视频类型 默认投稿视频
  SearchType videoType = Get.arguments['videoType'] ?? SearchType.video;
  // 页面来源 稍后再看 收藏夹
  RxString sourceType = 'normal'.obs;

  /// tabs相关配置
  late TabController tabCtr;
  RxList<String> tabs = <String>['简介', '评论'].obs;

  // 请求返回的视频信息
  late PlayUrlModel data;
  // 请求状态
  RxBool isLoading = false.obs;

  /// 播放器配置 画质 音质 解码格式
  late VideoQuality currentVideoQa;
  AudioQuality? currentAudioQa;
  VideoDecodeFormats? currentDecodeFormats;
  // 是否开始自动播放 存在多p的情况下，第二p需要为true
  RxBool autoPlay = true.obs;
  // 视频资源是否有效
  RxBool isEffective = true.obs;
  // 封面图的展示
  RxBool isShowCover = true.obs;
  // 硬解
  RxBool enableHA = false.obs;

  /// 本地存储
  Box userInfoCache = GStrorage.userInfo;
  Box localCache = GStrorage.localCache;
  Box setting = GStrorage.setting;

  RxInt oid = 0.obs;
  // 评论id 请求楼中楼评论使用
  int fRpid = 0;

  ReplyItemModel? firstFloor;
  final scaffoldKey = GlobalKey<ScaffoldState>();
  RxString bgCover = ''.obs;
  RxString cover = ''.obs;
  PlPlayerController plPlayerController = PlPlayerController();

  late VideoItem firstVideo;
  late AudioItem firstAudio;
  late String videoUrl;
  late String audioUrl;
  late Duration defaultST;
  // 亮度
  double? brightness;
  // 默认记录历史记录
  bool enableHeart = true;
  var userInfo;
  late bool isFirstTime = true;
  Floating? floating;
  late PreferredSizeWidget headerControl;

  late bool enableCDN;
  late int? cacheVideoQa;
  late String cacheDecode;
  late int defaultAudioQa;

  PersistentBottomSheetController? replyReplyBottomSheetCtr;
  RxList<SubTitileContentModel> subtitleContents =
      <SubTitileContentModel>[].obs;
  late bool enableRelatedVideo;
  List subtitles = [];
  RxList<BottomControlType> bottomList = [
    BottomControlType.playOrPause,
    BottomControlType.time,
    BottomControlType.space,
    BottomControlType.fit,
    BottomControlType.fullscreen,
  ].obs;
  RxDouble sheetHeight = 0.0.obs;
  RxString archiveSourceType = 'dash'.obs;
  ScrollController? replyScrollController;
  List<MediaVideoItemModel> mediaList = <MediaVideoItemModel>[];
  RxBool isWatchLaterVisible = false.obs;
  RxString watchLaterTitle = ''.obs;

  @override
  void onInit() {
    super.onInit();
    final Map argMap = Get.arguments;
    userInfo = userInfoCache.get('userInfoCache');
    if (argMap.containsKey('videoItem')) {
      var args = argMap['videoItem'];
      updateCover(args.pic);
    } else if (argMap.containsKey('pic')) {
      updateCover(argMap['pic']);
    }

    tabCtr = TabController(length: 2, vsync: this);
    autoPlay.value =
        setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
    enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false);
    enableRelatedVideo =
        setting.get(SettingBoxKey.enableRelatedVideo, defaultValue: true);
    if (userInfo == null ||
        localCache.get(LocalCacheKey.historyPause) == true) {
      enableHeart = false;
    }
    danmakuCid.value = cid.value;

    ///
    if (Platform.isAndroid) {
      floating = Floating();
    }

    // CDN优化
    enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
    // 预设的画质
    cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa);
    // 预设的解码格式
    cacheDecode = setting.get(SettingBoxKey.defaultDecode,
        defaultValue: VideoDecodeFormats.values.last.code);
    defaultAudioQa = setting.get(SettingBoxKey.defaultAudioQa,
        defaultValue: AudioQuality.hiRes.code);
    oid.value = IdUtils.bv2av(Get.parameters['bvid']!);
    getSubtitle();
    headerControl = HeaderControl(
      controller: plPlayerController,
      videoDetailCtr: this,
      floating: floating,
      bvid: bvid,
      videoType: videoType,
    );

    sourceType.value = argMap['sourceType'] ?? 'normal';
    isWatchLaterVisible.value =
        sourceType.value == 'watchLater' || sourceType.value == 'fav';
    if (sourceType.value == 'watchLater') {
      watchLaterTitle.value = '稍后再看';
      fetchMediaList();
    }
    if (sourceType.value == 'fav') {
      watchLaterTitle.value = argMap['favTitle'];
      queryFavVideoList();
    }
    tabCtr.addListener(() {
      onTabChanged();
    });
  }

  showReplyReplyPanel(oid, fRpid, firstFloor, currentReply, loadMore) {
    replyReplyBottomSheetCtr =
        scaffoldKey.currentState?.showBottomSheet((BuildContext context) {
      return VideoReplyReplyPanel(
        oid: oid,
        rpid: fRpid,
        closePanel: () => {
          fRpid = 0,
        },
        firstFloor: firstFloor,
        replyType: ReplyType.video,
        source: 'videoDetail',
        sheetHeight: sheetHeight.value,
        currentReply: currentReply,
        loadMore: loadMore,
      );
    });
    replyReplyBottomSheetCtr?.closed.then((value) {
      fRpid = 0;
    });
  }

  /// 更新画质、音质
  /// TODO 继续进度播放
  updatePlayer() {
    defaultST = plPlayerController.position.value;
    plPlayerController.removeListeners();
    plPlayerController.isBuffering.value = false;
    plPlayerController.buffered.value = Duration.zero;

    if (archiveSourceType.value == 'dash') {
      /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl
      List<VideoItem> videoList =
          data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList();
      try {
        firstVideo = videoList.firstWhere(
            (i) => i.codecs!.startsWith(currentDecodeFormats?.code));
      } catch (_) {
        if (currentVideoQa == VideoQuality.dolbyVision) {
          firstVideo = videoList.first;
          currentDecodeFormats =
              VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!;
        } else {
          // 当前格式不可用
          currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get(
              SettingBoxKey.defaultDecode,
              defaultValue: VideoDecodeFormats.values.last.code))!;
          firstVideo = videoList.firstWhere(
              (i) => i.codecs!.startsWith(currentDecodeFormats?.code));
        }
      }
      videoUrl = firstVideo.baseUrl!;

      /// 根据currentAudioQa 重新设置audioUrl
      if (currentAudioQa != null) {
        final AudioItem firstAudio = data.dash!.audio!.firstWhere(
          (AudioItem i) => i.id == currentAudioQa!.code,
          orElse: () => data.dash!.audio!.first,
        );
        audioUrl = firstAudio.baseUrl ?? '';
      }
    }

    if (archiveSourceType.value == 'durl') {
      cacheVideoQa = VideoQualityCode.toCode(currentVideoQa);
      queryVideoUrl();
    }
    playerInit();
  }

  Future playerInit({
    video,
    audio,
    seekToTime,
    duration,
    bool? autoplay,
  }) async {
    /// 设置/恢复 屏幕亮度
    if (brightness != null) {
      ScreenBrightness().setScreenBrightness(brightness!);
    } else {
      ScreenBrightness().resetScreenBrightness();
    }
    await plPlayerController.setDataSource(
      DataSource(
        videoSource: video ?? videoUrl,
        audioSource: audio ?? audioUrl,
        type: DataSourceType.network,
        httpHeaders: {
          'user-agent':
              'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15',
          'referer': HttpString.baseUrl
        },
      ),
      // 硬解
      enableHA: enableHA.value,
      seekTo: seekToTime ?? defaultST,
      duration: duration ?? Duration(milliseconds: data.timeLength ?? 0),
      // 宽>高 水平 否则 垂直
      direction: firstVideo.width != null && firstVideo.height != null
          ? ((firstVideo.width! - firstVideo.height!) > 0
              ? 'horizontal'
              : 'vertical')
          : null,
      bvid: bvid,
      cid: cid.value,
      enableHeart: enableHeart,
      isFirstTime: isFirstTime,
      autoplay: autoplay ?? autoPlay.value,
    );

    /// 开启自动全屏时，在player初始化完成后立即传入headerControl
    plPlayerController.headerControl = headerControl;

    plPlayerController.subtitles.value = subtitles;
  }

  // 视频链接
  Future queryVideoUrl() async {
    var result =
        await VideoHttp.videoUrl(cid: cid.value, bvid: bvid, qn: cacheVideoQa);
    if (result['status']) {
      data = result['data'];
      if (data.acceptDesc!.isNotEmpty && data.acceptDesc!.contains('试看')) {
        SmartDialog.showToast(
          '该视频为专属视频，仅提供试看',
          displayTime: const Duration(seconds: 3),
        );
        videoUrl = data.durl!.first.url!;
        audioUrl = '';
        defaultST = Duration.zero;
        firstVideo = VideoItem();
        if (autoPlay.value) {
          await playerInit();
          isShowCover.value = false;
        }
        return result;
      }
      if (data.durl != null) {
        archiveSourceType.value = 'durl';
        videoUrl = data.durl!.first.url!;
        audioUrl = '';
        defaultST = Duration.zero;
        firstVideo = VideoItem();
        currentVideoQa = VideoQualityCode.fromCode(data.quality!)!;
        if (autoPlay.value) {
          await playerInit();
          isShowCover.value = false;
        }
        return result;
      }
      final List<VideoItem> allVideosList = data.dash!.video!;
      try {
        archiveSourceType.value = 'dash';
        // 当前可播放的最高质量视频
        int currentHighVideoQa = allVideosList.first.quality!.code;
        // 预设的画质为null，则当前可用的最高质量
        cacheVideoQa ??= currentHighVideoQa;
        int resVideoQa = currentHighVideoQa;
        if (cacheVideoQa! <= currentHighVideoQa) {
          // 如果预设的画质低于当前最高
          final List<int> numbers = data.acceptQuality!
              .where((e) => e <= currentHighVideoQa)
              .toList();
          resVideoQa = Utils.findClosestNumber(cacheVideoQa!, numbers);
        }
        currentVideoQa = VideoQualityCode.fromCode(resVideoQa)!;

        /// 取出符合当前画质的videoList
        final List<VideoItem> videosList =
            allVideosList.where((e) => e.quality!.code == resVideoQa).toList();

        /// 优先顺序 设置中指定解码格式 -> 当前可选的首个解码格式
        final List<FormatItem> supportFormats = data.supportFormats!;
        // 根据画质选编码格式
        final List supportDecodeFormats =
            supportFormats.firstWhere((e) => e.quality == resVideoQa).codecs!;
        // 默认从设置中取AVC
        currentDecodeFormats = VideoDecodeFormatsCode.fromString(cacheDecode)!;
        try {
          // 当前视频没有对应格式返回第一个
          bool flag = false;
          for (var i in supportDecodeFormats) {
            if (i.startsWith(currentDecodeFormats?.code)) {
              flag = true;
            }
          }
          currentDecodeFormats = flag
              ? currentDecodeFormats
              : VideoDecodeFormatsCode.fromString(supportDecodeFormats.first)!;
        } catch (err) {
          SmartDialog.showToast('DecodeFormats error: $err');
        }

        /// 取出符合当前解码格式的videoItem
        try {
          firstVideo = videosList.firstWhere(
              (e) => e.codecs!.startsWith(currentDecodeFormats?.code));
        } catch (_) {
          firstVideo = videosList.first;
        }
        videoUrl = enableCDN
            ? VideoUtils.getCdnUrl(firstVideo)
            : (firstVideo.backupUrl ?? firstVideo.baseUrl!);
      } catch (err) {
        SmartDialog.showToast('firstVideo error: $err');
      }

      /// 优先顺序 设置中指定质量 -> 当前可选的最高质量
      late AudioItem? firstAudio;
      final List<AudioItem> audiosList = data.dash!.audio!;

      try {
        if (data.dash!.dolby?.audio?.isNotEmpty == true) {
          // 杜比
          audiosList.insert(0, data.dash!.dolby!.audio!.first);
        }

        if (data.dash!.flac?.audio != null) {
          // 无损
          audiosList.insert(0, data.dash!.flac!.audio!);
        }

        if (audiosList.isNotEmpty) {
          final List<int> numbers = audiosList.map((map) => map.id!).toList();
          int closestNumber = Utils.findClosestNumber(defaultAudioQa, numbers);
          if (!numbers.contains(defaultAudioQa) &&
              numbers.any((e) => e > defaultAudioQa)) {
            closestNumber = 30280;
          }
          firstAudio = audiosList.firstWhere((e) => e.id == closestNumber);
        } else {
          firstAudio = AudioItem();
        }
      } catch (err) {
        firstAudio = audiosList.isNotEmpty ? audiosList.first : AudioItem();
        SmartDialog.showToast('firstAudio error: $err');
      }

      audioUrl = enableCDN
          ? VideoUtils.getCdnUrl(firstAudio)
          : (firstAudio.backupUrl ?? firstAudio.baseUrl!);
      //
      if (firstAudio.id != null) {
        currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;
      }
      defaultST = Duration(milliseconds: data.lastPlayTime!);
      if (autoPlay.value) {
        await playerInit();
        isShowCover.value = false;
      }
    } else {
      if (result['code'] == -404) {
        isShowCover.value = false;
      }
      SmartDialog.showToast(result['msg'].toString());
    }
    return result;
  }

  // mob端全屏状态关闭二级回复
  hiddenReplyReplyPanel() {
    replyReplyBottomSheetCtr != null
        ? replyReplyBottomSheetCtr!.close()
        : print('replyReplyBottomSheetCtr is null');
  }

  // 获取字幕配置
  Future getSubtitle() async {
    var result = await VideoHttp.getSubtitle(bvid: bvid, cid: cid.value);
    if (result['status']) {
      if (result['data'].subtitles.isNotEmpty) {
        subtitles = result['data'].subtitles;
        getDanmaku(subtitles);
      }
    }
  }

  // 获取弹幕
  Future getDanmaku(List subtitles) async {
    if (subtitles.isNotEmpty) {
      for (var i in subtitles) {
        final Map<String, dynamic> res = await VideoHttp.getSubtitleContent(
          i.subtitleUrl,
        );
        i.content = res['content'];
        i.body = res['body'];
      }
    }
  }

  setSubtitleContent() {
    plPlayerController.subtitleContent.value = '';
    plPlayerController.subtitles.value = subtitles;
  }

  clearSubtitleContent() {
    plPlayerController.subtitleContent.value = '';
    plPlayerController.subtitles.value = [];
  }

  /// 发送弹幕
  void showShootDanmakuSheet() {
    final TextEditingController textController = TextEditingController();
    bool isSending = false; // 追踪是否正在发送
    showDialog(
      context: Get.context!,
      builder: (BuildContext context) {
        // TODO: 支持更多类型和颜色的弹幕
        return AlertDialog(
          title: const Text('发送弹幕'),
          content: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
            return TextField(
              controller: textController,
            );
          }),
          actions: [
            TextButton(
              onPressed: () => Get.back(),
              child: Text(
                '取消',
                style: TextStyle(color: Theme.of(context).colorScheme.outline),
              ),
            ),
            StatefulBuilder(
                builder: (BuildContext context, StateSetter setState) {
              return TextButton(
                onPressed: isSending
                    ? null
                    : () async {
                        final String msg = textController.text;
                        if (msg.isEmpty) {
                          SmartDialog.showToast('弹幕内容不能为空');
                          return;
                        } else if (msg.length > 100) {
                          SmartDialog.showToast('弹幕内容不能超过100个字符');
                          return;
                        }
                        setState(() {
                          isSending = true; // 开始发送，更新状态
                        });
                        //修改按钮文字
                        // SmartDialog.showToast('弹幕发送中,\n$msg');
                        final dynamic res = await DanmakaHttp.shootDanmaku(
                          oid: cid.value,
                          msg: textController.text,
                          bvid: bvid,
                          progress:
                              plPlayerController.position.value.inMilliseconds,
                          type: 1,
                        );
                        setState(() {
                          isSending = false; // 发送结束，更新状态
                        });
                        if (res['status']) {
                          SmartDialog.showToast('发送成功');
                          // 发送成功，自动预览该弹幕，避免重新请求
                          // TODO: 暂停状态下预览弹幕仍会移动与计时，可考虑添加到dmSegList或其他方式实现
                          plPlayerController.danmakuController?.addItems([
                            DanmakuItem(
                              msg,
                              color: Colors.white,
                              time: plPlayerController
                                  .position.value.inMilliseconds,
                              type: DanmakuItemType.scroll,
                              isSend: true,
                            )
                          ]);
                          Get.back();
                        } else {
                          SmartDialog.showToast('发送失败，错误信息为${res['msg']}');
                        }
                      },
                child: Text(isSending ? '发送中...' : '发送'),
              );
            })
          ],
        );
      },
    );
  }

  void updateCover(String? pic) {
    if (pic != null) {
      cover.value = videoItem['pic'] = pic;
    }
  }

  void onControllerCreated(ScrollController controller) {
    replyScrollController = controller;
  }

  void onTapTabbar(int index) {
    if (tabCtr.animation!.isCompleted && index == 1 && tabCtr.index == 1) {
      replyScrollController?.animateTo(0,
          duration: const Duration(milliseconds: 300), curve: Curves.ease);
    }
  }

  void toggeleWatchLaterVisible(bool val) {
    if (sourceType.value == 'watchLater' || sourceType.value == 'fav') {
      isWatchLaterVisible.value = !isWatchLaterVisible.value;
    }
  }

  // 获取稍后再看列表
  Future fetchMediaList() async {
    final Map argMap = Get.arguments;
    var count = argMap['count'];
    var res = await UserHttp.getMediaList(
      type: 2,
      bizId: userInfo.mid,
      ps: count,
    );
    if (res['status']) {
      mediaList = res['data'].reversed.toList();
    } else {
      SmartDialog.showToast(res['msg']);
    }
  }

  // 稍后再看面板展开
  showMediaListPanel() {
    replyReplyBottomSheetCtr =
        scaffoldKey.currentState?.showBottomSheet((BuildContext context) {
      return MediaListPanel(
        sheetHeight: sheetHeight.value,
        mediaList: mediaList,
        changeMediaList: changeMediaList,
        panelTitle: watchLaterTitle.value,
        bvid: bvid,
        mediaId: Get.arguments['mediaId'],
        hasMore: mediaList.length != Get.arguments['count'],
      );
    });
    replyReplyBottomSheetCtr?.closed.then((value) {
      isWatchLaterVisible.value = true;
    });
  }

  // 切换稍后再看
  Future changeMediaList(bvidVal, cidVal, aidVal, coverVal) async {
    final VideoIntroController videoIntroCtr =
        Get.find<VideoIntroController>(tag: heroTag);
    bvid = bvidVal;
    oid.value = aidVal ?? IdUtils.bv2av(bvid);
    cid.value = cidVal;
    danmakuCid.value = cidVal;
    cover.value = coverVal;
    queryVideoUrl();
    clearSubtitleContent();
    await getSubtitle();
    setSubtitleContent();
    // 重新请求评论
    try {
      /// 未渲染回复组件时可能异常
      final VideoReplyController videoReplyCtr =
          Get.find<VideoReplyController>(tag: heroTag);
      videoReplyCtr.aid = aidVal;
      videoReplyCtr.queryReplyList(type: 'init');
    } catch (_) {}
    videoIntroCtr.lastPlayCid.value = cidVal;
    videoIntroCtr.bvid = bvidVal;
    replyReplyBottomSheetCtr!.close();
    await videoIntroCtr.queryVideoIntro();
  }

  // 获取收藏夹视频列表
  Future queryFavVideoList() async {
    final Map argMap = Get.arguments;
    var mediaId = argMap['mediaId'];
    var oid = argMap['oid'];
    var res = await UserHttp.parseFavVideo(
      mediaId: mediaId,
      oid: oid,
      bvid: bvid,
    );
    if (res['status']) {
      mediaList = res['data'];
    }
  }

  // 监听tabBarView切换
  void onTabChanged() {
    isWatchLaterVisible.value = tabCtr.index == 0;
  }

  @override
  void onClose() {
    super.onClose();
    tabCtr.removeListener(() {
      onTabChanged();
    });
  }
}
