import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:get/get.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:vitalapp/helper/utc_dateTime_converter.dart';
import 'package:vitalapp/managers/interfaces/remedical.dart';
import 'package:vitalapp/pages/patient/create/widgets/patient_info.dart';
import 'package:vitalapp/rpc.dart';
import 'interfaces/base_manager.dart';
import 'interfaces/models/process_arg.dart';
import 'package:fis_common/event/event_type.dart';
import 'simple_Info.dart';

class RemedicalManager extends BaseManager implements IRemedicalManager {
  final processChange = FEventHandler<ProcessArg>();

  @override
  Future<PageResult<ClientPatientInfoBaseDTO>> findPatients({
    int pageIndex = 1,
    int pageSize = 20,
    String keyWord = '',
    DateTime? startDateTime,
    DateTime? endDateTime,
    PatientValidStatusEnum isValid = PatientValidStatusEnum.All,
  }) async {
    final patients = await rpc.patient.findPatientsAsync(
      FindPatientsPageRequest(
        token: token,
        pageIndex: pageIndex,
        pageSize: pageSize,
        keyWord: keyWord,
        startTime: startDateTime,
        endTime: endDateTime,
        isValid: isValid,
      ),
    );
    return patients;
  }

  @override
  Future<bool> createPatientByUnregisteredAsync(String patientName,
      {String? code}) async {
    final name = FEncryptHelper.encodeBase64(patientName);
    final result = await rpc.patient.createPatientByUnregisteredAsync(
      CreatePatientByUnregisteredRequest(
        token: token,
        patientName: name,
        unregisteredPatientCode: code,
      ),
    );
    return result;
  }

  @override
  Future<String> createUnregisteredPatient(String patientName,
      {String? code}) async {
    final name = FEncryptHelper.encodeBase64(patientName);
    final result = await rpc.patient.createUnregisteredPatientAsync(
      CreatePatientByUnregisteredRequest(
        token: token,
        patientName: name,
        unregisteredPatientCode: code,
      ),
    );
    return result;
  }

  @override
  Future<List<SimpleInfoItem>> findSimpleInfoPatients({
    int pageIndex = 1,
    int pageSize = 20,
    String keyWord = '',
    DateTime? startDateTime,
    DateTime? endDateTime,
    PatientValidStatusEnum isValid = PatientValidStatusEnum.All,
    bool isCounsultationPatient = false,
  }) async {
    PageResult<ClientPatientInfoBaseDTO> patients;
    if (isCounsultationPatient) {
      patients = await rpc.liveConsultation.findConsultationPatientAsync(
        FindConsultationPatientPageRequest(
          token: token,
          keyword: keyWord,
          pageIndex: pageIndex,
          pageSize: pageSize,
        ),
      );
    } else {
      patients = await findPatients(
        keyWord: keyWord,
        pageIndex: pageIndex,
        pageSize: pageSize,
        startDateTime: startDateTime,
        endDateTime: endDateTime,
      );
    }
    List<SimpleInfoItem> items = [];
    for (ClientPatientInfoBaseDTO p in patients.pageData ?? []) {
      List<DataItemDTO> patientData = p.patientData ?? [];
      var identityCard = patientData
          .firstWhereOrNull((element) => element.key == 'IdentityCard');
      items.add(
        SimpleInfoItem(
          itemCode: p.patientCode ?? '',
          name: _getPatientName(patientData),
          image: patientData
              .firstWhereOrNull((element) => element.key == 'HeadImgUrl')
              ?.value,
          role: patientData
              .firstWhereOrNull((element) => element.key == 'Phone')
              ?.value,
          des: [
            identityCard == null ? '' : identityCard.value,
          ],
        ),
      );
    }
    return items;
  }

  String? _getPatientName(List<DataItemDTO> patientData) {
    var name =
        patientData.firstWhereOrNull((element) => element.key == 'Name')?.value;
    if (name == null || name.isEmpty) {
      name = patientData
          .firstWhereOrNull((element) => element.key == 'AnimalInfoName')
          ?.value;
    }
    return name;
  }

  @override
  List<DataItemDTO>? convertPatientInfoToPatientDatas(
      PatientInfo? patientInfo) {
    if (patientInfo == null) {
      return [];
    }
    return [];
  }

  /// 根据后端接口的key值取到对应的value
  ///
  /// [patientData] 后端数据
  ///
  /// [keys] 对应的Key值
  @override
  String getKeyValue(
    List<DataItemDTO> patientData,
    List<String> keys,
  ) {
    return patientData.firstWhereOrNull((element) {
          return keys.contains(element.key);
        })?.value ??
        '';
  }

  @override
  Future<ClientPatientInfoDTO> findPatientByCode(
    String patientCode,
  ) async {
    return await rpc.remoteUltrasound.vitalFindPatientByCodeAsync(
      FindPatientByCodeRequest(
        code: patientCode,
        token: token,
      ),
    );
  }

