import 'package:fis_common/env/env.dart';
import 'package:fis_common/js_plateform/js_platform.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:fis_lib_pdf/pdf_objects/report/report_helper/report_dic.dart';
import 'package:fis_lib_report/converts/event_type.dart';
import 'package:fis_lib_report/report_info/element_tag_names.dart';
import 'package:fis_lib_report/report_info/input_text_info.dart';
import 'package:fis_lib_report/report_info/report_info.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/desktop/names.dart';
import 'package:flyinsono/architecture/services/entity/local_setting.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/storage/file_storage.dart';
import 'package:flyinsono/architecture/utils/web_parameter_helpler.dart';
import 'package:flyinsono/managers/interfaces/report.dart';
import 'package:flyinsono/managers/report_manager.dart';
import 'package:flyinsono/pages/remedical/consultation/controller.dart';
import 'package:flyinsono/pages/remedical/consultation/widgets/report/report_share_dialog.dart';
import 'package:flyinsono/pages/remedical/report_preview/state.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../../../architecture/router/router.dart';
import 'package:universal_html/html.dart' as html;
import 'package:fis_lib_pdf/ultils/pdf_type_enum.dart';

///报告预览控制器
class ReportPreviewController extends FControllerBase {
  ///报告预览控制器状态
  final state = ReportPreviewState();

  ///选中事件
  final FEventHandler<String> onSelect = new FEventHandler<String>();

  late String referralRecordCode = '';

  String? recordCode;

  ///是否来自编辑器
  static bool isFromEditor = false;

  ///报告图片列表
  static List<String> imageOrFileUrls = [];

  /// 载入类型
  static PDFTypeEnum pdfType =
      isFromEditor ? PDFTypeEnum.report : PDFTypeEnum.pdfJpeg;

  final fileStorage = FileStorage.createInstance("remedical/report");

  String _patientName = "";
  String _recordCode = "";
  ReportDTO? reportDTO;
  Future<bool> shareReport() async {
    if (state.reportCode.isEmpty) {
      return false;
    }
    var reportUrlToShare =
        await rpc.report.findReportShareUrlAsync(FindReportShareUrlRequest(
      reportCode: state.reportCode,
      token: Store.user.token,
      languageCode: i18nBook.locale.toCodeString('-'),
    ));
    if (reportUrlToShare.isEmpty) {
      return false;
    }

    ///ReportShareDialog 依赖ConsultationController
    Get.put(ConsultationController());
    router.dialog(
      () => ReportShareDialog(
        reportUrlToShare,
        state.reportCode,
      ),
    );
    return true;
  }

  @override
  void onReady() {
    initDatas();
    super.onReady();
  }

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

  ///初始化数据
  Future<void> initDatas() async {
    pdfType = isFromEditor ? PDFTypeEnum.report : PDFTypeEnum.pdfJpeg;
    imageOrFileUrls = [];
    var parameters = router.getParams(NavIds.HOME) ?? {};
    if (parameters.isEmpty) {
      parameters = ParameterHelper.parasmeters;
    }
    Future.delayed(Duration(milliseconds: 1000), () {
      ParameterHelper.setWindowState();
    });
    if (parameters.containsKey('token')) {
      Store.user.setToken(parameters['token'] ?? '');
    }
    if (parameters.containsKey('reportCode')) {
      var reportCode = parameters['reportCode'] ?? '';
      state.reportCode = reportCode;
    }
    if (parameters.containsKey('isFromEditor')) {
      var isFromEditorStr = parameters['isFromEditor'] ?? '';
      if (isFromEditorStr == 'true') {
        isFromEditor = true;
      } else {
        isFromEditor = false;
      }
    }
    if (parameters.containsKey('recordCode')) {
      recordCode = parameters['recordCode'] ?? '';
      await _initPreviewReportByRecordCode(recordCode!);
      state.qualityType = reportDTO?.qualityType ?? QualityType.None;
    } else {
      state.isLoaded = true;
    }
    if (parameters.containsKey('referralRecordCode')) {
      referralRecordCode = parameters['referralRecordCode'] ?? '';
    }
    _generateReportName();
  }

  ///关闭PDF预览
  void onPDFClose() {
    var isShell = FPlatform.isWindows || FPlatform.isMacOS;

    if ((LocalSetting.ins.isUseSecondWindow! && isShell) ||
        (Store.app.enableNewTab && !isShell)) {
      if (isFromEditor) {
        router.back();
      } else {
        if (FPlatform.isWindows || FPlatform.isMacOS) {
          JSPlateForm.closeSlaveWindow();
        } else {
          html.window.close();
        }
      }
    } else {
      router.back(id: NavIds.HOME);
    }
  }

