import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/Prescriptions.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/get_medication_for_inpatient_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/get_medication_for_inpatient_request_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/perscription_pharmacy.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/post_prescrition_req_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_entity_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_in_patient.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_report.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_report_enh.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_req_model.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/prescriptions_order.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/request_get_list_pharmacy_for_prescriptions.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/request_prescription_report.dart';
import 'package:doctor_app_flutter/core/model/Prescriptions/request_prescription_report_enh.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Allergy/get_allergies_res_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_res_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/master_key_model.dart';
import 'package:doctor_app_flutter/core/model/calculate_box_request_model.dart';
import 'package:doctor_app_flutter/core/model/search_drug/get_medication_response_model.dart';
import 'package:doctor_app_flutter/core/model/search_drug/item_by_medicine_request_model.dart';
import 'package:doctor_app_flutter/core/model/search_drug/search_drug_model.dart';
import 'package:doctor_app_flutter/core/model/search_drug/search_drug_request_model.dart';
import 'package:doctor_app_flutter/core/service/base/lookup-service.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_req_model.dart';
import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/core/model/patient/vital_sign/patient-vital-sign-data.dart';
import 'package:doctor_app_flutter/utils/date-utils.dart';
import 'package:flutter/cupertino.dart';

class PrescriptionService extends LookupService {
  List<PrescriptionModel> _prescriptionList = [];

  List<PrescriptionModel> get prescriptionList => _prescriptionList;

  List<PrescriptionEntityModel> _prescriptionListNew = [];

  List<PrescriptionEntityModel> get prescriptionListNew => _prescriptionListNew;

  List<SearchDrugModel> _drugsList = [];

  List<SearchDrugModel> get drugsList => _drugsList;
  List<dynamic> doctorsList = [];
  List<GetMedicationResponseModel> allMedicationList = [];
  List<dynamic> specialityList = [];
  List<dynamic> drugToDrug = [];

  List<dynamic> get drugToDrugList => drugToDrug;
  List<dynamic> itemMedicineList = [];
  List<dynamic> itemMedicineListRoute = [];
  List<dynamic> itemMedicineListUnit = [];
  List<MasterKeyModel> icd10CodeListByItem =[];
  bool isDiagnosisCovered =true;
  dynamic boxQuantity;

  PrescriptionReqModel _prescriptionReqModel = PrescriptionReqModel();
  ItemByMedicineRequestModel _itemByMedicineRequestModel = ItemByMedicineRequestModel();
  SearchDrugRequestModel _drugRequestModel = SearchDrugRequestModel(
    search: ["Amoxicillin"],
  );

  CalculateBoxQuantityRequestModel _boxQuantityRequestModel = CalculateBoxQuantityRequestModel();

  PostPrescriptionReqModel _postPrescriptionReqModel = PostPrescriptionReqModel();

