import 'dart:async';
import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dsbridge_flutter/dsbridge_flutter.dart';
import 'package:electronic_assistant/base/base_controller.dart';
import 'package:electronic_assistant/data/consts/event_report_id.dart';
import 'package:electronic_assistant/data/repositories/account_repository.dart';
import 'package:electronic_assistant/data/repositories/task_repository.dart';
import 'package:electronic_assistant/handler/event_handler.dart';
import 'package:electronic_assistant/module/chat/view.dart';
import 'package:electronic_assistant/module/login/view.dart';
import 'package:electronic_assistant/module/record/record_handler.dart';
import 'package:electronic_assistant/module/store/view.dart';
import 'package:electronic_assistant/module/talk/mindmap/mind_util.dart';
import 'package:electronic_assistant/module/talk/summary/view.dart';
import 'package:electronic_assistant/module/talk/todo/controller.dart';
import 'package:electronic_assistant/module/talk/todo/view.dart';
import 'package:electronic_assistant/resource/assets.gen.dart';
import 'package:electronic_assistant/resource/colors.gen.dart';
import 'package:electronic_assistant/resource/string.gen.dart';
import 'package:electronic_assistant/router/app_pages.dart';
import 'package:electronic_assistant/utils/audio_picker_utils.dart';
import 'package:electronic_assistant/utils/error_handler.dart';
import 'package:electronic_assistant/utils/expand.dart';
import 'package:electronic_assistant/utils/file_upload_check_helper.dart';
import 'package:electronic_assistant/utils/mmkv_util.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:just_audio/just_audio.dart';
import 'package:share_plus/share_plus.dart';
import 'package:wakelock_plus/wakelock_plus.dart';

import '../../data/api/request/agenda_update_bean.dart';
import '../../data/bean/agenda.dart';
import '../../data/bean/agenda_list_all_bean.dart';
import '../../data/bean/talks.dart';
import '../../data/bean/template_bean.dart';
import '../../data/repositories/agenda_repository.dart';
import '../../data/repositories/talk_repository.dart';
import '../../dialog/add_agenda_dialog.dart';
import '../../dialog/alert_dialog.dart';
import '../../dialog/loading_dialog.dart';
import '../../dialog/rename_dialog.dart';
import '../../dialog/talk_share_dialog.dart';
import '../../utils/common_utils.dart';
import '../../utils/event_bus.dart';
import '../../utils/system_share_util.dart';
import '../../utils/toast_util.dart';
import 'package:webview_flutter/webview_flutter.dart';

import 'mindmap/view.dart';
import 'original/view.dart';

class TalkController extends BaseController {
  static const String argumentItem = 'argument_item';
  static const String argumentTalkId = 'argument_talk_id';
  static const String argumentEventTag = 'argument_event_tag';
  final String uploadNoPrompts = "UPLOAD_NO_PROMPTS";

  final Rxn<TalkBean> talkBean = Rxn();

  StreamSubscription? _talkUploadListener;
  final RxDouble uploadProgress = RxDouble(0);

  final isShowElectricLow = false.obs;

  bool isAudioLoading = false;

  final double sliderMax = 1;

  bool? audioFileIsExist;

  bool? isUploadedFile;

  Rxn<bool> isUploading = Rxn();

  final isAudioPlaying = false.obs;

  final audioProgressValue = 0.0.obs;

  final audioDuration = Duration.zero.obs;

  final agendaOriginalAllList = <AgendaListAllBean>[];

  final agendaAllList = <AgendaListAllBean>[].obs;

  final _isEditModel = false.obs;

  final defaultIndex = 0;

  final Rxn<TalkBarBean> checkTabBean = Rxn();

  final List<TalkBarBean> tabBeans = [];

  final List<Widget> pages = [];

  final isInitializedView = false.obs;

  bool get isEditModel => _isEditModel.value;

  RxBool get isEditModelRx => _isEditModel;

  final _audioPlayer = AudioPlayer();

  StreamSubscription? _talkBeanListener;

  TextEditingController? _agendaContentController;
  TextEditingController? _agendaNameController;

  TextEditingController get agendaContentController {
    _agendaContentController ??= TextEditingController();
    return _agendaContentController!;
  }

  TextEditingController get agendaNameController {
    _agendaNameController ??= TextEditingController();
    return _agendaNameController!;
  }

