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/diagnosis/GetDiagnosisForInPatientRequestModel.dart';
import 'package:doctor_app_flutter/core/model/diagnosis/GetDiagnosisForInPatientResponseModel.dart';
import 'package:doctor_app_flutter/core/model/doctor/doctor_profile_model.dart';
import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_request_model.dart';
import 'package:doctor_app_flutter/core/model/patient/my_referral/PendingReferral.dart';
import 'package:doctor_app_flutter/core/model/patient/my_referral/clinic-doctor.dart';
import 'package:doctor_app_flutter/core/model/patient/my_referral/my_referred_patient_model.dart';
import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/core/model/referral/DischargeReferralPatient.dart';
import 'package:doctor_app_flutter/core/model/referral/MyReferralPatientModel.dart';
import 'package:doctor_app_flutter/core/service/hospitals/hospitals_service.dart';
import 'package:doctor_app_flutter/core/service/patient/DischargedPatientService.dart';
import 'package:doctor_app_flutter/core/service/patient/MyReferralPatientService.dart';
import 'package:doctor_app_flutter/core/service/patient/ReferralService.dart';
import 'package:doctor_app_flutter/core/service/patient/patient-doctor-referral-service.dart';
import 'package:doctor_app_flutter/core/service/patient/patient_service.dart';
import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart';
import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart';
import 'package:flutter/cupertino.dart';

import '../../locator.dart';

class PatientReferralViewModel extends BaseViewModel {
  PatientReferralService _referralPatientService = locator<PatientReferralService>();

  ReferralService _referralService = locator<ReferralService>();

  HospitalsService _hospitalService = locator<HospitalsService>();

  MyReferralInPatientService _myReferralService = locator<MyReferralInPatientService>();

  DischargedPatientService _dischargedPatientService = locator<DischargedPatientService>();

  List<DischargeReferralPatient> get myDischargeReferralPatient => _dischargedPatientService.myDischargeReferralPatients;

  List<dynamic>? branchesList = [];

  List<dynamic>? get clinicsList => _referralPatientService.clinicsList;

  List<dynamic> get referralFrequencyList => _referralPatientService.frequencyList;

  List<dynamic> doctorsList = [];

  List<ClinicDoctor> get clinicDoctorsList => _referralPatientService.doctorsList;

  List<MyReferralPatientModel> get myReferralPatients => _myReferralService.myReferralPatients;

  List<MyReferredPatientModel> get listMyReferredPatientModel => _referralPatientService.listMyReferredPatientModel;

  List<PendingReferral> get pendingReferral => _referralPatientService.pendingReferralList;

  List<PendingReferral> get patientReferral => _referralPatientService.patientReferralList;

  List<PatiantInformtion> get patientArrivalList => _referralPatientService.patientArrivalList;

  PatientService _patientService = locator<PatientService>();

  List<dynamic>  diagnosisForInPatientList = [];



  Future getDiagnosisForInPatient(
      GetDiagnosisForInPatientRequestModel requestModel, bool isVidaPlusProject, PatiantInformtion patient) async {
    await getDoctorProfile();
    setState(ViewState.Busy);
    List<dynamic> response = [];

    if(isVidaPlusProject){
      response =   await _patientService.getDiagnosis(patient);
    }

    if (_patientService.hasError) {
      error = _patientService.error;
      setState(ViewState.ErrorLocal);
    } else {
      diagnosisForInPatientList = response;
      setState(ViewState.Idle);
    }
  }

  Future getPatientReferral(PatiantInformtion patient) async {
    setState(ViewState.Busy);
    await _referralPatientService.getPatientReferral(patient);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else {
      await getBranches();
      if (patientReferral.length == 0) {
        await getMasterLookup(MasterKeysService.physiotherapyGoals);
      } else {
        setState(ViewState.Idle);
      }
    }
  }

