import 'package:doctor_app_flutter/core/enum/master_lookup_key.dart';
import 'package:doctor_app_flutter/core/enum/view_state.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_res_model.dart';
import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/core/model/procedure/procedure_template_details_model.dart';
import 'package:doctor_app_flutter/core/model/search_drug/get_medication_response_model.dart';
import 'package:doctor_app_flutter/core/service/patient_medical_file/prescription/medicine_service.dart';
import 'package:doctor_app_flutter/core/service/patient_medical_file/prescription/prescription_service.dart';
import 'package:doctor_app_flutter/core/service/patient_medical_file/procedure/procedure_service.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_req_model.dart';
import 'package:doctor_app_flutter/core/viewModel/prescription/prescription_view_model.dart';
import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_container.dart';
import 'package:flutter/cupertino.dart';
import '../../locator.dart';
import '../../utils/dr_app_toast_msg.dart';
import '../../utils/utils.dart';
import '../../widgets/shared/loader/gif_loader_dialog_utils.dart';
import '../model/Prescriptions/post_prescrition_req_model.dart';
import '../model/Prescriptions/prescription_model.dart';
import 'base_view_model.dart';

class MedicineViewModel extends BaseViewModel {
  bool hasError = false;
  MedicineService _medicineService = locator<MedicineService>();
  ProcedureService _procedureService = locator<ProcedureService>();
  PrescriptionService _prescriptionService = locator<PrescriptionService>();

  List<ProcedureTempleteDetailsModel> get procedureTemplate => _procedureService.templateList;
  List<ProcedureTempleteDetailsModelList> templateList = [];

  get pharmacyItemsList => _medicineService.pharmacyItemsList;

  get searchText => _medicineService.searchText;

  get pharmaciesList => _medicineService.pharmaciesList;

  get medicationStrengthList => _prescriptionService.medicationStrengthList;

  get medicationDurationList => _prescriptionService.medicationDurationList;

  get medicationRouteList => _prescriptionService.medicationRouteList;

  get medicationFrequencyList => _prescriptionService.medicationFrequencyList;

  get boxQuintity => _prescriptionService.boxQuantity;

  get medicationIndicationsList => _prescriptionService.medicationIndicationsList;

  get medicationDoseTimeList => _prescriptionService.medicationDoseTimeList;

  List<GetAssessmentResModel> get patientAssessmentList => _prescriptionService.patientAssessmentList;

  List<GetMedicationResponseModel> get allMedicationList => _prescriptionService.allMedicationList;

  List<dynamic> get itemMedicineList => _prescriptionService.itemMedicineList;

  List<dynamic> get itemMedicineListRoute => _prescriptionService.itemMedicineListRoute;

  List<dynamic> get itemMedicineListUnit => _prescriptionService.itemMedicineListUnit;

