import 'dart:convert';

import 'package:flyinsono/architecture/services/modules/config_language.dart';
import 'package:flyinsono/architecture/services/modules/examine_configurations.dart';
import 'package:flyinsono/lab/manager/interfaces/project.dart';
import 'package:flyinsono/lab/manager/page_manager.dart';
import 'package:flyinsono/lab/mixin/tab_hook_mixin.dart';
import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
import 'package:flyinsono/lab/pages/lab_record_info/widgets/medication_usage.dart';
import 'package:get/get.dart';
import 'dart:math' as math;
import 'package:fis_jsonrpc/rpc.dart';
import 'package:intl/intl.dart';
import 'index.dart';

class LabRecordInfoController extends GetxController
    with GetSingleTickerProviderStateMixin, TabHookMixin {
  LabRecordInfoController({required this.tabHashCode, this.initArguments});

  final int tabHashCode;

  final dynamic initArguments;

  final state = LabRecordInfoState();

  static const String labRecordInfoId = "lab_record_info";

  static const String baseInfoFieldId = "base_info_field";

  static const String recordInfoFieldId = "record_info_field";

  static const String recordInfoTabsBarId = "record_info_tabs_bar";

  static const String baseInfoMedicationUsage = "base_info_medication_usage";

  static const List<String> tabLists = [
    "Routine",
    "Obstetrics",
    "Gynaecology",
    "Urology",
    "Heart"
  ];

  static Map<int, List<String>> recordInfoFieldMap = {
    0: ["Weight", "Height", "BSA", "BMI"],
    1: [
      "GestationalAgeOrigin",
      "LMP",
      "GestationalAge",
      "EstimateDueDate",
      "FetusNumber",
      "Gravida",
      "Para",
      "AB",
      "Ectopic"
    ],
    2: ["AB", "Ectopic", "Gravida", "LMP", "Para"],
    3: ["PPSACoefficient", "PSA"],
    4: ["HighPR", "LowPR", "HR"],
  };

  static Map<int, List<String>> recordInfoFieldAnimalsMap = {
    0: ["Weight", "Height", "BSA"],
  };

  final initRecordInfoFieldIndex = 0;

  String initPatientName = "实验小鼠-A";

  String initPatientId = "123456";

  DateTime? birthday;

  /// 当前检查详情
  BaseSampleDetail? currentBaseSampleDetail;

  // String birthdayAge = "0";

  String currentTab = tabLists[0];

  Map<String, Map<String, dynamic>> fieldsResult = {};

  /// 项目接口
  final projectService = Get.find<IProjectManager>();

  /// 语言服务
  final languageService = Get.find<LanguageService>();

  /// 接口返回的检查控制器
  final examInfo = Get.find<CheckService>();

  /// 当前检查的病人信息
  List<DataItemDTO>? patientInfo;

  /// 药物使用情况
  List<MedicationUsageResult> medicationUsageResultList = [];

  RecordModel? currentRecord;

  // /// 是否是人用
  // bool get isPerson =>
  //     currentRecord?.organizationPatientTypeEnum ==
  //     OrganizationPatientTypeEnum.Person;

  List<String> recordInfoFields = recordInfoFieldMap[0]!;

  void updateRecordInfoFields(int index) {
    if (recordInfoFields == recordInfoFieldMap[index]!) return;
    currentTab = tabLists[index];
    recordInfoFields = recordInfoFieldMap[index]!;
    update([recordInfoFieldId]);
  }

  void updateBsaAndBmi() {
    String? weight = fieldsResult[currentTab]?["Weight"];
    String? height = fieldsResult[currentTab]?["Height"];
    if (weight != null && height != null) {
      if (weight.isNotEmpty && height.isNotEmpty) {
        fieldsResult["Routine"]!["BMI"] =
            calculation(weight, height, "Weight/(Height*Height)")
                .toStringAsFixed(2);
        fieldsResult["Routine"]!["BSA"] = calculation(
                weight, height, "0.007184*(Weight^0.425)*(Height^0.725)")
            .toStringAsFixed(2);
      }
    }
    update([recordInfoFieldId]);
  }

  /// 获取检查列表
  void getList() {
    List<String> list = [];
    examInfo
        .getChectList(currentRecord?.organizationPatientTypeEnum as Enum)
        .forEach(
      (element) {
        list.add(element);
      },
    );
    state.tabLists = list;
    print(list);
  }

  /// 获取翻译值
  String getValues(String code) {
    var value = languageService.findLanguageValueByCode('exam', code);
    return value;
  }

  /// 前端计算公式 BSA BMI 动物的BSA
  num calculation(String weight, String height, String calculationKey) {
    if (weight == '0' || height == '0') {
      return 0;
    } else
      switch (calculationKey) {
        case '0.007184*(Weight^0.425)*(Height^0.725)':
          return math.pow(num.parse(weight), 0.425) *
              math.pow(num.parse(height), 0.725) *
              0.007184;
        case 'Weight/(Height*Height)':
          return num.parse(weight) /
              (num.parse(height) / 100 * num.parse(height) / 100);
        case '0.1*Weight^0.667':
          return 0.1 * math.pow(num.parse(weight), 0.667);
        case '0.101*(Weight^0.667)':
          return 0.101 * math.pow(num.parse(weight), 0.667);
        default:
          return 0;
      }
  }

  // 切换检查记录
  void changeRecord(RecordModel newRecord) async {
    print("changeRecord");
    currentRecord = newRecord;
    state.isPerson = currentRecord?.organizationPatientTypeEnum ==
        OrganizationPatientTypeEnum.Person;
    recordInfoFields =
        state.isPerson ? recordInfoFieldMap[0]! : recordInfoFieldAnimalsMap[0]!;

    /// FIXME 此处仅作入参演示示例，实际应用中应该更新完整数据
    initPatientName = newRecord.patient.name;
    initPatientId = newRecord.patient.id;
    BaseSampleDetail? result = await projectService.getSampleDetailAsync(
      recordCode: newRecord.id,
    );
    currentBaseSampleDetail = result;
    List<PatientInfoExt>? patientInfoExtList = result?.patientInfoExtList;
    patientInfoExtList?.forEach((element) {
      Map<String, dynamic> map = {};

      /// 排除用药情况
      if (element.patientScanType == "MedicationUsage") {
        List<dynamic> usages = jsonDecode(element.content?.first.value ?? '');
        List<MedicationUsageResult> medicationUsageList = [];
        usages.forEach((element) {
          medicationUsageList.add(MedicationUsageResult.fromJson(element));
        });
        medicationUsageResultList = medicationUsageList;
      } else {
        element.content?.forEach((ext) {
          map.addAll({
            ext.key!: ext.value,
          });
        });
      }

      fieldsResult.addAll({element.patientScanType!: map});
    });
    patientInfo = result?.patientInfo;
    patientInfo?.forEach((element) {
      if (element.key == "AgeYear") {
        state.birthdayAge = element.value;
      }
      if (element.key == "Birthday" && (element.value?.isNotEmpty ?? false)) {
        state.birthday = DateTime.parse(element.value!);
      }
      if (element.key == "Sex") {
        state.sex = element.value;
      }
      if (element.key == "Breed") {
        state.breed = element.value;
      }
      if (element.key == "AnimalInfoSex") {
        state.sex = element.value;
      }
      if (element.key == "Species") {
        state.species = element.value;
      }
      if (element.key == "Owner") {
        state.owner = element.value;
      }
    });
    update([baseInfoFieldId, recordInfoFieldId, baseInfoMedicationUsage]);
  }

  void saveLabRecordInfo() {
    List<PatientInfoExt> patientInfoExtList = [];
    fieldsResult.forEach((key, value) {
      if (key != "MedicationUsage") {
        List<DataItemDTO> content = [];
        value.forEach((key1, value1) {
          DataItemDTO dataItem = DataItemDTO(key: key1, value: value1);
          content.add(dataItem);
        });
        patientInfoExtList.add(
          PatientInfoExt(
            patientScanType: key,
            content: content,
          ),
        );
      }
    });

    List<DataItemDTO> _patientInfo = [];
    patientInfo?.forEach((element) {
      if (element.key == "AgeYear" ||
          element.key == "Birthday" ||
          element.key == "Sex" ||
          element.key == "AnimalInfoSex") {
        //print("element.value");
      } else {
        _patientInfo.add(element);
      }
    });
    if (state.birthday != null) {
      String birthdayVal = DateFormat('yyyy-MM-dd').format(state.birthday);
      _patientInfo.add(DataItemDTO(key: "Birthday", value: birthdayVal));
      _patientInfo.add(DataItemDTO(key: "AgeYear", value: state.birthdayAge));
    }
    if (state.sex != null) {
      if (state.isPerson) {
        _patientInfo.add(DataItemDTO(key: "Sex", value: state.sex));
      } else {
        _patientInfo.add(DataItemDTO(key: "AnimalInfoSex", value: state.sex));
      }
    }

    if (state.species != null) {
      _patientInfo.add(
        DataItemDTO(
          key: "Species",
          value: state.species,
        ),
      );
    }

    /// 用药情况
    if (medicationUsageResultList.isNotEmpty) {
      patientInfoExtList.add(
        PatientInfoExt(
          patientScanType: "MedicationUsage",
          content: [
            DataItemDTO(
              key: "MedicationUsageItems",
              value: jsonEncode(medicationUsageResultList),
            ),
          ],
        ),
      );
    }
    projectService.modifySampleDetailAsync(
      recordCode: currentBaseSampleDetail?.recordCode ?? '',
      patientInfoExtList: patientInfoExtList,
      patientInfo: _patientInfo,
    );

    PageManager.ins.closeTab(tabHashCode);
  }

  @override
  void onSleep() {
    print("LabRecordInfoController onSleep");
  }

  @override
  void onActive(args) {
    print("LabRecordInfoController onActive args: $args");
    print("LabRecordInfoController onActive args type: ${args.runtimeType}");
    if (args is RecordModel) {
      changeRecord(args);
    }
  }

  Future<void> initService() async {
    await examInfo.init();
    getList();
  }

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
    initService();
    print("LabRecordInfoController onInit initArguments: $initArguments");
    print(
        "LabRecordInfoController onInit initArguments type: ${initArguments.runtimeType}");
    if (initArguments is RecordModel) {
      changeRecord(initArguments);
    }
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
  }

  /// dispose 释放内存
  @override
  void dispose() {
    super.dispose();
  }
}