  Future getMasterLookup(MasterKeysService masterKeys) async {
    setState(ViewState.Busy);
    await _referralPatientService.getMasterLookup(masterKeys);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    }
      await getBranches();
  }

  Future getBranches() async {
    setState(ViewState.BusyLocal);
    if( _hospitalService.hospitals.isNotEmpty){
      mapHospitalToBranchList();
      setState(ViewState.Idle);
      return;
    }

    DoctorProfileModel doctorProfile = await getDoctorProfile();
    await _hospitalService.getHospitals(GetHospitalsRequestModel(
      memberID: doctorProfile.doctorID?.toString()??"" ,doctorID: doctorProfile.doctorID?.toString()??""
    ));
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else {
      mapHospitalToBranchList();
      setState(ViewState.Idle);
    }
  }

  mapHospitalToBranchList() async {
    branchesList!.clear();
    DoctorProfileModel doctorProfile = await getDoctorProfile();
    _hospitalService.hospitals.forEach((element) {
      if(doctorProfile.projectID != element.facilityId)
      branchesList!.add({"facilityId": element.facilityId, "facilityName": element.facilityName});
    });
  }

  Future getClinics(int projectId) async {
    setState(ViewState.BusyLocal);
    await _referralPatientService.getClinicsList(projectId);
    // await _referralPatientService.getProjectInfo(projectId);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.ErrorLocal);
    } else
      setState(ViewState.Idle);
  }

  Future getClinicDoctors(PatiantInformtion patient, int clinicId, int branchId) async {
    setState(ViewState.BusyLocal);
    await _referralPatientService.getDoctorsList(patient, clinicId, branchId);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.ErrorLocal);
    } else {
      doctorsList.clear();
      clinicDoctorsList.forEach((element) {
        doctorsList.add(element.toJson());
      });
      setState(ViewState.Idle);
    }
  }

  Future<dynamic> getDoctorBranch() async {
    DoctorProfileModel doctorProfile = await getDoctorProfile();
    if (doctorProfile != null) {
      dynamic _selectedBranch = {"facilityId": doctorProfile.projectID, "facilityName": doctorProfile.projectName};
      return _selectedBranch;
    }
    return null;
  }

  Future getMyReferredPatient({bool isFirstTime = true}) async {
    if (isFirstTime)
      setState(ViewState.Busy);
    else
      setState(ViewState.BusyLocal);
    await _referralPatientService.getMyReferredPatient();
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMyReferredOutPatient({bool isFirstTime = true}) async {
    if (isFirstTime)
      setState(ViewState.Busy);
    else
      setState(ViewState.BusyLocal);
    await _referralPatientService.getMyReferredOutPatient();
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  MyReferredPatientModel getReferredPatientItem(int index) {
    return listMyReferredPatientModel[index];
  }

  Future getPendingReferralPatients() async {
    setState(ViewState.Busy);
    await _referralPatientService.getPendingReferralList();
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMyReferralPatientService({bool localBusy = false}) async {
    if (localBusy)
      setState(ViewState.BusyLocal);
    else
      setState(ViewState.Busy);
    await _myReferralService.getMyReferralPatientService();
    if (_myReferralService.hasError) {
      error = _myReferralService.error;
      if (localBusy)
        setState(ViewState.ErrorLocal);
      else
        setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future getMyReferralOutPatientService({bool localBusy = false}) async {
    if (localBusy)
      setState(ViewState.BusyLocal);
    else
      setState(ViewState.Busy);
    await _myReferralService.getMyReferralOutPatientService();
    if (_myReferralService.hasError) {
      error = _myReferralService.error;
      if (localBusy)
        setState(ViewState.ErrorLocal);
      else
        setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future replay(String referredDoctorRemarks, MyReferralPatientModel referral) async {
    setState(ViewState.Busy);
    await _myReferralService.replay(referredDoctorRemarks, referral);
    if (_myReferralService.hasError) {
      error = _myReferralService.error;
      setState(ViewState.ErrorLocal);
    } else
      getMyReferralPatientService();
  }

  Future responseReferral(MyReferralPatientModel referralPatient, bool isAccepted) async {
    setState(ViewState.Busy);
    await _referralPatientService.responseReferral(referralPatient, isAccepted);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.ErrorLocal);
    } else
      setState(ViewState.Idle);
  }

  Future makeReferral(PatiantInformtion patient, String isoStringDate, int projectID, int clinicID, int doctorID, String remarks) async {
    setState(ViewState.BusyLocal);
    await _referralPatientService.makeReferral(patient, isoStringDate, projectID, clinicID, doctorID, remarks);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.ErrorLocal);
    } else {
      setState(ViewState.Idle);
    }
  }

  Future makeInPatientReferral(bool isVidaPlusProject,
      {PatiantInformtion? patient,
      int? projectID,
      int? clinicID,
      int? doctorID,
      int? frequencyCode,
      int? priority,
      String? referralDate,
      String? remarks,
      String? ext,
      bool isLocalBusy = false,
        dynamic? diagnosis}) async {
    if (isLocalBusy)
      setState(ViewState.BusyLocal);
    else
      setState(ViewState.Busy);
    await _referralService.referralPatient(
      patientID: patient!.patientId,
      roomID: patient.roomId,
      referralClinic: clinicID,
      admissionNo: isVidaPlusProject?patient.admissionID:int.parse(patient.admissionNo!),
      referralDoctor: doctorID,
      patientTypeID: patient.patientType,
      referringDoctorRemarks: remarks,
      priority: priority,
      frequency: frequencyCode,
      diagnosisCode: ProjectViewModel.getVidaPlusStatus()? diagnosis['selectedIcdCode']:null,
      diagnosisDescription: ProjectViewModel.getVidaPlusStatus()?diagnosis['selectedDisease']: null ,
      extension: ext,
    );
    if (_referralService.hasError) {
      error = _referralService.error;
      setState(ViewState.ErrorLocal);
    } else {
      setState(ViewState.Idle);
    }
  }

  Future getReferralFrequencyList() async {
    setState(ViewState.Busy);
    await _referralPatientService.getReferralFrequencyList();
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  Future verifyReferralDoctorRemarks(MyReferredPatientModel referredPatient) async {
    setState(ViewState.Busy);
    await _referralPatientService.verifyReferralDoctorRemarks(referredPatient);
    if (_referralPatientService.hasError) {
      error = _referralPatientService.error;
      setState(ViewState.ErrorLocal);
    } else {
      getMyReferredPatient();
      setState(ViewState.Idle);
    }
  }

  Future gtMyDischargeReferralPatient() async {
    setState(ViewState.Busy);
    await _dischargedPatientService.gtMyDischargeReferralPatient();
    if (_dischargedPatientService.hasError) {
      error = _dischargedPatientService.error;
      setState(ViewState.Error);
    } else
      setState(ViewState.Idle);
  }

  String getReferralStatusNameByCode(int statusCode, BuildContext context) {
    switch (statusCode) {
      case 1:
        return TranslationBase.of(context).referralStatusHold /*pending*/;
      case 2:
        return TranslationBase.of(context).referralStatusActive /* accepted*/;
      case 4:
        return TranslationBase.of(context).referralStatusCancelled /*rejected*/;
      case 46:
        return TranslationBase.of(context).referralStatusCompleted /*accepted*/;
      case 63:
        return TranslationBase.of(context).rejected /*referralStatusNotSeen*/;
      default:
        return "-";
    }
  }

  PatiantInformtion getPatientFromReferral(MyReferredPatientModel referredPatient) {
    PatiantInformtion patient = PatiantInformtion();
    patient.doctorId = referredPatient.doctorID;
    patient.doctorName = referredPatient.doctorName;
    patient.patientId = referredPatient.patientID;
    patient.patientMRN = referredPatient.patientID;
    patient.firstName = referredPatient.firstName;
    patient.middleName = referredPatient.middleName;
    patient.lastName = referredPatient.lastName;
    patient.gender = referredPatient.gender;
    patient.dateofBirth = referredPatient.dateofBirth;
    patient.mobileNumber = referredPatient.mobileNumber;
    patient.emailAddress = referredPatient.emailAddress;
    patient.patientIdentificationNo = referredPatient.patientIdentificationNo;
    patient.patientType = referredPatient.patientType;
    patient.admissionNo = referredPatient.admissionNo;
    patient.admissionDate = referredPatient.admissionDate;
    patient.roomId = referredPatient.roomID;
    patient.bedId = referredPatient.bedID;
    patient.nationalityName = referredPatient.nationalityName;
    patient.nationalityFlagURL = referredPatient.nationalityFlagURL;
    patient.age = referredPatient.age;
    patient.clinicDescription = referredPatient.clinicDescription;
    patient.appointmentNo = referredPatient.appointmentNo;

    return patient;
  }

  PatiantInformtion getPatientFromReferralO(MyReferralPatientModel referredPatient) {
    PatiantInformtion patient = PatiantInformtion();
    patient.doctorId = referredPatient.doctorID;
    patient.doctorName = referredPatient.doctorName;
    patient.patientId = referredPatient.patientID;
    patient.firstName = referredPatient.firstName;
    patient.middleName = referredPatient.middleName;
    patient.lastName = referredPatient.lastName;
    patient.gender = referredPatient.gender;
    patient.dateofBirth = referredPatient.dateofBirth;
    patient.mobileNumber = referredPatient.mobileNumber;
    patient.emailAddress = referredPatient.emailAddress;
    patient.patientIdentificationNo = referredPatient.patientIdentificationNo;
    patient.patientType = referredPatient.patientType;
    patient.admissionNo = referredPatient.admissionNo;
    patient.admissionDate = referredPatient.admissionDate;
    patient.roomId = referredPatient.roomID;
    patient.bedId = referredPatient.bedID;
    patient.nationalityName = referredPatient.nationalityName;
    patient.nationalityFlagURL = referredPatient.nationalityFlagURL;
    patient.age = referredPatient.age;
    patient.clinicDescription = referredPatient.clinicDescription;
    return patient;
  }

  PatiantInformtion getPatientFromDischargeReferralPatient(DischargeReferralPatient referredPatient) {
    PatiantInformtion patient = PatiantInformtion();
    patient.doctorId = referredPatient.doctorID;
    patient.doctorName = referredPatient.doctorName;
    patient.patientId = referredPatient.patientID;
    patient.firstName = referredPatient.firstName;
    patient.middleName = referredPatient.middleName;
    patient.lastName = referredPatient.lastName;
    patient.gender = referredPatient.gender;
    patient.dateofBirth = referredPatient.dateofBirth;
    patient.mobileNumber = referredPatient.mobileNumber;
    patient.emailAddress = referredPatient.emailAddress;
    patient.patientIdentificationNo = referredPatient.patientIdentificationNo;
    patient.patientType = referredPatient.patientType;
    patient.admissionNo = referredPatient.admissionNo;
    patient.admissionDate = referredPatient.admissionDate;
    patient.roomId = referredPatient.roomID;
    patient.bedId = referredPatient.bedID;
    patient.nationalityName = referredPatient.nationalityName;
    patient.nationalityFlagURL = ''; // TODO from backend referredPatient.nationalityFlagURL;
    patient.age = referredPatient.age;
    patient.clinicDescription = referredPatient.clinicDescription;
    return patient;
  }

  Future replayReferred(String referredDoctorRemarks, MyReferralPatientModel referral, int referralStatus) async {
    setState(ViewState.Busy);
    await _myReferralService.replayReferred(referredDoctorRemarks, referral, referralStatus);
    if (_myReferralService.hasError) {
      error = _myReferralService.error;
      setState(ViewState.ErrorLocal);
    } else
      getMyReferralPatientService();
  }
}