  // @override
  // Future<List<FSelectModel>> findScanPositions() async {
  //   List<FSelectModel> scanPositionsList = [];

  //   return scanPositionsList;
  // }

  /// 获取测量图像
  @override
  Future<List<RemedicalMeasuredInfoDTO>> findRemedicalMeasuredInfoAsync(
      String recordCode,
      {BusinessTypeEnum businessType =
          BusinessTypeEnum.RemoteDiagnosis}) async {
    List<RemedicalMeasuredInfoDTO> result = [];
    try {
      result = await rpc.remoteUltrasound.vitalFindRemedicalMeasuredInfoAsync(
        FindRemedicalMeasuredInfoRequest(
          token: token,
          recordCode: recordCode,
          businessType: businessType,
        ),
      );
      return result;
    } catch (e) {
      logger.i("findRemedicalMeasuredInfoAsync exception:" + e.toString());
    }

    return result;
  }

  @override
  Future<List<ReportDTO>> findExamReports(String recordCode) async {
    try {
      var result = await rpc.ultrasoundReport.vitalFindReportsAsync(
        FindReportsRequest(
          token: token,
          recordCode: recordCode,
        ),
      );
      return result;
    } catch (e) {
      logger.e('RemedicalManager findExamReports ex:$e');
      return [];
    }
  }

  ///查询检查详情
  @override
  Future<QueryRecordResult?> queryRecordInfoAsync(String recordCode) async {
    try {
      return await rpc.remoteUltrasound.vitalQueryRecordInfoAsync(
        QueryRecordRequest(
          token: token,
          recordCode: recordCode,
        ),
      );
    } catch (e) {
      print('error:$recordCode');
      logger.i('queryRecordInfoAsync recordCode:$recordCode');
      logger.e('RemedicalManager queryRecordInfoAsync ex:', e);
      return null;
    }
  }

  @override
  Future<List<RemedicalAISelectedInfoDTO>> findAIImages(
      String recordCode, String patientId) async {
    final result = await rpc.remedical.getPatientAISelectedInfosAsync(
      GetPatientAISelectedInfosRequest(
        token: token,
        recordCode: recordCode,
        patientCode: patientId,
      ),
    );
    return result;
  }

  @override
  bool checkCarotidList(
      RemedicalItemList remedicalItem, CarotidScanTypeEnum scanTypeEnum) {
    return (remedicalItem.remedicalList
                ?.where(
                  (element) =>
                      element.carotidResult != null &&
                      element.carotidResult?.carotidScanType == scanTypeEnum,
                )
                .toList() ??
            [])
        .isNotEmpty;
  }

  @override
  Future<RemedicalInfoDTO> findRemedicalByCode(String remedicalCode) async {
    return rpc.remoteUltrasound.vitalFindRemedicalByCodeAsync(
      FindRemedicalByCodeRequest(
        remedicalCode: remedicalCode,
        token: token,
      ),
    );
  }

  @override
  Future<PageResult<SimpleRecordInfoDTO>> findRecordPages({
    List<String>? organizationCodes,
    List<String>? deviceCodes,
    RecordQueryStateEnum recordQueryState = RecordQueryStateEnum.All,
    RecordProcessStateEnum recordProcessState = RecordProcessStateEnum.All,
    String? keyWord,
    DateTime? startTime,
    DateTime? endTime,
    String? patientCode,
    int pageIndex = 1,
    int pageSize = 20,
  }) async {
    try {
      var startTimeTemporaryVariable =
          UtcDateConverter.getDayStartOrEndUTCTime(startTime);
      var endTimeTemporaryVariable =
          UtcDateConverter.getDayStartOrEndUTCTime(endTime, isEnd: true);
      var records = await rpc.remoteUltrasound.vitalFindRecordPagesAsync(
        FindRecordPagesRequest(
          token: token,
          pageIndex: pageIndex,
          pageSize: pageSize,
          organizationCodes: organizationCodes,
          deviceCodes: deviceCodes,
          keyWord: keyWord,
          recordQueryState: recordQueryState,
          language: i18nBook.locale.toCodeString('-'),
          recordProcessState: recordProcessState,
          patientCode: patientCode,
          startTime: startTimeTemporaryVariable,
          endTime: endTimeTemporaryVariable,
        ),
      );
      return records;
    } catch (e) {
      logger.e('RemedicalManager findRecordPages ex:$e');
      return PageResult<SimpleRecordInfoDTO>();
    }
  }

  @override
  void openImageMeasurePage(
      String imageUrl,
      int imageindex,
      String remedicalCode,
      String recordCode,
      String? remedicalAISelectedInfoCode,
      String patientCode) {}
}