import 'dart:io';

import 'package:auto_route/auto_route.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:eitc_erm_dental_flutter/app_router.gr.dart';
import 'package:eitc_erm_dental_flutter/db_util.dart';
import 'package:eitc_erm_dental_flutter/entity/db/local_patient_info.dart';
import 'package:eitc_erm_dental_flutter/exts.dart';
import 'package:eitc_erm_dental_flutter/global.dart';
import 'package:eitc_erm_dental_flutter/pages/view/widget/video_patient_info_bar.dart';
import 'package:eitc_erm_dental_flutter/sp_util.dart';
import 'package:eitc_erm_dental_flutter/vm/global_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:just_audio/just_audio.dart';
import 'package:wakelock_plus/wakelock_plus.dart';

import '../../funcs.dart';
import '../../generated/assets.dart';
import 'widget/video_operation_view.dart';

///视频查看页面
@RoutePage(name: "videoViewRoute")
class VideoViewPage extends ConsumerStatefulWidget {
  const VideoViewPage({super.key});

  @override
  ConsumerState createState() => _VideoViewPageState();
}

class _VideoViewPageState extends ConsumerState<VideoViewPage>
    with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
  ///纹理ID
  int _textureId = -1;

  ///视频控制界面控制器
  final VideoOperationViewController _operationViewController =
      VideoOperationViewController();

  ///上一次拍照的路径
  String _lastTakePhotoPath = "";

  ///音频播放器
  final AudioPlayer _takePhotoAudioPlayer = AudioPlayer();

  ///是否已弹出
  bool _hasPoped = false;

  ///已选择的咨询人信息
  LocalPatientInfo? _patientInfo;

  ///wifi名称
  String _wifiName = "";

  ///设备型号
  String _deviceModel = "";

  ///当前牙齿区域
  String _currentToothArea = "";

  ///是否可以设备拍照
  bool _canDeviceTakePhoto = true;

  ///是否正在选择牙齿区域
  bool _isSelectingToothArea = false;

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addObserver(this);

    //保持屏幕常亮
    WakelockPlus.enable();
    //开启屏幕旋转
    screenEnableRotate();
    //设置MethodChannel回调
    videoChannel.setMethodCallHandler(_methodCallHandler);
    //音频播放器加载资源
    _takePhotoAudioPlayer.setAsset(Assets.audiosTakePhoto);
    //开始视频
    _startVideo();

    //监听连接状态变化
    ref.listenManual(deviceConnectStatusProvider(videoChannel), (_, bo) {
      if (!bo) {
        logd("连接丢失");
        _popSelf();
      }
    });
    //初始化数据
    _initData();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      //选择牙齿区域
      _selectToothArea();
    });
  }

  ///初始化数据
  void _initData() async {
    //初始化咨询人信息,设备型号
    await Future.wait([_initPatientInfo(), _initDeviceModel()]);
    setState(() {});
  }

  ///初始化咨询人信息
  Future _initPatientInfo() async {
    if (selectedPatientId < 0) {
      return;
    }
    LocalPatientInfo? info =
        await DbUtil.instance.getLocalPatientById(selectedPatientId);
    if (info != null) {
      _patientInfo = info;
    }
  }

  ///初始化设备型号
  Future _initDeviceModel() async {
    String? name = await getWifiName();
    if (name.isNullOrEmpty) {
      return;
    }
    _wifiName = name!;
    _deviceModel = await getDeviceModel() ?? "";
    logd("初始化设备型号,wifiName=$_wifiName,deviceModel=$_deviceModel");
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    //关闭屏幕常亮
    WakelockPlus.disable();
    if (!_hasPoped) {
      _stopRecord();
    }
    _stopVideo();
    videoChannel.setMethodCallHandler(null);
    //关闭屏幕旋转
    screenDisableRotate();
    _operationViewController.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (!(state == AppLifecycleState.inactive ||
        state == AppLifecycleState.resumed)) {
      _popSelf();
    }
  }

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      body: SafeArea(
          child: Container(
        color: Colors.black,
        child: Stack(
          children: [
            Center(
              child: _getVideo(),
            ),
            VideoOperationView(
              controller: _operationViewController,
              onTakePhoto: _takePhoto,
              onStartRecord: _startRecord,
              onStopRecord: () => _stopRecord(toPreview: true),
              onStopVideo: _stopVideo,
              area: _currentToothArea,
            ),
            Align(
              alignment: Alignment.topLeft,
              child: _getVideoViewToolBar(),
            )
          ],
        ),
      )),
    );
  }

  void _startVideo() async {
    if (!mounted) {
      return;
    }
    try {
      int result = await videoChannel.invokeMethod("startVideo");
      setState(() {
        _textureId = result;
      });
    } catch (e) {
      showToast(text: getS().showVideoError);
      loge("开始视频失败", error: e);
    }
  }

  void _stopVideo() async {
    logd("停止视频");
    if (_textureId < 0) {
      return;
    }
    _textureId = -1;
    try {
      await videoChannel.invokeMethod("stopVideo");
    } catch (e) {
      loge("停止视频失败", error: e);
    }
  }

  Future<dynamic> _methodCallHandler(MethodCall call) {
    logd(call);
    if (call.method == "onDeviceTakePhoto") {
      _onDeviceTakePhoto(call.arguments);
    }
    return Future.value("");
  }

  ///获取视频Widget
  Widget _getVideo() {
    return OrientationBuilder(builder: (ctx, orientation) {
      if (Platform.isIOS) {
        Size size = MediaQuery.of(context).size;
        double width = size.width;
        double height = size.height;
        videoChannel.invokeMethod(
            orientation == Orientation.landscape
                ? "getLandscapeView"
                : "getPortraitView",
            [width, height]);
        logd("ios,width=$width,height=$height");

        if (orientation == Orientation.landscape) {
          return AspectRatio(
            aspectRatio: 16.0 / 9.0,
            child: Stack(
              children: [
                _getVideoView(true),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: _getPatientInfoBar(orientation),
                )
              ],
            ),
          );
        } else {
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              AspectRatio(
                aspectRatio: 16.0 / 9.0,
                child: _getVideoView(true),
              ),
              _getPatientInfoBar(orientation),
            ],
          );
        }
      } else {
        if (orientation == Orientation.landscape) {
          return AspectRatio(
            aspectRatio: 16.0 / 9.0,
            child: Stack(
              children: [
                _getVideoView(false),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: _getPatientInfoBar(orientation),
                )
              ],
            ),
          );
        } else {
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              AspectRatio(
                aspectRatio: 16.0 / 9.0,
                child: _getVideoView(false),
              ),
              _getPatientInfoBar(orientation)
            ],
          );
        }
      }
    });
  }

  Widget _getVideoView(bool isIos) {
    if (isIos) {
      return UiKitView(
        viewType: "VideoView",
        onPlatformViewCreated: (id) => logd("IOS PlatformView创建,id=$id"),
      );
    } else {
      return _textureId >= 0
          ? Texture(textureId: _textureId)
          : const SizedBox();
    }
  }

  ///获取患者信息条
  Widget _getPatientInfoBar(Orientation orientation) {
    return _operationViewController.isRecording
        ? SizedBox()
        : VideoPatientInfoBar(
            info: _patientInfo,
            orientation: orientation,
            area: _currentToothArea,
            deviceModel: _deviceModel);
  }

  ///获取工具栏
  Widget _getVideoViewToolBar() {
    return Row(
      children: [
        IconButton(
            onPressed: () => _popSelf(true),
            icon: Icon(
              Platform.isAndroid ? Icons.arrow_back : Icons.arrow_back_ios_new,
              color: Colors.white,
            )),
        const Spacer(),
        IconButton(
            onPressed: _gotoSettings,
            icon: const Icon(
              Icons.settings_outlined,
              color: Colors.white,
            )),
      ],
    );
  }

  ///拍照
  void _takePhoto() async {
    if (_operationViewController.isRecording) {
      return;
    }
    try {
      String path = await videoChannel.invokeMethod("takePhoto");
      _showTakePhotoSuccess(path);
    } catch (e) {
      loge("拍照失败", error: e);
      showToast(text: getS().takePhotoFailed);
    }
  }

  ///当设备拍照
  ///IOS平台设备和手机拍照都会调用
  void _onDeviceTakePhoto(dynamic arguments) async {
    if (!_canDeviceTakePhoto || !isCurrentPage) {
      logd("设备拍照,但是不可拍照,返回");
      return;
    }

    _takePhoto();
  }

  void _showTakePhotoSuccess(String newPath) async {
    if (newPath == _lastTakePhotoPath) {
      return;
    }
    logd("拍照成功，path=$newPath");
    _lastTakePhotoPath = newPath;
    showToast(text: getS().takePhotoSuccess);
    _playTakePhotoAudio();
    String area = _currentToothArea;
    if (mounted) {
      setState(() {
        _currentToothArea = "";
        _stopVideo();
      });
      await context.pushRoute(PhotoPreviewRoute(
          info: _patientInfo!,
          path: newPath,
          area: area,
          time: DateTime.now(),
          mobile: "",
          deviceModel: _deviceModel,
          wifi: _wifiName));
      _selectToothArea();
      _startVideo();
    }
  }

  ///开始录像
  void _startRecord() async {
    if (_operationViewController.isRecording) {
      return;
    }
    _canDeviceTakePhoto = false;
    try {
      await videoChannel.invokeMethod(
          "startRecord",
          makeFilePrefix(
              name: _patientInfo?.name ?? "",
              idCard: _patientInfo?.idCardDecrypt ?? "",
              mobile: "",
              area: _currentToothArea,
              wifi: _wifiName,
              time: DateTime.now().millisecondsSinceEpoch,
              userId: await SpUtil.getUserId()));
      _operationViewController.updateRecordingState(true);
      showToast(text: getS().hasStartRecord);
      setState(() {});
    } catch (e) {
      _canDeviceTakePhoto = true;
      _operationViewController.updateRecordingState(false);
      loge("开始录像失败", error: e);
      showToast(text: getS().startRecordFailed);
    }
  }

  ///停止录像
  void _stopRecord({bool toPreview = false}) async {
    if (!_operationViewController.isRecording) {
      return;
    }
    logd("停止录像");
    _canDeviceTakePhoto = true;
    try {
      String path = await videoChannel.invokeMethod("stopRecord");

      if (toPreview) {
        //显示loading延迟停止视频,因为停止录像是异步的,如果在没执行完就停止视频
        //会导致录像文件丢失尾帧信息,播放时没有总时长
        var cancel = BotToast.showLoading(
            crossPage: false,
            clickClose: false,
            backButtonBehavior: BackButtonBehavior.ignore);
        await Future.delayed(Duration(seconds: 1, milliseconds: 500));
        cancel();
        showToast(text: getS().hasStopRecord);
        setState(() {
          _operationViewController.updateRecordingState(false);
          _stopVideo();
        });
        if (mounted) {
          await context.pushRoute(VideoPreviewRoute(
              info: _patientInfo!,
              path: path,
              area: _currentToothArea,
              time: DateTime.now(),
              mobile: "",
              deviceModel: _deviceModel,
              wifi: _wifiName));
          _selectToothArea();
          _startVideo();
        }
      } else {
        _operationViewController.updateRecordingState(false);
        showToast(text: getS().hasStopRecord);
      }
    } catch (e) {
      _operationViewController.updateRecordingState(false);
      loge("停止录像失败", error: e);
      showToast(text: getS().stopRecordFailed);
    }
  }

  ///播放拍照音效
  void _playTakePhotoAudio() async {
    await _takePhotoAudioPlayer.seek(Duration.zero);
    await _takePhotoAudioPlayer.play();
  }

  ///前往设置
  void _gotoSettings() async {
    await context.pushRoute(const DelayShotSettingsRoute());
    if (_hasPoped) {
      return;
    }
    screenEnableRotate();
  }

  ///弹出自身页面
  void _popSelf([bool force = false]) {
    if (force) {
      Navigator.pop(context);
      return;
    }
    if (_hasPoped) {
      return;
    }
    _hasPoped = true;
    _stopRecord();
    //如果是锁屏导致的,dispose会在解锁后才会调用,导致在锁屏期间视频还是播放的,所以这里提前停止
    _stopVideo();
    //如果当前页面是最上层的就是pop,否则remove,否则会导致把后来打开的页面pop但是当前页面还存在的问题
    if (isCurrentPage) {
      logd("视频查看页面pop自身");
      //如果正在选择牙齿区域,先把弹窗pop掉
      if (_isSelectingToothArea) {
        Navigator.pop(context);
      }
      Navigator.pop(context);
    } else {
      logd("视频查看页面remove自身");
      AutoRouter.of(context).removeRoute(context.routeData);
    }
  }

  ///是否是当前页面
  bool get isCurrentPage =>
      AutoRouter.of(context).current.name == VideoViewRoute.name;

  ///选择延迟区域
  void _selectToothArea() async {
    if (!mounted) {
      return;
    }
    _canDeviceTakePhoto = false;
    _isSelectingToothArea = true;
    String? area = await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (ctx) {
          return _getToothSelect(ctx, (String area) {
            showToast(text: getS().hasSelectXx(toothAreaTranslate(area)));
            Navigator.pop(ctx, area);
          });
        });
    _canDeviceTakePhoto = true;
    _isSelectingToothArea = false;
    if (area == null) {
      return;
    }
    setState(() {
      _currentToothArea = area;
    });
  }

  Widget _getToothSelect(
      BuildContext context, void Function(String area) onSelect) {
    return PopScope(
        canPop: false,
        child: FittedBox(
          child: Container(
            margin: EdgeInsets.all(80.r),
            padding: EdgeInsets.symmetric(horizontal: 100.w, vertical: 50.h),
            decoration: BoxDecoration(
                color: Colors.white30,
                borderRadius: BorderRadius.circular(100.r)),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    GestureDetector(
                      child: Image.asset(Assets.imagesToothRt),
                      onTap: () => onSelect(toothAreaRightTop),
                    ),
                    GestureDetector(
                      child: Image.asset(Assets.imagesToothRb),
                      onTap: () => onSelect(toothAreaRightBottom),
                    ),
                  ],
                ),
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    GestureDetector(
                      child: Image.asset(Assets.imagesToothLt),
                      onTap: () => onSelect(toothAreaLeftTop),
                    ),
                    GestureDetector(
                      child: Image.asset(Assets.imagesToothLb),
                      onTap: () => onSelect(toothAreaLeftBottom),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ));
  }
}