  Future<List<ReportDTO>> findExamReportsAsync(String recordCode) async {
    int retries = 0;
    while (retries < 5) {
      //最多重试5次
      try {
        print('findExamReportsAsync start');
        print("recordCode:" + recordCode);
        var reportInfo = await rpc.report.findExamReportsAsync(
          FindReportsRequest(
            token: Store.user.token,
            recordCode: recordCode,
            languageCode: i18nBook.locale.toCodeString('-'),
          ),
        );
        print('findExamReportsAsync end');
        return reportInfo;
      } catch (e) {
        print('findExamReportsAsync rpc error:' + e.toString());
        retries++; //重试次数增加
        await Future.delayed(Duration(seconds: retries)); //等待时间逐渐增加
      }
    }
    return []; //最终返回[]，因为已经达到最大尝试次数
  }

  /// 查询转诊检查关联报告列表
  Future<List<ReportDTO>> queryReferralExamReportsAsync(
    String recordCode,
    String referralRecordCode,
  ) async {
    final getRecordsPage = await rpc.remedical.queryReferralExamReportsAsync(
      QueryReferralExamReportRequest(
        token: Store.user.token,
        // recordCode: recordCode,
        referralRecordCode: referralRecordCode,
        languageCode: i18nBook.locale.toCodeString('-'),
      ),
    );
    return getRecordsPage;
  }

  Future<void> _initPreviewReportByRecordCode(String recordCode) async {
    try {
      busy = true;
      final reportCode = state.reportCode;
      var reportInfos = referralRecordCode.isEmpty
          ? await findExamReportsAsync(recordCode)
          : await queryReferralExamReportsAsync(recordCode, referralRecordCode);

      /// 1. 先获取对应语言的 _reportDTO
      if (reportInfos.any((element) => element.reportCode == reportCode)) {
        reportDTO = reportInfos
            .firstWhere((element) => element.reportCode == reportCode);
        var reportInfo =
            await Get.find<IReportManager>().findReportByCodeAsync(reportCode);
        reportDTO?.qualityControlDatas = reportInfo.qualityControlDatas;
      } else if (reportInfos.isNotEmpty) {
        reportDTO = reportInfos.last;
      }

      /// 从 _reportDTO 中获取编号、姓名，后续用于文件命名
      if (reportDTO != null) {
        _recordCode = reportDTO!.reportCode ?? '';
        _patientName = reportDTO!.patientName ?? '';
      } else {
        _recordCode = recordCode;
      }

      /// 如果没有 PDF file 那么从 _reportDTO 中获取图像列表
      var images = reportDTO?.reportPreviewList?.where(
              (element) => element.fileType == UploadFileTypeEnum.JPG) ??
          [];
      List<String> imageList = images.map((e) => e.fileToken ?? '').toList();
      for (var image in imageList) {
        if (image.contains(';')) {
          imageOrFileUrls
              .addAll(image.split(';').where((element) => element.isNotEmpty));
        } else {
          imageOrFileUrls.add(image);
        }
      }

      var pdfFiles = reportDTO?.reportPreviewList?.where(
              (element) => element.fileType == UploadFileTypeEnum.PDF) ??
          [];
      List<String> pdfList = pdfFiles.map((e) => e.fileToken ?? '').toList();
      if (pdfList.isNotEmpty) {
        imageOrFileUrls.clear();
        pdfType = PDFTypeEnum.pdfBytes;
        for (var pdf in pdfList) {
          if (pdf.contains(';')) {
            imageOrFileUrls
                .addAll(pdf.split(';').where((element) => element.isNotEmpty));
          } else {
            imageOrFileUrls.add(pdf);
          }
        }
      }

      /// 设置报告文件名
      if (imageOrFileUrls.isNotEmpty) {
        String fileName = _generateReportFileNameWithReportInfo(reportDTO!);
        if (state.reportName == "") {
          state.reportName = fileName;
        }
      }
    } catch (e) {
      print(e);
    }
    busy = false;
    state.isLoaded =
        true; // 此时会触发 reportImageList 进入 FPDFRenderContainer 的渲染逻辑（会做图像压缩，缓存）
  }

  void _generateReportName() {
    var reportInfo = FReportInfo.instance;
    var inputTextInfo;
    String patientName = '';
    var patientElement =
        reportInfo.getElementInfoByTagName(TagNames.PATIENT_NAME_TAG);
    if (patientElement != null) {
      inputTextInfo = patientElement as InputTextInfo;
      patientName = inputTextInfo.text;
    } else {
      patientName = _patientName;
    }
    var creatTime =
        reportInfo.reportDate ?? reportDTO?.reportTime ?? DateTime.now();
    var reportCode = reportInfo.id ?? _recordCode;

    DateFormat format = DateFormat("yyyMMddHHmmss");

    var dateStr = format.format(creatTime);
    var fileName = "[$patientName]-[$dateStr]-[$reportCode].pdf";
    if (state.reportName == '') {
      state.reportName = fileName;
    }
  }

  String _generateReportFileNameWithReportInfo(ReportDTO reportDTO) {
    var patientName = reportDTO.patientName!.replaceAll("*", "x");
    DateFormat format = DateFormat("yyyMMddHHmmss");
    var dateStr = format.format(reportDTO.reportTime!.toLocal());
    var fileName = "[$patientName]-[$dateStr]-[${reportDTO.reportCode!}].pdf";
    return fileName;
  }
}