  Future getItem({required int itemID, bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await _prescriptionService.getItem(itemID: itemID);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.ErrorLocal);
    } else
      setState(ViewState.Idle);
  }

  setTemplateListDependOnId() {
    procedureTemplate.forEach((element) {
      List<ProcedureTempleteDetailsModelList> templateListData = templateList.where((elementTemplate) => elementTemplate.templateId == element.templateID).toList();

      if (templateListData.length != 0) {
        templateList[templateList.indexOf(templateListData[0])].procedureTemplate.add(element);
      } else {
        var template = ProcedureTempleteDetailsModelList(templateName: element.templateName, templateId: element.templateID, template: element);
        if (!templateList.contains(template)) templateList.add(template);
      }
    });
    print(templateList.length.toString());
  }

  getPrescriptionForDrug(
    List<PrescriptionModel> prescriptionList,
    MedicineViewModel model,
  ) {
    var prescriptionDetails = [];
    if (prescriptionList.length > 0) {
      prescriptionList[0].entityList!.forEach((element) {
        if (element.mediSpanGPICode != null) {
          prescriptionDetails.add({
            'DrugId': element.mediSpanGPICode,
            'DrugName': element.medicationName,
            'Dose': element.doseDailyQuantity,
            'DoseType': element.doseDailyUnitID,
            'Unit': element.uom,
            'FrequencyType': element.frequencyID,
            'Duration': element.doseDurationDays,
            'RouteID': element.routeID,
            'IsScreen': element.isSIG
          });
        }
      });
    }
    return prescriptionDetails;
  }

  postPrescription(
      {String? duration,
      String? doseTimeIn,
      String? dose,
      String? drugId,
      String? strength,
      String? route,
      String? frequency,
      String? indication,
      String? instruction,
      PrescriptionViewModel? model,
      DateTime? doseTime,
      String? doseUnit,
      String? icdCode,
      PatiantInformtion? patient,
      String? patientType,
      bool isLocalBusy = false,
      BuildContext? context,
      PrescriptionRequestModel? prescriptionRequestModel}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    PostPrescriptionReqModel postProcedureReqModel = new PostPrescriptionReqModel();
    List<PrescriptionRequestModel> prescriptionList = [];

    postProcedureReqModel.appointmentNo = patient!.appointmentNo;
    postProcedureReqModel.clinicID = patient.clinicId;
    postProcedureReqModel.episodeID = patient.episodeNo;
    postProcedureReqModel.patientMRN = patient.patientMRN;

    prescriptionList.add(PrescriptionRequestModel(
        covered: true,
        dose: double.parse(dose!),
        itemId: drugId!.isEmpty ? 1 : int.parse(drugId!),
        doseUnitId: int.parse(doseUnit!),
        route: route!.isEmpty ? 1 : int.parse(route),
        frequency: frequency!.isEmpty ? 1 : int.parse(frequency),
        remarks: instruction,
        approvalRequired: true,
        icdcode10Id: icdCode.toString(),
        doseTime: doseTimeIn!.isEmpty ? 1 : int.parse(doseTimeIn),
        duration: duration!.isEmpty ? 1 : int.parse(duration),
        doseStartDate: doseTime!.toIso8601String()));
    postProcedureReqModel.prescriptionRequestModel = prescriptionList;
    await _prescriptionService.postPrescription(postProcedureReqModel);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      if (isLocalBusy) {
        setState(ViewState.ErrorLocal);
      } else {
        setState(ViewState.Error);
      }
    } else {
      setState(ViewState.Idle);
      // TODO Elham* to investigate why we are calling that
      setTemplateListDependOnId();
    }
  }

  Future getAssessmentList({PatiantInformtion? patientInfo, bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    GetAssessmentReqModel getAssessmentReqModel =
        GetAssessmentReqModel(patientMRN: patientInfo!.patientMRN!, episodeID: patientInfo.episodeNo.toString(), editedBy: '', doctorID: '', appointmentNo: patientInfo.appointmentNo);
    // if (medicationStrengthList.length == 0) {
      await getMedicationStrength(isLocalBusy: true);
    // }
    // if (medicationDurationList.length == 0) {
      await getMedicationDuration(isLocalBusy: true);
    // }
    // if (medicationDoseTimeList.length == 0) {
      await getMedicationDoseTime(isLocalBusy: true);
    // }
    await getPatientAssessment(getAssessmentReqModel, isLocalBusy: true);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      if (isLocalBusy) {
        setState(ViewState.ErrorLocal);
      } else {
        setState(ViewState.Error);
      }
    } else {
      setState(ViewState.Idle);
    }
  }

  Future getMedicineItem(String itemName) async {
    setState(ViewState.Busy);
    await _medicineService.getMedicineItem(itemName);
    if (_medicineService.hasError) {
      error = _medicineService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  getMedicationList({String? drug, bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await getDoctorProfile(isGetProfile: true);
    await _prescriptionService.getMedicationList(drug: drug!);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      if (isLocalBusy) {
        setState(ViewState.ErrorLocal);
      } else {
        setState(ViewState.Error);
      }
    } else {
      setState(ViewState.Idle);
    }
  }

  Future getPatientAssessment(GetAssessmentReqModel getAssessmentReqModel, {bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await _prescriptionService.getPatientAssessment(getAssessmentReqModel);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.ErrorLocal);
    } else
      setState(ViewState.Idle);
  }

  Future onInitiateAllPrescription({PrescriptionViewModel? model, PatiantInformtion? patient, ProcedureTempleteDetailsModel? groupProcedures, BuildContext? context, bool isLocalBusy = true}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    model!.getItem(
      itemID: int.parse(
        groupProcedures!.aliasN!.replaceAll("item code ;", ""),
      ),
    );

    GetAssessmentReqModel getAssessmentReqModel =
        GetAssessmentReqModel(patientMRN: patient!.patientMRN!, episodeID: patient.episodeNo.toString(), editedBy: '', doctorID: '', appointmentNo: patient.appointmentNo);
    // if (medicationStrengthList.length == 0) {
      await getMedicationStrength();
    // }
    // if (medicationDurationList.length == 0) {
      await getMedicationDuration();
    // }
    // if (medicationDoseTimeList.length == 0) {
      await getMedicationDoseTime();
    // }
    await getPatientAssessment(getAssessmentReqModel);
  }

  Future getMedicationStrength({bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationStrength);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      if (isLocalBusy) {
        setState(ViewState.ErrorLocal);
      } else {
        setState(ViewState.Error);
      }
    } else
      setState(ViewState.Idle);
  }

  Future getMedicationRoute() async {
    setState(ViewState.Busy);
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationRoute);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMedicationIndications() async {
    setState(ViewState.Busy);
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationIndications);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMedicationDoseTime({bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationDoseTime);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMedicationFrequency() async {
    setState(ViewState.Busy);
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationFrequency);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMedicationDuration({bool isLocalBusy = false}) async {
    if (isLocalBusy) {
      setState(ViewState.BusyLocal);
    } else {
      setState(ViewState.Busy);
    }
    await _prescriptionService.getMasterLookup(MasterKeysService.MedicationDuration);
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      setState(ViewState.ErrorLocal);
    } else
      setState(ViewState.Idle);
  }

  Future getBoxQuantity({int? itemCode, int? duration, double? strength, int? freq, bool showLoader = true, int? unitCode}) async {

    if(showLoader)
    setState(ViewState.Busy);
    await _prescriptionService.calculateBoxQuantity(
      strength: strength!,
      itemCode: itemCode!,
      duration: duration!,
      freq: freq!,
      unitCode: unitCode,
    );
    if (_prescriptionService.hasError) {
      error = _prescriptionService.error;
      if(showLoader)
      setState(ViewState.Error);
    } else{
      if(showLoader)
      setState(ViewState.Idle);
    }
  }

  Future getPharmaciesList(int itemId) async {
    setState(ViewState.Busy);
    await _medicineService.getPharmaciesList(itemId);
    if (_medicineService.hasError) {
      error = _medicineService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  dynamic getLookupById(List<dynamic> list, String id) {
    for (int i = 0; i < list.length; i++) {
      if (list[i]['id'].toString() == id) {
        return list[i];
      }
    }
    return null;
  }

  dynamic getLookupByIdFilter(List<dynamic> list, String id) {
    for (int i = 0; i < list.length; i++) {
      if (list[i]['parameterCode'].toString() == id) {
        return list[i];
      }
    }
    return null;
  }
}