  String? paramId;
  String? eventTag;

  bool isLocalFileHas = false;

  final Rxn<Duration> playingDuration = Rxn();

  bool isFirstRequestTask = true;

  //模板
  Rxn<List<TemplateBean>?> templateList = Rxn();

  Rxn<int> templateSelectId = Rxn();

  final RxBool isShowMindFullScreen = false.obs;

  //模板最大数量
  int? maxTemplateCount;

  final mindFullDuration = const Duration(milliseconds: 250);

  GlobalKey headGlobalKey = GlobalKey();
  GlobalKey bottomGlobalKey = GlobalKey();

  double? _bottomViewHeight;
  final RxnDouble _headViewHeight = RxnDouble();

  double? get headViewHeight => _headViewHeight.value;

  final DWebViewController webViewController =
      MindUtil.createMindWebViewController();

  final Rxn<DWebViewController> _temporaryController = Rxn();

  DWebViewController? get temporaryController => _temporaryController.value;

  RxBool isShowMindMap = false.obs;

  @override
  void onInit() {
    super.onInit();
    _getArguments();
    _analyticWebVersion();
  }

  Future<void> _analyticWebVersion() async {
    if (Platform.isAndroid) {
      String? userAgent = await webViewController.getUserAgent();
      bool shouldShowMindMap = true;
      String? version;
      if (userAgent != null) {
        RegExp regExp = RegExp(r'Chrome/(\d+)\.');
        Match? match = regExp.firstMatch(userAgent);
        if (match != null) {
          version = match.group(1) ?? '';
          if (version.isNotEmpty && isNumeric(version)) {
            int versionNum = int.parse(version);
            shouldShowMindMap = versionNum > 92;
          } else {
            shouldShowMindMap = false;
          }
        }
      } else {
        shouldShowMindMap = false;
      }
      _setMindMap(shouldShowMindMap, version: version);
    } else {
      _setMindMap(true);
    }
  }

  void _setMindMap(bool isShow, {String? version}) {
    isShowMindMap.value = isShow;
    String? talkId = talkBean.value != null ? talkBean.value!.id : paramId;
    if (isShow) {
      pages.assignAll([
        SummaryView(talkId),
        MindMapView(talkId),
        TodoView(talkId),
        OriginalView(talkId),
      ]);
      tabBeans.assignAll([
        TalkBarBean(TalkBarType.summary, StringName.talkTabSummary.tr, true),
        TalkBarBean(TalkBarType.mindMap, StringName.talkMindMap.tr, false,
            isDisallowScroll: true),
        TalkBarBean(TalkBarType.myTask, StringName.talkTabMyTask.tr, true),
        TalkBarBean(TalkBarType.original, StringName.talkTabOriginal.tr, false)
      ]);
      EventHandler.report(EventId.event_101401, params: {EventId.id: version});
    } else {
      pages.assignAll([
        SummaryView(talkId),
        TodoView(talkId),
        OriginalView(talkId),
      ]);
      tabBeans.assignAll([
        TalkBarBean(TalkBarType.summary, StringName.talkTabSummary.tr, true),
        TalkBarBean(TalkBarType.myTask, StringName.talkTabMyTask.tr, true),
        TalkBarBean(TalkBarType.original, StringName.talkTabOriginal.tr, false)
      ]);
      EventHandler.report(EventId.event_101402, params: {EventId.id: version});
    }
    checkTabBean.value = tabBeans[defaultIndex];
    isInitializedView.value = true;
  }

