import 'dart:async';

import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:fis_lib_pdf/pdf_helper.dart';
import 'package:fis_ui/index.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/router.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/storage/file_storage.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/managers/interfaces/remedical.dart';
import 'package:flyinsono/managers/interfaces/report.dart';
import 'package:flyinsono/pages/remedical/consultation/controller.dart';
import 'package:flyinsono/pages/remedical/consultation/state.dart';
import 'package:flyinsono/pages/remedical/consultation/widgets/exam_images_list_view.dart';
import 'package:flyinsono/pages/remedical/consultation/widgets/exam_images_view.dart';
import 'package:flyinsono/pages/remedical/consultation/widgets/exam_records.dart';
import 'package:flyinsono/pages/remedical/consultation/widgets/report/reports_mobile.dart';
import 'package:flyinsono/pages/remedical/report_preview/controller.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import '../widgets/report/report_preview.dart';

/// 检查报告的控制器
class ExamReportController extends FControllerBase {
  final reportManager = Get.find<IReportManager>();
  final remedicalManager = Get.find<IRemedicalManager>();
  late ConsultationController controller;
  late FConsultationState state;
  late String _defaultTemplate;
  late final reportPreviewController =
      Get.put<ReportPreviewController>(ReportPreviewController());
  ReportDataPipe get fileStorage => ReportDataPipe(
      cacheGet: reportPreviewController.fileStorage.getFile,
      cacheSave: reportPreviewController.fileStorage.setFile);
  Future<bool> Function(List<int> data, String fileName)? get shellExporter =>
      TextMediaFileExporterForShell.exportFile;

  ExamReportController(ConsultationController controller) {
    this.controller = controller;
    this.state = controller.state;
    if (kIsMobile) {
      reportManager.initFluwx();
      _initDefaultDatas();
    }
  }

  Future<List<ReportDTO>> findPatientReports() async {
    try {
      final findPatientReportsAsync = await rpc.report.findPatientReportsAsync(
        FindPatientReportsRequest(
          token: Store.user.token,
          patientCode: state.patientCode,
          languageCode: i18nBook.locale.toCodeString('-'),
        ),
      );
      return findPatientReportsAsync;
    } catch (e) {
      return [];
    }
  }

  /// 报告列表-根据病人查询报告
  Future<void> findPatientReportsAsync() async {
    try {
      final findPatientReportsAsync = state.patientTab == 0
          ? await findPatientReports()
          : await controller.referPatientInfoController
              .queryReferralPatientReportsAsync();
      state.reportList = findPatientReportsAsync;
    } catch (e) {
      printError(info: "findPatientReportsAsync exception:" + e.toString());
      logger.e("findPatientReportsAsync exception:", e);
    }
  }

  ///跟据reportCode获取报告详情
  Future<void> findReportByCodeAsync() async {
    final reportInfo =
        await rpc.report.findReportByCodeAsync(FindReportByCodeRequest(
      token: Store.user.token,
      reportCode: state.reportCode,
    ));
    state.reportInfo = reportInfo;
  }

  ///获取分享报告链接
  Future<String> findReportShareUrlAsync() async {
    return await reportManager.findReportShareUrlAsync(state.reportCode);
  }

  ///打开报告编辑页面
  Future<void> openReportEdit(
    String recordCode,
    String patientCode, {
    String reportCode = '',
    int patientTab = 0,
    String referralRecordCode = '',
  }) async {
    final result = state.patientTab == 0
        ? await reportManager.getRemedicalListByRecordInfoAsync(recordCode)
        : await reportManager.queryReferralRemedicalListByRecordInfoAsync(
            recordCode, state.referralRecordCode);
    state.getScannedImage = result;
    reportManager.openReportEdit(
      patientCode,
      recordCode: recordCode,
      reportCode: reportCode,
      patientTab: patientTab,
      referralRecordCode: referralRecordCode,
    );
  }

  Future<List<ReportDTO>> findExamReportsAsync(String recordCode) async {
    return reportManager.findReportsAsync(recordCode);
  }

  ///打开报告列表页面
  Future<void> openReportsView({bool isOff = false}) async {
    await findPatientReportsAsync();
    if (state.reportList.isNotEmpty) {
      var recordCode = state.checkLists[state.examRecordIndex].recordCode!;

      var mobileReportsContentView = MobileReportsContentView(
        reportList: state.reportList,
        recordCode: recordCode,
        onRefresh: () => remedicalManager.findExamReports(recordCode),
        patientInfo: controller.state.patientInfo,
        onTapCard: (index) async {
          final reportInfo = state.reportList[index];
          state.reportCode = reportInfo.reportCode ?? '';
          await controller.findReportByCodeAsync();
          final preList = controller.state.reportInfo.reportPreviewList ?? [];
          if (preList.isEmpty) {
            PromptBox.toast(i18nBook.remedical.reportNoInit.t);
          } else {
            controller.state.reportIndex = index;
            Get.to(() => ReportPreview(
                  reportInfo: controller.state.reportInfo,
                  reportList: controller.state.reportList,
                ));
            controller.findPatientReportsAsync();
          }
        },
        onTapCheck: () async {
          await controller.inspectionRecordsController.getCheckInfo(controller
              .state
              .imageScanned[controller.state.imageScannedIndex]
              .recordCode!);
          Get.to(() => ExamRecord(isSingle: true));
        },
        onTapShare: (reportCode) {
          controller.state.reportCode = reportCode;
        },
        onTapImage: (index) async {
          throw UnimplementedError();
          // final result = await controller.inspectionRecordsController
          //     .getCheckScannedImage(
          //         controller.state.reportList[index].recordCode!);
          // if (result) {
          //   Get.to(
          //     () => ExamImagesListView(
          //       patientCode: controller.state.patientCode,
          //       measureImages: controller.state.remedicalMeasured,
          //       cloudImageInfos: [controller.state.getScannedImage],
          //       isShowConsultationImage: true,
          //     ),
          //   );
          // }
        },
      );
      if (isOff) {
        Get.off(() => mobileReportsContentView);
      } else {
        Get.to(() => mobileReportsContentView);
      }
    } else {
      PromptBox.toast(i18nBook.remedical.noReport.t);
    }
  }

