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:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/router.dart';
import 'package:flyinsono/architecture/services/modules/examine_configurations.dart';
import 'package:flyinsono/architecture/services/modules/config_language.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/date_time.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/managers/interfaces/entities/patient_Info.dart';
import 'package:flyinsono/pages/components/select.dart';
import 'package:flyinsono/pages/remedical/consultation/controller.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'dart:math' as math;

import 'index.dart';

class CreatecheckController extends FControllerBase {
  CreatecheckController();
  final state = CreatecheckState();

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

  /// 后端语言包
  final languageService = Get.find<LanguageService>();

  /// 会诊的主控制器
  final consultationController = Get.put(ConsultationController());

  /// 病人Code
  String patientCode = "";

  /// 保存的检查数据
  List<DataItemDTO> contentsList = [];

  /// 病人类型
  Enum patientType = OrganizationPatientTypeEnum.Person;

  /// 品种类型
  String speciesName = '';

  /// 获取检查的key值
  List getChectKeyList(String checkKey) {
    List checkList = [];
    patientType == OrganizationPatientTypeEnum.Person
        ? examInfo.allMap["ExamInfo"][checkKey]?.forEach(
            (key, value) {
              checkList.add(
                {
                  'key': key,
                  'name': key,
                  'value': value,
                  'showType': value['ShowType'],
                },
              );
            },
          )
        : examInfo.allMap["AnimalExamInfo"][checkKey]?.forEach(
            (key, value) {
              checkList.add(
                {
                  'key': key,
                  'name': key,
                  'value': value,
                  'showType': value['ShowType'],
                },
              );
            },
          );
    return checkList;
  }

  ///部门选择控制器
  late FSelectController<SelectModel> equipmentSelectController;

  /// 获取设备
  Future<void> getIdentity() async {
    try {
      List<SelectModel> deviceOptions = [];
      final patients =
          await rpc.device.getPersonDeviceListAsync(GetPersonDeviceRequest(
        token: Store.user.token,
        keyWord: '',
        pageIndex: 1,
        pageSize: 60,
      ));
      if (patients.pageData == null) {
        return;
      }
      patients.pageData!.forEach((item) {
        deviceOptions.add(
          SelectModel(
            name: item.displayName!,
            code: item.deviceCode!,
          ),
        );
      });
      if (deviceOptions.length > 0) {
        state.deviceOptions = deviceOptions;
        state.deviceCode = state.deviceOptions[0].code;
      } else {
        state.deviceOptions = [];
        state.deviceCode = null;
      }
    } catch (e) {
      printError(info: "getIdentity exception:" + e.toString());
      logger.e("getIdentity exception:", e);
    }
  }

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

  /// 获取检查列表
  Future<void> getList() async {
    List<SelectModel> list = [];
    examInfo.getChectList(patientType).forEach(
      (element) {
        list.add(
          SelectModel(
            name: getValues(element),
            code: element,
          ),
        );
        state.checkHasSelect = list;
      },
    );
  }

  ///获取病人信息
  Future<void> getPatientInfo() async {
    try {
      patientCode = state.patientCode;
      if (patientCode.isEmpty) {
        return null;
      }
      final patients = await rpc.patient.findPatientByCodeAsync(
        FindPatientByCodeRequest(
          code: state.patientCode,
          token: Store.user.token,
        ),
      );
      final patientData = patients.patientData!;
      final name = patientData
          .firstWhereOrNull((element) =>
              element.key == "Name" || element.key == "AnimalInfoName")!
          .value;
      final phone = patientData
          .firstWhereOrNull((element) =>
              element.key == "Phone" || element.key == "AnimalInfoPhone")!
          .value;
      final age = patientData
          .firstWhereOrNull((element) =>
              element.key == "Age" || element.key == "AnimalInfoAge")
          ?.value;
      final sex = patientData
          .firstWhereOrNull((element) =>
              element.key == "Sex" || element.key == "AnimalInfoSex")
          ?.value;
      final encryptFullName =
          FEncryptHelper.decryptBase64(patients.encryptFullName ?? '');
      speciesName = patientData
              .firstWhereOrNull((element) => element.key == "Species")
              ?.value ??
          '';
      state.patientInfo = {
        'patientCode': state.patientCode,
        'name': name,
        'phone': phone,
        'age': age,
        'gender': sex,
        'encryptFullName': encryptFullName,
      };
    } catch (e) {
      printError(info: "getPatientInfo exception:" + e.toString());
      logger.e("getPatientInfo exception:", e);
    }
  }