  Future getItem({required int itemID}) async {
    _itemByMedicineRequestModel = ItemByMedicineRequestModel(medicineCode: itemID);

    hasError = false;

    await baseAppClient.post(GET_ITEM_BY_MEDICINE, onSuccess: (dynamic response, int statusCode) {
      itemMedicineList = [];
      itemMedicineList = response['listItemByMedicineCode']['frequencies'];
      itemMedicineListRoute = response['listItemByMedicineCode']['routes'];
      itemMedicineListUnit = response['listItemByMedicineCode']['strengths'];
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _itemByMedicineRequestModel.toJson());
  }

  Future getPatientAssessment(GetAssessmentReqModel getAssessmentReqModel) async {
    hasError = false;
    await baseAppClient.post(GET_ASSESSMENT, onSuccess: (dynamic response, int statusCode) {
      print("Success");
      patientAssessmentList.clear();
      response['AssessmentList']['entityList'].forEach((v) {
        patientAssessmentList.add(GetAssessmentResModel.fromJson(v));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: getAssessmentReqModel.toJson());
  }

  Future getPrescriptionListNew({required int mrn, required int appNo, int? episodeID}) async {
    _prescriptionReqModel = PrescriptionReqModel(patientMRN: mrn, appNo: appNo, episodeId: episodeID);
    hasError = false;
    _prescriptionList.clear();
    _prescriptionListNew.clear();
    await baseAppClient.post(GET_PRESCRIPTION_LIST, onSuccess: (dynamic response, int statusCode) {
      _prescriptionList.add(PrescriptionModel.fromJson(response['PrescriptionList']));
      if (response['PrescriptionList'] != null) {
        response['PrescriptionList']["entityList"].forEach((prescriptions) {
          _prescriptionListNew.add(PrescriptionEntityModel.fromJson(prescriptions));
        });
      }
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _prescriptionReqModel.toJson());
  }

  Future getDrugs({required String drugName}) async {
    _drugRequestModel = SearchDrugRequestModel(search: [drugName]);

    hasError = false;

    await baseAppClient.post(SEARCH_DRUG, onSuccess: (dynamic response, int statusCode) {
      doctorsList = [];
      doctorsList = response['MedicationList']['entityList'];
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _drugRequestModel.toJson());
  }

  Future getMedicationList({String drug = ''}) async {
    allMedicationList = [];
    hasError = false;
    _drugRequestModel.search = ["$drug"];
    await baseAppClient.post(SEARCH_DRUG, onSuccess: (dynamic response, int statusCode) {
      response['MedicationList']['entityList'].forEach((v) {
        allMedicationList.add(GetMedicationResponseModel.fromJson(v));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _drugRequestModel.toJson());
  }

  Future postPrescription(PostPrescriptionReqModel postProcedureReqModel) async {
    hasError = false;
    //_prescriptionList.clear();
    await baseAppClient.post(
      POST_PRESCRIPTION_LIST,
      onSuccess: (dynamic response, int statusCode) {
        print("Success");
      },
      onFailure: (String error, int statusCode) {
        hasError = true;
        super.error = error;
      },
      body: postProcedureReqModel.toJson(),
    );
  }

  Future updatePrescription(PostPrescriptionReqModel updatePrescriptionReqModel) async {
    hasError = false;
    //_prescriptionList.clear();
    await baseAppClient.post(
      UPDATE_PRESCRIPTION,
      onSuccess: (dynamic response, int statusCode) {
        print("Accepted");
      },
      onFailure: (String error, int statusCode) {
        hasError = true;
        super.error = error;
      },
      body: updatePrescriptionReqModel.toJson(),
    );
  }

  Future getDrugToDrug(VitalSignData? vital, List<GetAssessmentResModel> lstAssessments, List<GetAllergiesResModel> allergy, PatiantInformtion patient, List<dynamic> prescription) async {
    Map<String, dynamic> request = {
      "Prescription": {
        "objPatientInfo": {"Gender": patient.gender == 1 ? 'Male' : 'Female', "Age": AppDateUtils.convertDateFromServerFormat(patient.dateofBirth!, 'dd/MM/yyyy')},
        "objVitalSign": {"Height": vital?.heightCm ?? "", "Weight": vital?.weightKg ?? ""},
        "objPrescriptionItems": prescription,
        "objAllergies": getAllergiesObj(allergy),
        "objDiagnosis": getDiagnosisObj(lstAssessments),
        "IsDoctor": "false",
        "IsPharmacist": "false"
      }
    };

    hasError = false;
    await baseAppClient.post(DRUG_TO_DRUG, onSuccess: (dynamic response, int statusCode) {
      drugToDrug = [];
      drugToDrug = response['DrugToDrugResponse']['objPrescriptionCheckerResult'];
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: request);
  }

  Future calculateBoxQuantity({required int freq, required int duration, required int itemCode, required double strength, int? unitCode}) async {
    _boxQuantityRequestModel = CalculateBoxQuantityRequestModel(frequency: freq, duration: duration, itemCode: itemCode, strength: strength, strengthUnitID: unitCode);

    hasError = false;

    await baseAppClient.post(GET_BOX_QUANTITY, onSuccess: (dynamic response, int statusCode) {
      boxQuantity = response['BoxQuantity'];
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _boxQuantityRequestModel.toJson());
  }

  getAllergiesObj(List<GetAllergiesResModel> allergies) {
    var allergiesObj = [];
    allergies.forEach((element) {
      allergiesObj.add({
        "objProperties": {'Id': element.allergyDiseaseId, 'Name': element.allergyDiseaseName}
      });
    });
    return allergiesObj;
  }

  getDiagnosisObj(List<GetAssessmentResModel> lstAssessments) {
    var lstAssessmentsObj = [];
    lstAssessments.forEach((element) {
      lstAssessmentsObj.add({
        "objProperties": {'Id': element.icdCode10ID, 'Name': element.asciiDesc}
      });
    });
    return lstAssessmentsObj;
  }

  List<Prescriptions> prescriptionsList = [];
  List<GetMedicationForInPatientModel> medicationForInPatient = [];
  List<PrescriptionsOrder> prescriptionsOrderList = [];
  List<PrescriotionInPatient> prescriptionInPatientList = [];

  GetMedicationForInPatientRequestModel _getMedicationForInPatientRequestModel = GetMedicationForInPatientRequestModel();

  Future getPrescriptions(PatiantInformtion patient) async {
    hasError = false;
    Map<String, dynamic> body = Map();
    body['isDentalAllowedBackend'] = false;
    await baseAppClient.postPatient(GET_PRESCRIPTION, patient: patient, onSuccess: (dynamic response, int statusCode) {
      prescriptionsList.clear();
      response['PatientPrescriptionList'].forEach((prescriptions) {
        prescriptionsList.add(Prescriptions.fromJson(prescriptions));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
  }

  RequestPrescriptionReport _requestPrescriptionReport = RequestPrescriptionReport(appointmentNo: 0, isDentalAllowedBackend: false);
  List<PrescriptionReport> prescriptionReportList = [];

  Future getPrescriptionReport({required Prescriptions prescriptions, required PatiantInformtion patient}) async {
    hasError = false;
    _requestPrescriptionReport.dischargeNo = prescriptions.dischargeNo;
    _requestPrescriptionReport.projectID = prescriptions.projectID;
    _requestPrescriptionReport.clinicID = prescriptions.clinicID;
    _requestPrescriptionReport.setupID = prescriptions.setupID;
    _requestPrescriptionReport.episodeID = prescriptions.episodeID;
    _requestPrescriptionReport.appointmentNo = prescriptions.appointmentNo;

    await baseAppClient.postPatient(prescriptions.isInOutPatient! ? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT_NEW, patient: patient, onSuccess: (dynamic response, int statusCode) {
      prescriptionReportList.clear();
      prescriptionReportEnhList.clear();
      if (prescriptions.isInOutPatient!) {
        response['ListPRM'].forEach((prescriptions) {
          prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions));
          prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions));
        });
      } else {
        response['INP_GetPrescriptionReport_List'].forEach((prescriptions) {
          prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions));
        });
      }
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _requestPrescriptionReport.toJson());
  }

  RequestGetListPharmacyForPrescriptions requestGetListPharmacyForPrescriptions = RequestGetListPharmacyForPrescriptions(
    latitude: 0,
    longitude: 0,
    isDentalAllowedBackend: false,
  );
  List<PharmacyPrescriptions> pharmacyPrescriptionsList = [];

  RequestPrescriptionReportEnh _requestPrescriptionReportEnh = RequestPrescriptionReportEnh(
    isDentalAllowedBackend: false,
  );

  List<PrescriptionReportEnh> prescriptionReportEnhList = [];

  Future getPrescriptionReportEnh({PrescriptionsOrder? prescriptionsOrder, required PatiantInformtion patient}) async {
    ///This logic copy from the old app from class [order-history.component.ts] in line 45
    bool isInPatient = false;
    prescriptionsList.forEach((element) {
      if (prescriptionsOrder!.appointmentNo == "0") {
        if (element.dischargeNo == int.parse(prescriptionsOrder.dischargeID)) {
          _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo;
          _requestPrescriptionReportEnh.clinicID = element.clinicID;
          _requestPrescriptionReportEnh.projectID = element.projectID;
          _requestPrescriptionReportEnh.episodeID = element.episodeID;
          _requestPrescriptionReportEnh.setupID = element.setupID;
          _requestPrescriptionReportEnh.dischargeNo = element.dischargeNo;
          isInPatient = element.isInOutPatient!;
        }
      } else {
        if (int.parse(prescriptionsOrder.appointmentNo) == element.appointmentNo) {
          _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo;
          _requestPrescriptionReportEnh.clinicID = element.clinicID;
          _requestPrescriptionReportEnh.projectID = element.projectID;
          _requestPrescriptionReportEnh.episodeID = element.episodeID;
          _requestPrescriptionReportEnh.setupID = element.setupID;
          _requestPrescriptionReportEnh.dischargeNo = element.dischargeNo;
          isInPatient = element.isInOutPatient!;

          ///call inpGetPrescriptionReport
        }
      }
    });

    hasError = false;

    await baseAppClient.postPatient(isInPatient ? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT_NEW, patient: patient, onSuccess: (dynamic response, int statusCode) {
      prescriptionReportEnhList.clear();

      if (isInPatient) {
        response['ListPRM'].forEach((prescriptions) {
          prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions));
        });
      } else {
        response['INP_GetPrescriptionReport_List'].forEach((prescriptions) {
          PrescriptionReportEnh reportEnh = PrescriptionReportEnh.fromJson(prescriptions);
          reportEnh.itemDescription = prescriptions['ItemDescriptionN'];
          prescriptionReportEnhList.add(reportEnh);
        });
      }
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _requestPrescriptionReportEnh.toJson());
  }

  Future getPrescriptionsOrders() async {
    Map<String, dynamic> body = Map();
    body['isDentalAllowedBackend'] = false;
    await baseAppClient.post(GET_PRESCRIPTIONS_ALL_ORDERS, onSuccess: (dynamic response, int statusCode) {
      prescriptionsOrderList.clear();
      response['PatientER_GetPatientAllPresOrdersList'].forEach((prescriptionsOrder) {
        prescriptionsOrderList.add(PrescriptionsOrder.fromJson(prescriptionsOrder));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
  }

  Future getMedicationForInPatient(PatiantInformtion patient, {required bool isVidaPlusProject}) async {
    hasError = false;
    _getMedicationForInPatientRequestModel = GetMedicationForInPatientRequestModel(
      isDentalAllowedBackend: false,
      admissionNo: isVidaPlusProject ? patient.admissionID :  int.parse(patient.admissionNo!),
      projectID: patient.projectId,
    );
    await baseAppClient.postPatient(GET_MEDICATION_FOR_IN_PATIENT, patient: patient, onSuccess: (dynamic response, int statusCode) {
      medicationForInPatient.clear();
      response['List_GetMedicationForInpatient'].forEach((prescriptions) {
        medicationForInPatient.add(GetMedicationForInPatientModel.fromJson(prescriptions));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _getMedicationForInPatientRequestModel.toJson());
  }

  Future isPrincipalCovered(PatiantInformtion patient) async {
    hasError = false;

    await baseAppClient.post(IS_PRINCIPAL_COVERED,
        body:{
          "PatientID":patient.patientId,
          "EncounterNo":patient.appointmentNo ?? 0,
          "EncounterType":patient.appointmentTypeId ?? 0,
          "DoctorID":patient.doctorId,
        }, onSuccess: (dynamic response, int statusCode) {
          isDiagnosisCovered = response['IsDiagnosisCovered'];
        }, onFailure: (String error, int statusCode) {
          hasError = true;
          super.error = error;
        });
  }
  Future getIcd10DISESECode(PatiantInformtion patient, int itemID) async {
    hasError = false;

    await baseAppClient.post(GET_ICD10DISEASE,
        body:{
          "PatientMRN":patient.patientId,
          "ItemID":itemID,
          "DoctorID":patient.doctorId,
        }, onSuccess: (dynamic response, int statusCode) {
          icd10CodeListByItem.clear();
          Map<String, dynamic> data = response['List_ICD10Desease'];
          data['entityList'].forEach((v) {
            icd10CodeListByItem.add(MasterKeyModel.fromJson(v));
          });

        }, onFailure: (String error, int statusCode) {
          hasError = true;
          super.error = error;
        });
  }
}