  ///手机端提交报告
  Future<void> submitReport() async {
    busy = true;
    try {
      final patientInfo = state.patientInfos[state.selectPatientCardIndex];
      var recordCode = state.examRecord.recordCode;

      final reportDatasJson = reportManager.getMobileReportDatasJson(
        patientName: patientInfo.name,
        patientSex: patientInfo.sex,
        age: patientInfo.age,
        imageInfos: state.selectedRemedicalImages,
        des: controller.desController.text,
        summary: controller.consualationController.text,
        creatorName: state.examRecord.creatorName,
        fullName: Store.user.fullName,
      );
      final addRequest = AddReportRequest(
          token: Store.user.token,
          patientName: FEncryptHelper.encodeBase64(patientInfo.name ?? ''),
          recordCode: recordCode,
          reportTemplateJson: _defaultTemplate,
          reportDatasJson: reportDatasJson,
          platformLabels: ["Flyinsono", "Mobile", "RemoteDiagnosis"]);
      if (state.referralRecordCode.isNotEmpty) {
        addRequest.isReferral = true;
      }
      final submitResult = await rpc.report.addReportAsync(addRequest);
      if (submitResult.isNotEmpty) {
        PromptBox.toast(i18nBook.remedical.submitSuccess.t);
        QueryRecordResult? checkInfo;
        checkInfo = await controller
            .queryRecordInfoAsync(state.examRecord.recordCode ?? '');
        if (checkInfo == null) {
          return;
        }
        if (checkInfo.recordStatus != state.examRecord.recordStatus) {
          state.examRecord.recordStatus = checkInfo.recordStatus;
        }
        controller.onstatusChange.emit(this, '');
        state.selectedImages.clear();
        state.selectedRemedicalImages.clear();
        controller.desController.text = '';
        controller.consualationController.text = '';

        Future.delayed(Duration(milliseconds: 500), () {
          openReportsView(isOff: true);
        });
      }
    } catch (e) {
      logger.e('InspectionReportController submitReport:', e);
      print(e);
    }
    busy = false;
  }

  Future<void> _initDefaultDatas() async {
    final userInfo = await rpc.user.getUserInfoAsync(
      GetUserInfoRequest(token: Store.user.token),
    );
    final orgInfo = await rpc.organization
        .getOrganizationByCodeAsync(GetOrganizationByCodeRequest(
      token: Store.user.token,
      organizationCode: userInfo.rootOrganizationCode,
    ));
    Store.user.rootOrganizationName = orgInfo.organizationName ?? '';
    _defaultTemplate = await reportManager.getReportTemplate();
  }

  ///提交报告标签
  Future<void> submitReportTags(List<String> values) async {
    try {
      final result =
          await reportManager.submitReportTags(state.reportCode, values);
      if (result) {
        PromptBox.toast(i18nBook.remedical.submitSuccess.t);
        controller.inspectionReportController.findPatientReportsAsync();
        Future.delayed(Duration(milliseconds: 500), () {
          router.back();
        });
      } else {
        PromptBox.toast(i18nBook.remedical.submitFail.t);
      }
    } catch (e) {
      logger.e('AddReportTagController submitReportTags ex:', e);
    }
  }

  ///查看报告
  Future<void> viewReport() async {
    final examInfo = state.checkLists[state.examRecordIndex];
    String reportCode = '';
    final reportInfos = state.patientTab == 0
        ? await findExamReportsAsync(examInfo.recordCode!)
        : await controller.referPatientInfoController
            .queryReferralExamReportsAsync(state.referralRecordCode);

    if (reportInfos.isNotEmpty) {
      controller.state.reportList = reportInfos;
      reportCode = reportInfos.first.reportCode ?? '';
      controller.state.reportCode = reportCode;
      await findReportByCodeAsync();
      final preList = state.reportInfo.reportPreviewList ?? [];
      if (preList.isEmpty) {
        PromptBox.toast(i18nBook.remedical.reportNoInit.t);
      } else {
        controller.state.reportIndex = 0;
        Get.to(() => ReportPreview(
              reportInfo: state.reportInfo,
              reportList: reportInfos,
            ));
      }
    } else {
      PromptBox.toast(i18nBook.remedical.noReport.t);
    }
  }
}