  /// 创建检查
  Future<void> createRecordInfo() async {
    try {
      print(state.contents);
      List<PatientInfoExt> patientInfoExt = [];
      state.selectCheckList.forEach((element) {
        List<DataItemDTO> dataItem = [];
        getChectKeyList(element).forEach(
          (key) {
            if (key['showType'] == 'WeekAndDay') {
              dataItem.add(
                DataItemDTO(
                  key: key['key'],
                  value: state.contents[element + '-' + key['key']] ??
                      state.weekAndDayContents[element + '-' + key['key']],
                ),
              );
            } else {
              dataItem.add(
                DataItemDTO(
                  key: key['key'],
                  value: state.contents[element + '-' + key['key']],
                ),
              );
            }
          },
        );

        patientInfoExt.add(
          PatientInfoExt(
            patientScanType: element,
            content: dataItem,
          ),
        );
      });

      final result = await rpc.recordInfo.createRecordInfoAsync(
        CreateRecordRequest(
          token: Store.user.token,
          patientCode: patientCode,
          deviceCode: state.deviceCode,
          patientInfoExtList: patientInfoExt,
        ),
      );
      if (result) {
        PromptBox.toast(i18nBook.remedical.createSuccess.t);
        Future.delayed(Duration(milliseconds: 200), () {
          int index = consultationController.state.patientInfos.indexWhere(
              (PatientInfo element) =>
                  element.patientCode ==
                  consultationController.state.currentNewlyCreatedPatient);
          if (index < 0) {
            return;
          }
          consultationController.patientInfoController.getPatientInfo();
          consultationController.inspectionRecordsController
              .getCheckLists(state.patientCode);
        });
      } else {
        PromptBox.toast(i18nBook.remedical.creatFailed.t);
      }
      router.back();
    } catch (e) {
      printError(info: "createRecordInfo exception" + e.toString());
      logger.e("createRecordInfo exception", e);
    }
  }