  @override
  void onReady() {
    super.onReady();
    _initAudioPlayer();
    eventReport(EventId.event_101001, params: {EventId.id: eventTag});
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _bottomViewHeight = bottomGlobalKey.currentContext?.size?.height;
      _headViewHeight.value = headGlobalKey.currentContext?.size?.height;
    });
  }

  double getBottomViewHeight() {
    if (_bottomViewHeight == null) {
      return -250.h;
    }
    return -_bottomViewHeight!;
  }

  void eventReport(String eventId, {Map<String, dynamic>? params}) {
    if (talkBean.value == null || talkBean.value?.isExample == true) {
      return;
    }
    EventHandler.report(eventId, params: params);
  }

  void _initAudioPlayer() {
    _audioPlayer.playerStateStream.listen((playerState) {
      if (playerState.processingState == ProcessingState.loading ||
          playerState.processingState == ProcessingState.buffering) {
        isAudioLoading = true;
        debugPrint('音频load = true');
      } else {
        debugPrint('音频load = false');
        isAudioLoading = false;
        if (playerState.processingState == ProcessingState.completed) {
          _audioPlayer.stop();
          _audioPlayer.seek(Duration.zero);
          isAudioPlaying.value = false;
          debugPrint('音频 播放结束了');
        }
      }
      isAudioPlaying.value = playerState.playing;
    }, onError: (Object e, StackTrace stackTrace) {
      debugPrint('音频加载异常 == $e');
    });

    _audioPlayer.durationStream.listen((duration) {
      if (duration != null) {
        debugPrint('音频总播放时长 == ${duration.inMilliseconds}');
        audioDuration.value = duration;
      }
    });

    _audioPlayer.positionStream.listen((duration) {
      debugPrint('音频播放时长 == ${duration.inMilliseconds}');
      playingDuration.value = duration;
      if (audioDuration.value.inMilliseconds > 0) {
        audioProgressValue.value =
            (duration.inMilliseconds / audioDuration.value.inMilliseconds)
                .clamp(0.0, sliderMax);
      }
    });
  }

  void _dealTalk(TalkBean? bean) async {
    debugPrint('talkBean == $bean');
    String? id = bean?.id;
    if (id == null) {
      return;
    }
    _loadAudioFile(bean);
    if (bean?.status.value == TalkStatus.notAnalysis) {
      setUploadingProgress(id);
    }
    if (bean?.status.value == TalkStatus.notAnalysis &&
        talkRepository.isUploadingTalk(id)) {
      isUploading.value = true;
    } else {
      isUploading.value = false;
    }
  }

  void setUploadingProgress(String id) {
    talkRepository.getUploadProgress(id).listen((progress) {
      uploadProgress.value = (progress * 20).toFormattedDouble(1);
    });
  }

  Future<void> _loadAudioFile(TalkBean? bean, {bool? loadPlay}) async {
    try {
      Uri? uri;
      if (bean?.isExample == true && bean?.audioUrl != null) {
        uri = Uri.parse(bean!.audioUrl!);
      } else {
        File? file = await getFileByTalk(talkBean.value);
        if (file?.existsSync() == true) {
          uri = file?.uri;
        }
      }
      if (uri == null) {
        throw '音频文件不存在';
      }
      await _audioPlayer.setAudioSource(AudioSource.uri(uri));
      if (loadPlay == true) {
        clickPlayAudio();
      }
      audioFileIsExist = true;
    } catch (e) {
      audioFileIsExist = false;
      debugPrint('音频设置异常 == $e');
    }
  }

  void _getArguments() {
    TalkBean? bean = parameters?[argumentItem];
    if (bean != null) {
      talkBean.value = bean;
      debugPrint('talkBean == ${bean.summary}');
      _dealTalk(bean);
    } else {
      paramId = parameters?[argumentTalkId];
      if (paramId != null) {
        talkRepository.talkInfo(paramId!).then((data) {
          talkBean.value = data.talkInfo;
          _dealTalk(data.talkInfo);
        }).catchError((error) {
          ErrorHandler.toastError(error);
        });
      }
    }
    eventTag = parameters?[argumentEventTag];
  }

  void updateProgress(double value) {
    final newPosition = Duration(
        milliseconds: (value * audioDuration.value.inMilliseconds).toInt());
    _audioPlayer.seek(newPosition);
  }

  void clickPlayAudio() async {
    if (audioFileIsExist != true && isLocalFileHas == false) {
      ToastUtil.showToast(StringName.talkFileNotFind.tr);
      return;
    }
    if (isLocalFileHas == true &&
        audioFileIsExist == false &&
        !await AudioPickerUtils.hasPermission()) {
      bool has = await AudioPickerUtils.requestPermissionExtend();
      if (has == false) {
        ToastUtil.showToast(StringName.authorizationFailed.tr);
        return;
      }
      //重新加载
      _loadAudioFile(talkBean.value, loadPlay: true);
      return;
    }
    if (isAudioLoading) {
      ToastUtil.showToast(StringName.talkAudioLoading.tr);
      return;
    }
    if (_audioPlayer.playing) {
      _audioPlayer.pause();
      isAudioPlaying.value = false;
    } else {
      _audioPlayer.play();
      isAudioPlaying.value = true;
    }
  }

  void _checkFileSizeAndNet() async {
    String? id = talkBean.value?.id;
    if (id == null) {
      return;
    }
    File? file = await getFileByTalk(talkBean.value);
    if (isLocalFileHas == true &&
        audioFileIsExist == false &&
        !await AudioPickerUtils.hasPermission()) {
      bool has = await AudioPickerUtils.requestPermissionExtend();
      if (has == false) {
        ToastUtil.showToast(StringName.authorizationFailed.tr);
        return;
      }
      //重新上传
      _checkFileSizeAndNet();
      return;
    }
    if (file == null || !file.existsSync()) {
      ToastUtil.showToast(StringName.talkUploadFileNotExist.tr);
      return;
    }
    bool isCheckRemind = KVUtil.getBool(uploadNoPrompts, false);
    if (isCheckRemind) {
      _requestAnalyze(file);
      return;
    }
    //如果文件大小低于250MB 不弹窗提醒
    if (file.lengthSync() < 250 * 1024 * 1024) {
      _requestAnalyze(file);
      return;
    }

    final List<ConnectivityResult> connectivityResult =
        await (Connectivity().checkConnectivity());
    if (connectivityResult.contains(ConnectivityResult.wifi)) {
      _requestAnalyze(file);
    } else {
      _showTrafficRemindDialog(file.lengthSync().toReadableSize(),
          confirmOnTap: (isCheckRemind) {
        if (isCheckRemind) {
          KVUtil.putBool(uploadNoPrompts, true);
        }
        _requestAnalyze(file);
      });
    }
  }

  void _showTrafficRemindDialog(String holderTxt,
      {void Function(bool isCheckRemind)? confirmOnTap}) {
    final remindTrafficConsume = false.obs;

    Widget getSelectIcon() {
      return Obx(() {
        return remindTrafficConsume.value
            ? Assets.images.iconSelectTrue.image()
            : Assets.images.iconSelectFalse.image();
      });
    }

    Assets.images.iconSelectTrue.image();

    EAAlertDialog.show(
        contentWidget: Column(
          children: [
            Text(
              StringName.talkTrafficRemindTitle.tr
                  .replacePlaceholders([holderTxt]),
              style:
                  TextStyle(fontSize: 15.sp, color: ColorName.primaryTextColor),
            ),
            SizedBox(height: 8.h),
            GestureDetector(
              onTap: () {
                remindTrafficConsume.value = !remindTrafficConsume.value;
              },
              child: IntrinsicWidth(
                child: Row(
                  children: [
                    SizedBox(width: 20.w, height: 20.w, child: getSelectIcon()),
                    SizedBox(width: 5.w),
                    Text(
                      StringName.talkTrafficRemindTips.tr,
                      style: TextStyle(
                          fontSize: 15.sp, color: ColorName.tertiaryTextColor),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
        cancelText: StringName.cancel.tr,
        confirmText: StringName.sure.tr,
        confirmOnTap: () {
          confirmOnTap?.call(remindTrafficConsume.value);
        });
  }

  void checkCanAnalyze() {
    String? id = talkBean.value?.id;
    double? duration = talkBean.value?.duration;
    if (id == null || duration == null) {
      return;
    }
    eventReport(EventId.event_101002);
    talkRepository.checkElectric(duration).then((data) {
      if (data.enough) {
        //检查网络以及文件大小
        _checkFileSizeAndNet();
      } else {
        ToastUtil.showToast(StringName.talkAnalyseLowToast.tr);
        isShowElectricLow.value = true;
      }
    }).catchError((error) {
      ErrorHandler.toastError(error);
    });
  }

  void _requestAnalyze(File file) {
    String? talkId = talkBean.value?.id;
    double? duration = talkBean.value?.duration;

    if (talkId == null || duration == null || isUploadedFile == true) {
      return;
    }
    isUploading.value = true;
    WakelockPlus.enable();
    talkRepository.uploadTalkFile(talkId, duration, file).then((taskId) {
      isUploadedFile = true;
      isUploading.value = false;
      talkBean.value?.progressContent.value =
          StringName.talkUploadingFileTip.tr;
      talkBean.value?.progress.value = 20;
      talkBean.value?.status.value = TalkStatus.analysing;
      taskRepository.addTask(taskId);
    }).catchError((error) {
      isUploading.value = false;
      ErrorHandler.toastError(error);
    }).whenComplete(() => WakelockPlus.disable());
  }

  void refreshAgendaAllData({bool isForceRefresh = false}) {
    String? id = talkBean.value?.id;
    if (id == null || (!isForceRefresh && agendaAllList.isNotEmpty)) {
      return;
    }
    agendaRepository.agendaListAll(id).then((agenda) {
      isFirstRequestTask = false;
      agendaAllList.clear();
      agendaOriginalAllList.clear();
      if (agenda.list != null) {
        agendaOriginalAllList.addAll(
            agenda.list!.map((item) => AgendaListAllBean.from(item)).toList());
        agendaAllList.addAll(agenda.list!);
      }
    });
  }

  void clickAIAnalysis() async {
    if (!await checkLogin()) {
      return;
    }
    if (talkBean.value != null) {
      eventReport(EventId.event_101003);
      ChatPage.startByTalk(
          talkBean.value!.isExample == true
              ? ChatFromType.fromTalkExample
              : ChatFromType.fromTalkDetail,
          talkBean.value!);
    }
  }

  void onGoElectricStore() {
    StorePage.start(fromType: StoreFromType.analyse);
    Future.delayed(const Duration(milliseconds: 250), () {
      isShowElectricLow.value = false;
    });
  }

  void onEditModelClick() async {
    if (!await checkLogin()) {
      return;
    }
    _isEditModel.value = true;
    if (_audioPlayer.playing) {
      _audioPlayer.pause();
      isAudioPlaying.value = false;
    }
  }

  void updateTabIndex(int index) {
    checkTabBean.value = tabBeans[index];
  }

  void onEditCancel() {
    _isEditModel.value = false;
    agendaAllList.assignAll(agendaOriginalAllList
        .map((item) => AgendaListAllBean.from(item))
        .toList());
  }

  void onEditDoneClick() {
    if (talkBean.value == null) {
      return;
    }
    List<AgendaUpdateBean> list = [];
    for (AgendaListAllBean item in agendaAllList) {
      if (item.list != null) {
        for (Agenda agenda in item.list!) {
          list.add(AgendaUpdateBean(agenda.id, agenda.name, agenda.content));
        }
      }
    }
    agendaRepository.agendaUpdate(talkBean.value!.id, list).then((data) {
      refreshAgendaAllData(isForceRefresh: true);
      eventBus.emit(TodoController.refreshTalkMineTask);
      isEditModelRx.value = false;
    }).catchError((error) {
      ErrorHandler.toastError(error);
    });
  }

  void removeTalkAgenda(List<Agenda>? list, Agenda agenda) {
    list?.remove(agenda);
    agendaAllList.refresh();
  }

  void showSingleAddAgendaDialog(BuildContext context) {
    showAddAgendaDialog(context, agendaContentController, agendaNameController,
        list: agendaAllList.map((e) => e.name ?? "").toList(), callback: () {
      if (agendaContentController.text.isEmpty) {
        ToastUtil.showToast(StringName.talkAddAgendaContentHint.tr);
        return;
      }
      if (agendaNameController.text.isEmpty) {
        ToastUtil.showToast(StringName.talkAddAgendaNameHint.tr);
        return;
      }
      Get.back();
      _dealAddProcedureList();
    });
  }

  void _dealAddProcedureList() {
    String name = agendaNameController.text;
    final addItem = Agenda(
      id: "",
      talkId: "",
      name: name,
    );
    addItem.content = agendaContentController.text;
    for (AgendaListAllBean item in agendaAllList) {
      if (item.name == name) {
        List<Agenda> list = item.list ?? [];
        list.add(addItem);
        item.list = list;
        agendaAllList.refresh();
        agendaContentController.clear();
        agendaNameController.clear();
        return;
      }
    }
    agendaAllList.add(AgendaListAllBean(name: name, list: [addItem]));
    agendaContentController.clear();
    agendaNameController.clear();
  }

  Future<File?> getFileByTalk(TalkBean? bean) async {
    isLocalFileHas = false;
    if (bean == null) {
      return null;
    }
    if (bean.uploadType == TalkUploadType.localUpload) {
      String? audioId =
          FileUploadCheckHelper.getLocalAudioId(bean.localAudioUrl);
      if (audioId != null && audioId.isNotEmpty) {
        isLocalFileHas = true;
        return await AudioPickerUtils.getAssetFile(audioId);
      } else {
        return await FileUploadCheckHelper.getChoiceUploadFile(bean.id);
      }
    } else {
      return await RecordHandler.getRecordFile(bean.id);
    }
  }

  Future<bool> checkLogin() async {
    if (!accountRepository.isLogin.value) {
      bool isLogin = await LoginPage.start(fromType: LoginFromType.talkDetail);
      if (isLogin) {
        backToSpecificPage(RoutePath.mainTab);
      }
      return false;
    }
    return true;
  }

  List<ShareTalkType> _getShareToType(bool isShowMindMap) {
    List<ShareTalkType> shareToType = [ShareTalkType.summary];
    if (isShowMindMap) {
      shareToType.add(ShareTalkType.mindMap);
    }
    shareToType.add(ShareTalkType.original);
    return shareToType;
  }

  void onShareClick() async {
    if (!await checkLogin()) {
      return;
    }
    if (talkBean.value?.status.value != TalkStatus.analysisSuccess) {
      return;
    }
    eventReport(EventId.event_101004);
    showTalkShareDialog(talkBean.value?.title.value,
        shareToType: _getShareToType(isShowMindMap.value),
        callback: (type, shareTo, fileName, tag) async {
      try {
        await isInstalled(shareTo);
        if (type == ShareTalkType.summary || type == ShareTalkType.original) {
          _shareSummaryOrOriginal(
              talkBean.value!.id, fileName, type, shareTo, tag);
        } else if (type == ShareTalkType.mindMap) {
          _shareMindMap(fileName, talkBean.value?.summary.value, shareTo, tag);
        }
      } catch (error) {
        if (error is SystemShareException) {
          ToastUtil.showToast(error.message);
        } else {
          ErrorHandler.toastError(error);
        }
      }
    });
  }

  Future<bool> isInstalled(ShareTo shareTo) async {
    if (shareTo == ShareTo.wechat) {
      bool isInstalled =
          await SystemShareUtil.isInstalled(SystemShareUtil.wechatPageName);
      if (!isInstalled) {
        throw SystemShareException('未安装微信');
      }
    } else if (shareTo == ShareTo.qq) {
      bool isInstalled =
          await SystemShareUtil.isInstalled(SystemShareUtil.qqPageName);
      if (!isInstalled) {
        throw SystemShareException('未安装QQ');
      }
    }
    // else if(shareTo == ShareTo.ios){
    //    //ios不用判断
    // }
    return true;
  }

  void _shareMindMap(
      String title, String? summary, ShareTo shareTo, String tag) {
    LoadingDialog.show(StringName.mindMapExport.tr, backDismiss: true);
    if (_temporaryController.value != null) {
      _temporaryController.value?.dispose();
      _temporaryController.value = null;
    }
    final temporaryController = MindUtil.createMindWebViewController();

    VoidCallback? errorCallback = () {
      LoadingDialog.hide();
      temporaryController.dispose();
      ToastUtil.showToast('思维导图导出失败');
    };

    try {
      Future.delayed(const Duration(seconds: 10), () {
        throw Exception('导出超时');
      });
      _temporaryController.value = temporaryController;
      temporaryController.loadFlutterAsset(Assets.html.indexExport);
      temporaryController.setNavigationDelegate(
        NavigationDelegate(
          onHttpError: (error) {
            errorCallback?.call();
            errorCallback = null;
          },
          // onWebResourceError: (error) {
          //   errorCallback?.call();
          //   errorCallback = null;
          // },
          onPageFinished: (String url) {
            temporaryController.callHandler(MindUtil.functionToJsExport,
                args: [title, summary], handler: (value) async {
              if (value == null) {
                throw Exception('data is null');
              }
              File file = await MindUtil.saveToFile(value, title);
              temporaryController.dispose();
              if (shareTo == ShareTo.wechat) {
                await SystemShareUtil.shareSystemFile(
                    SystemShareUtil.wechatPageName, file.path,
                    shareTitle: '分享到微信', shareFileType: 'image/*');
              } else if (shareTo == ShareTo.qq) {
                await SystemShareUtil.shareSystemFile(
                    SystemShareUtil.qqPageName, file.path,
                    shareTitle: '分享到QQ', shareFileType: 'image/*');
              } else if (shareTo == ShareTo.ios) {
                await Share.shareXFiles([XFile(file.path)], subject: title);
              } else {
                throw Exception('不支持该分享方式');
              }
              SmartDialog.dismiss(tag: tag);
              LoadingDialog.hide();
            });
          },
        ),
      );
    } catch (e) {
      errorCallback?.call();
      errorCallback = null;
    }
  }

  void _shareSummaryOrOriginal(String id, String fileName, ShareTalkType type,
      ShareTo shareTo, String tag) async {
    talkRepository.talkExport(id, fileName, type).then((file) async {
      if (shareTo == ShareTo.ios) {
        await Share.shareXFiles([XFile(file.path)], subject: fileName);
      } else if (shareTo == ShareTo.wechat) {
        await SystemShareUtil.shareSystemFile(
            SystemShareUtil.wechatPageName, file.path,
            shareTitle: '分享到微信', shareFileType: 'text/*');
      } else if (shareTo == ShareTo.qq) {
        await SystemShareUtil.shareSystemFile(
            SystemShareUtil.qqPageName, file.path,
            shareTitle: '分享到QQ', shareFileType: 'text/*');
      }
      SmartDialog.dismiss(tag: tag);
    }).catchError((error) {
      throw error;
    });
  }

  void seekTo(int? startMs) {
    if (startMs == null) {
      return;
    }
    _audioPlayer.seek(Duration(milliseconds: startMs));
  }

  Future<TalkBean?> refreshTalkDetail() async {
    String? id = talkBean.value?.id;
    if (id == null) {
      return null;
    }
    return talkRepository.talkInfo(id).then((data) {
      var bean = data.talkInfo;
      if (bean != null) {
        if (talkBean.value == null) {
          talkBean.value = data.talkInfo;
        } else {
          talkBean.value?.updateBean(bean);
        }
        maxTemplateCount = data.maxTemplateCount;
        templateSelectId.value = bean.templateId;
      }
      templateList.value = data.templateList;
      return bean;
    });
  }

  void onEditTitleClick() {
    reNameDialog(StringName.talkRenameTitle.tr, talkBean.value?.title.value,
        hintTxt: StringName.talkRenameTitleHint.tr,
        maxLength: 15, returnBuilder: (newName) {
      talkRepository.talkRename(talkBean.value!.id, newName).then((data) {
        talkBean.value?.title.value = newName;
      }).catchError((error) {
        ErrorHandler.toastError(error);
      });
    });
  }

  void onExitMindFullScreen() {
    isShowMindFullScreen.value = false;
  }

  void selectTemplate(TemplateBean bean) {
    String? id = talkBean.value?.id;
    int? templateId = bean.id;
    if (talkBean.value?.templateId == templateId) {
      return;
    }
    if (id == null || templateId == null) {
      ToastUtil.showToast('谈话信息获取异常，请退出页面重试！');
      return;
    }
    LoadingDialog.show('生成总结中...');

    talkRepository
        .talkSummaryGenerate(id, templateId)
        .timeout(const Duration(seconds: 60))
        .then((data) {
      LoadingDialog.hide();
      talkBean.value?.updateBean(data);
      templateSelectId.value = templateId;
      ToastUtil.showToast('生成成功', displayType: SmartToastType.last);
    }).catchError((error) {
      LoadingDialog.hide();
      ToastUtil.showToast('生成失败');
    });
  }

  @override
  void onClose() {
    super.onClose();
    _talkUploadListener?.cancel();
    _talkBeanListener?.cancel();
    _audioPlayer.dispose();
    _agendaContentController?.dispose();
    _agendaNameController?.dispose();
  }
}

enum TalkBarType { summary, mindMap, myTask, original }

class TalkBarBean {
  final TalkBarType type;

  final String title;

  final bool isShowEdit;

  final bool? isDisallowScroll;

  TalkBarBean(this.type, this.title, this.isShowEdit, {this.isDisallowScroll});
}
