import 'dart:convert';
import 'dart:io';

import 'package:auto_route/annotations.dart';
import 'package:bot_toast/bot_toast.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/preview_operation_view.dart';
import 'package:eitc_erm_dental_flutter/pages/view/widget/preview_title.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:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'package:photo_view/photo_view.dart';

import '../../funcs.dart';

///照片预览页面
@RoutePage(name: "photoPreviewRoute")
class PhotoPreviewPage extends StatefulWidget {
  final LocalPatientInfo info;
  final String path;
  final String area;
  final DateTime time;
  final String mobile;
  final String wifi;
  final String deviceModel;

  const PhotoPreviewPage(
      {super.key,
      required this.info,
      required this.path,
      required this.area,
      required this.time,
      required this.mobile,
      required this.deviceModel,
      required this.wifi});

  @override
  State<PhotoPreviewPage> createState() => _PhotoPreviewPageState();
}

class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
  bool _isSaving = false;
  bool _isSaved = false;

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

  @override
  void dispose() {
    super.dispose();
    _deleteCache();
  }

  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    return PopScope(
        canPop: !_isSaving,
        child: Scaffold(
          body: SafeArea(
            child: Container(
              color: Colors.black,
              child: Stack(
                children: [
                  PhotoView.customChild(
                      childSize: MediaQuery.of(context).orientation ==
                              Orientation.landscape
                          ? Size(screenSize.width,
                              screenSize.height + screenSize.height / 2)
                          : null,
                      child: Container(
                        alignment: Alignment.center,
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Image.file(File(widget.path)),
                            VideoPatientInfoBar(
                              info: widget.info,
                              orientation: MediaQuery.of(context).orientation,
                              area: widget.area,
                              deviceModel: widget.deviceModel,
                              time: widget.time,
                            ),
                          ],
                        ),
                      )),
                  Align(
                    alignment: Alignment.topLeft,
                    child: PreviewTitle(
                      title: getS().previewPhoto,
                    ),
                  ),
                  PreviewOperationView(
                    onSave: _onSave,
                    onCancel: _onCancel,
                  ),
                ],
              ),
            ),
          ),
        ));
  }

  Future<String?> _editPhoto() async {
    int height = 55;
    int fontHeight = 48;
    //读取原图片
    logd("读取原图片,path=${widget.path}");
    img.Command sourceImgCmd = img.Command();
    sourceImgCmd.decodeJpgFile(widget.path);
    await sourceImgCmd.executeThread();
    img.Image? sourceImg = await sourceImgCmd.getImage();
    if (sourceImg == null) {
      logd("读取原图片返回null");
      return null;
    }
    logd("原图片读取成功,image=${sourceImg.toString()}");

    logd("读取名字图片");
    LocalPatientInfo? patientInfo =
        await DbUtil.instance.getLocalPatientById(selectedPatientId);
    //读取名字图片
    img.Image? nameImg;
    img.Command? nameImgCmd;
    if (patientInfo != null && !patientInfo.namePic.isNullOrEmpty) {
      nameImgCmd = img.Command();
      nameImgCmd.decodePng(base64Decode(patientInfo.namePic!));
      await nameImgCmd.executeThread();
      nameImg = await nameImgCmd.getImage();
      logd("名字读片读取成功,image=${nameImg.toString()}");
    } else {
      logd("名字图片不存在,咨询人信息为null或名字图片字段为空");
    }

    //性别
    int gender = getGenderFromIdCard(widget.info.idCardDecrypt);
    String sex = getS().unknown;
    if (gender == 0) {
      sex = getS().male;
    } else if (gender == 1) {
      sex = getS().female;
    }
    //年龄
    int age = getAgeFromIdCard(
        widget.info.idCardDecrypt.isEmpty ? "--" : widget.info.idCardDecrypt);
    //区域
    String toothArea = toothAreaTranslate(widget.area);
    //时间
    String yyyy = widget.time.yyyyMMddHHmmss;
    logd("信息,性别=$sex,年龄=$age,area=$toothArea,时间=$yyyy");

    logd("创建黑条并写入信息");
    int gap = 30;
    //创建黑条
    img.Command blackCmd = img.Command()
      ..createImage(
        width: sourceImg.width,
        height: height,
      )
      ..fill(color: img.ColorRgb8(0, 0, 0))
      ..drawString(
          "/$sex/${getS().xxAge(age < 0 ? 0 : age)}        $toothArea        $yyyy",
          font: photoFont ?? img.arial48,
          x: (nameImg?.width ?? 0) + gap,
          y: (height - fontHeight) ~/ 2,
          color: img.ColorRgb8(255, 255, 255))
      ..drawString(widget.deviceModel.isEmpty ? "--" : widget.deviceModel,
          font: photoFont ?? img.arial48,
          rightJustify: true,
          //右对齐坐标从右往左算
          x: sourceImg.width - gap,
          y: (height - fontHeight) ~/ 2,
          color: img.ColorRgb8(255, 255, 255));
    if (nameImg != null && nameImgCmd != null) {
      logd("存在名字图片,合并到黑条中");
      blackCmd.compositeImage(nameImgCmd,
          dstX: gap, dstY: (height - nameImg.height) ~/ 2);
    }
    logd("黑条创建成功");

    logd("创建最终图片,合并原图片和黑条");
    //创建一个更大的图片装下原图片和黑条
    img.Command allCmd = img.Command();
    allCmd.createImage(
        width: sourceImg.width, height: sourceImg.height + height);
    allCmd.compositeImage(sourceImgCmd);
    allCmd.compositeImage(blackCmd, dstY: sourceImg.height);
    logd("最终图片创建成功");

    logd("开始保存");
    //保存
    Directory? dir;
    if (Platform.isIOS) {
      dir = await getApplicationDocumentsDirectory();
    } else {
      dir = await getDownloadsDirectory();
    }
    if (dir == null) {
      return null;
    }
    dir = Directory("${dir.path}/${Platform.isIOS ? "jpgimage" : "tempPhoto"}");
    if (!await dir.exists()) {
      await dir.create(recursive: true);
    }
    String prefix = makeFilePrefix(
        name: widget.info.name ?? "",
        idCard: widget.info.idCardDecrypt,
        mobile: widget.mobile,
        area: widget.area,
        wifi: widget.wifi,
        time: widget.time.millisecondsSinceEpoch,
        userId: await SpUtil.getUserId());
    String newPath =
        "${dir.path}/$prefix${widget.time.millisecondsSinceEpoch}.jpg";
    logd("保存路径=$newPath");
    allCmd.encodeJpgFile(newPath);
    await allCmd.executeThread();
    logd("执行完毕");
    return newPath;
  }

  void _onSave() async {
    logd("保存");
    setState(() {
      _isSaving = true;
    });
    var cancelFunc = BotToast.showLoading(clickClose: false, crossPage: false);
    try {
      //编辑并保存照片
      String? path = await _editPhoto();
      if (path == null) {
        setState(() {
          _isSaving = false;
        });
        cancelFunc();
        showToast(text: getS().saveFailed);
        return;
      }
      //通知原生保存图片
      await videoChannel.invokeMethod("savePhoto", [widget.path, path]);
      _isSaved = true;
      cancelFunc();

      setState(() {
        _isSaving = false;
      });
      showToast(text: getS().saveSuccess);
      if (mounted) {
        Navigator.pop(context);
      }
    } catch (e) {
      setState(() {
        _isSaving = false;
      });
      cancelFunc();
      showToast(text: getS().saveFailed);
      loge("保存图片异常", error: e);
    }
  }

  void _onCancel() {
    logd("取消");
    Navigator.pop(context);
  }

  void _deleteCache() {
    if (widget.path.isEmpty && _isSaved) {
      return;
    }
    try {
      fileChannel.invokeMethod("deleteFile", widget.path);
    } catch (e) {
      loge("照片预览删除文件异常", error: e);
    }
  }
}