  /// 设置input的值
  void setInputValue(
    String? value,
    Map<String, dynamic> configuration,
    String buildKey,
  ) {
    print(value);
    state.contents[buildKey + '-' + configuration['name']] = 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;
      }
  }

  /// 自动计算
  String? getFormula(Map<String, dynamic> configuration, String buildKey) {
    String value = '';
    var routineWeight = state.contents['Routine-Weight'];
    var routineHeight = state.contents['Routine-Height'];
    try {
      if (routineWeight != null && routineHeight != null) {
        if (configuration['value']['Formula'] is String) {
          value = calculation(routineWeight ?? '0', routineHeight ?? '0',
                  configuration['value']['Formula'])
              .toStringAsFixed(2)
              .toString();
        } else {
          if (['Canidae', 'Felidae'].contains(speciesName)) {
            value = calculation(routineWeight ?? '0', routineHeight ?? '0',
                    configuration['value']['Formula'][speciesName])
                .toStringAsFixed(2)
                .toString();
          }
        }
        return value;
      } else
        return '';
    } catch (e) {
      return '';
    }
  }

  /// 日期的 包含特殊处理的
  Future<void> calendarDateValue(
    DateTime dateTime,
    Map<String, dynamic> configuration,
    String buildKey,
  ) async {
    state.contents[buildKey + '-' + configuration['name']] =
        DateFormat('yyyy-MM-dd').format(dateTime).toString();

    if (configuration['value']['MethodName'] == 'GetRecordDateAsync') {
      List<String> requireTwo =
          configuration['value']['APIUnionRequired'].split(",");

      /// 这部分是孕龄需要俩个参数的时候调的接口
      if (requireTwo.length > 1) {
        if (state.contents[buildKey + '-LGA'] != null) {
          final processRecordDataAsync =
              await rpc.recordInfo.processRecordDataAsync(
            ProcessRecordDataRequest(
              token: Store.user.token,
              methodName: configuration['value']['MethodName'],
              content: [
                DataItemDTO(
                  key: configuration['name'],
                  value: state.contents[buildKey + '-' + configuration['name']],
                ),
                DataItemDTO(
                  key: 'LGA',
                  value: state.contents[buildKey + '-LGA'],
                ),
                DataItemDTO(
                  key: 'GestationalAgeOrigin',
                  value: state.contents[buildKey + '-GestationalAgeOrigin'] ??
                      'LMP',
                ),
              ],
            ),
          );
          processRecordDataAsync.content?.forEach(
            (element) {
              if (element.value == null || element.value!.length < 15) {
                state.contents[buildKey + '-' + element.key!] = null;
                state.weekAndDayContents[buildKey + '-' + element.key!] =
                    element.value;
              } else {
                state.contents[buildKey + '-' + element.key!] =
                    DateTimeClass.getLocalTime(
                  element.value!,
                );
              }
            },
          );
        }
      } else {
        final processRecordDataAsync =
            await rpc.recordInfo.processRecordDataAsync(
          ProcessRecordDataRequest(
            token: Store.user.token,
            methodName: configuration['value']['MethodName'],
            content: [
              DataItemDTO(
                key: configuration['name'],
                value: state.contents[buildKey + '-' + configuration['name']],
              ),
              DataItemDTO(
                key: 'GestationalAgeOrigin',
                value:
                    state.contents[buildKey + '-GestationalAgeOrigin'] ?? 'LMP',
              ),
            ],
          ),
        );
        processRecordDataAsync.content?.forEach(
          (element) {
            if (element.value == null || element.value!.length < 15) {
              state.contents[buildKey + '-' + element.key!] = null;
              state.weekAndDayContents[buildKey + '-' + element.key!] =
                  element.value;
            } else {
              state.contents[buildKey + '-' + element.key!] =
                  DateTimeClass.getLocalTime(
                element.value!,
              );
            }
          },
        );
      }
      // state.contents[key['name']]
    }
  }

  /// weekandday的数据掉接口返回
  Future<void> getRecordDateAsync(
    String value,
    Map<String, dynamic> configuration,
    String buildKey,
  ) async {
    ProcessRecordDataResult processRecordDataAsync = ProcessRecordDataResult();
    if (configuration['name'] == 'LGA') {
      if (state.contents[buildKey + '-LastExamDate'] != null) {
        processRecordDataAsync = await rpc.recordInfo.processRecordDataAsync(
          ProcessRecordDataRequest(
            token: Store.user.token,
            methodName: "${configuration['value']['MethodName']}",
            content: [
              DataItemDTO(
                key: configuration['name'],
                value: value,
              ),
              DataItemDTO(
                key: 'LastExamDate',
                value: state.contents[buildKey + '-LastExamDate'] ?? 'LMP',
              ),
              DataItemDTO(
                key: 'GestationalAgeOrigin',
                value:
                    state.contents[buildKey + '-GestationalAgeOrigin'] ?? 'LMP',
              ),
            ],
          ),
        );
      }
    } else {
      processRecordDataAsync = await rpc.recordInfo.processRecordDataAsync(
        ProcessRecordDataRequest(
          token: Store.user.token,
          methodName: "${configuration['value']['MethodName']}",
          content: [
            DataItemDTO(
              key: configuration['name'],
              value: value,
            ),
            DataItemDTO(
              key: 'GestationalAgeOrigin',
              value:
                  state.contents[buildKey + '-GestationalAgeOrigin'] ?? 'LMP',
            ),
          ],
        ),
      );
    }

    processRecordDataAsync.content?.forEach(
      (element) {
        if (element.value == null || element.value!.length < 15) {
          // Future.delayed(Duration(milliseconds: 500), () {
          state.contents[buildKey + '-' + element.key!] = element.value;
          state.weekAndDayContents[buildKey + '-' + element.key!] =
              element.value;
          // });
        } else {
          state.contents[buildKey + '-' + element.key!] =
              DateTimeClass.getLocalTime(
            element.value!,
          );
        }
      },
    );
  }

  /// 获取组织类型
  Future<void> getOrgType() async {
    final result = await rpc.user.getUserInfoAsync(
      GetUserInfoRequest(token: Store.user.token),
    );
    final org = await rpc.organization
        .getOrganizationByCodeAsync(GetOrganizationByCodeRequest(
      organizationCode: result.rootOrganizationCode,
      token: Store.user.token,
    ));
    state.organizationName =
        result.organizationName ?? result.rootOrganizationName;
    patientType = org.patientType;
  }

  /// 检查数据初始化
  Future<void> getCheckInit() async {
    await examInfo.init();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() async {
    super.onReady();
    // busy = true;
    // await onLoad();
    // onLoad().then((_) {
    //   busy = false;
    //   // ignore: argument_type_not_assignable_to_error_handler
    // }).catchError(() {
    //   busy = false;
    // });
    // busy = false;
  }

  @override
  Future<void> onLoad() async {
    await Future.wait(
      [
        getCheckInit(),
        getPatientInfo(),
        getIdentity(),
        getOrgType(),
        getList(),
      ],
    );
  }

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

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