import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_analysis_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_delivery_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_detail_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_delivery_order_summary_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/services/prescription_reminder_prefs_service.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';

class PrescriptionsViewModel extends ChangeNotifier {
  bool isPrescriptionsOrdersLoading = false;
  bool isPrescriptionsDetailsLoading = false;

  PrescriptionsRepo prescriptionsRepo;
  ErrorHandlerService errorHandlerService;
  NavigationService navServices;

  // Prescription Orders Lists
  List<PatientPrescriptionsResponseModel> patientPrescriptionOrders = [];

  List<PrescriptionsList> patientPrescriptionOrdersByClinic = [];
  List<PrescriptionsList> patientPrescriptionOrdersByHospital = [];
  List<PrescriptionsList> patientPrescriptionOrdersViewList = [];

  // Prescription Details List
  List<PrescriptionDetailResponseModel> prescriptionDetailsList = [];

  bool isSortByClinic = true;

  String prescriptionInstructionsPDFLink = "";

  String prescriptionPDFBase64Data = "";

  late GeocodeResponse locationGeocodeResponse;

  bool isPrescriptionsDeliveryOrdersLoading = false;

  bool isPrescriptionsDataNeedsReloading = true;
  List<PrescriptionDeliveryResponseModel> prescriptionsOrderList = [];

  DateTime? selectedReminderTime;

  PrescriptionAnalysisResponse? prescriptionAnalysisResponse;
  bool isPrescriptionAIAnalysisNeedsToBeShown = false;

  PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService, required this.navServices});

  initPrescriptionsViewModel() {
    if (isPrescriptionsDataNeedsReloading) {
      patientPrescriptionOrders.clear();
      patientPrescriptionOrdersByClinic.clear();
      patientPrescriptionOrdersByHospital.clear();
      patientPrescriptionOrdersViewList.clear();
      prescriptionsOrderList.clear();
      isPrescriptionsOrdersLoading = true;
      getPatientPrescriptionOrders();
    }
    isSortByClinic = true;
    isPrescriptionsDeliveryOrdersLoading = true;
    notifyListeners();
  }

  Future<bool> checkIfReminderExistForPrescription(int index) async {
    final item = prescriptionDetailsList[index];
    // Check device calendar
    final calendarHasEvent = await CalenderUtilsNew.instance.checkIfEventExist(item.itemID?.toString() ?? "");
    prescriptionDetailsList[index].hasReminder = calendarHasEvent;

    // Sync the SharedPreferences status to match the calendar reality
    if (item.appointmentNo != null && item.itemID != null && item.projectID != null) {
      await PrescriptionReminderPrefsService.instance.setReminderStatus(
        appointmentNo: item.appointmentNo!,
        itemDescription: item.itemDescription ?? '',
        itemID: item.itemID!,
        projectID: item.projectID!,
        hasReminder: calendarHasEvent,
      );
    }
    return calendarHasEvent;
  }

  setPrescriptionsDetailsLoading() {
    isPrescriptionsDetailsLoading = true;
    prescriptionDetailsList.clear();
    notifyListeners();
  }

  setPrescriptionItemReminder(bool value, PrescriptionDetailResponseModel item) {
    int index = prescriptionDetailsList.indexOf(item);
    if (index != -1) {
      prescriptionDetailsList[index].hasReminder = value;
      notifyListeners();

      // Persist to SharedPreferences
      final target = prescriptionDetailsList[index];
      if (target.appointmentNo != null && target.itemID != null && target.projectID != null) {
        PrescriptionReminderPrefsService.instance.setReminderStatus(
          appointmentNo: target.appointmentNo!,
          itemDescription: target.itemDescription ?? '',
          itemID: target.itemID!,
          projectID: target.projectID!,
          hasReminder: value,
        );
      }
    }
  }

  notify() {
    notifyListeners();
  }

  setIsSortByClinic(bool value) {
    isSortByClinic = value;
    if (isSortByClinic) {
      patientPrescriptionOrdersViewList = patientPrescriptionOrdersByClinic;
    } else {
      patientPrescriptionOrdersViewList = patientPrescriptionOrdersByHospital;
    }
    notifyListeners();
  }

  Future<void> getPatientPrescriptionOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    if (!isPrescriptionsDataNeedsReloading) {
      return;
    }

    final result = await prescriptionsRepo.getPatientPrescriptionOrders(patientId: "1231755");

    result.fold(
      // (failure) async => await errorHandlerService.handleError(failure: failure),
      (failure) async {
        isPrescriptionsOrdersLoading = false;
        notifyListeners();
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientPrescriptionOrders = apiResponse.data!;
          isPrescriptionsOrdersLoading = false;

          for (var element in patientPrescriptionOrders) {
            List<PrescriptionsList> prescriptionsByClinic = patientPrescriptionOrdersByClinic.where((elementClinic) => elementClinic.filterName == element.clinicDescription).toList();

            if (prescriptionsByClinic.isNotEmpty) {
              patientPrescriptionOrdersByClinic[patientPrescriptionOrdersByClinic.indexOf(prescriptionsByClinic[0])].prescriptionsList!.add(element);
            } else {
              patientPrescriptionOrdersByClinic.add(PrescriptionsList(filterName: element.clinicDescription, prescriptions: element));
            }

            List<PrescriptionsList> prescriptionsByHospital = patientPrescriptionOrdersByHospital.where((elementClinic) => elementClinic.filterName == element.name).toList();

            if (prescriptionsByHospital.isNotEmpty) {
              patientPrescriptionOrdersByHospital[patientPrescriptionOrdersByHospital.indexOf(prescriptionsByHospital[0])].prescriptionsList!.add(element);
            } else {
              patientPrescriptionOrdersByHospital.add(PrescriptionsList(filterName: element.name, prescriptions: element));
            }
          }
          patientPrescriptionOrdersViewList = patientPrescriptionOrdersByClinic;
          isPrescriptionsDataNeedsReloading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPrescriptionDetails(PatientPrescriptionsResponseModel prescriptionsResponseModel, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await prescriptionsRepo.getPatientPrescriptionDetails(prescriptionsResponseModel: prescriptionsResponseModel);

    result.fold(
      // (failure) async => await errorHandlerService.handleError(failure: failure),
      (failure) async {
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) async {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          prescriptionDetailsList = apiResponse.data!;

          // Always load reminder status from SharedPreferences first
          final savedReminders = await PrescriptionReminderPrefsService.instance.getAllReminders();
          for (int i = 0; i < prescriptionDetailsList.length; i++) {
            final item = prescriptionDetailsList[i];
            if (item.appointmentNo != null && item.itemID != null && item.projectID != null) {
              final key = '${item.appointmentNo}_${item.itemID}_${item.projectID}';
              try {
                final saved = savedReminders.firstWhere((e) => e.uniqueKey == key);
                prescriptionDetailsList[i].hasReminder = saved.hasReminder;
              } catch (_) {
                // No entry found — keep default false
              }
            }
          }

          // If calendar permissions are granted, verify against actual calendar events
          if (await Permission.calendarFullAccess.isGranted && await Permission.calendarWriteOnly.isGranted) {
            prescriptionDetailsList.forEach((element) async {
              await checkIfReminderExistForPrescription(prescriptionDetailsList.indexOf(element));
            });
          }
          isPrescriptionsDetailsLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPrescriptionInstructionsPDF(PatientPrescriptionsResponseModel prescriptionsResponseModel, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await prescriptionsRepo.getPrescriptionInstructionsPDF(prescriptionsResponseModel: prescriptionsResponseModel);

    result.fold(
      (failure) async {
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          if (onError != null) {
            onError(apiResponse.errorMessage ?? "An error occurred while fetching the prescription instructions PDF.");
          }
          // onError!(apiResponse.errorMessage!);
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          prescriptionInstructionsPDFLink = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPrescriptionPDFBase64(PatientPrescriptionsResponseModel prescriptionsResponseModel, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await prescriptionsRepo.getPrescriptionPDF(prescriptionsResponseModel: prescriptionsResponseModel, prescriptionDetailsList: prescriptionDetailsList);

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          onError!(apiResponse.errorMessage!);
        } else if (apiResponse.messageStatus == 1) {
          prescriptionPDFBase64Data = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  showError(String errorMessage) {
    getIt<NavigationService>().pop();
    Future.delayed(Duration(milliseconds: 500), (){
      getIt<DialogService>().showErrorBottomSheet(message: errorMessage);
    });

  }

  Future<void> submitPrescriptionDeliveryRequest(
      {required String latitude,
      required String longitude,
      required String appointmentNo,
      required String dischargeID,
      required String projectID,
      Function(dynamic)? onSuccess,
      Function(String)? onError}) async {
    final result = await prescriptionsRepo.submitPrescriptionDeliveryRequest(latitude: latitude, longitude: longitude, appointmentNo: appointmentNo, dischargeID: dischargeID, projectID: projectID);

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          onError!(apiResponse.errorMessage!);
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  void initiatePrescriptionDelivery(BuildContext context) async {
    context.read<LocationViewModel>().placeValueInController();

    getIt.get<LocationUtils>().getLocation(
        isShowConfirmDialog: true,
        onSuccess: (position) async {
          bool result = await navServices.push(
            CustomPageRoute(
                page: MapUtilityScreen(
                  confirmButtonString: LocaleKeys.next.tr(),
                  titleString: LocaleKeys.selectLocation.tr(),
                  subTitleString: LocaleKeys.selectLocationPrescriptionDelivery.tr(),
                  isGmsAvailable: getIt.get<AppState>().isGMSAvailable,
                ),
                direction: AxisDirection.down),
          ) ?? false;
          print("Location Selected: $result");
          if (result) {
            LocationViewModel locationViewModel = getIt.get<LocationViewModel>();
            locationGeocodeResponse = locationViewModel.geocodeResponse!;
            navServices.push(
              CustomPageRoute(
                page: PrescriptionDeliveryOrderSummaryPage(),
              ),
            );
          }
        });
  }

  Future<void> getPrescriptionOrdersList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    isPrescriptionsDeliveryOrdersLoading = true;
    prescriptionsOrderList.clear();
    notifyListeners();

    final result = await prescriptionsRepo.getPrescriptionOrdersList();

    result.fold(
      (failure) async {
        isPrescriptionsDeliveryOrdersLoading = false;
        prescriptionsOrderList.clear();
        notifyListeners();
        if(onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          isPrescriptionsDeliveryOrdersLoading = false;
          notifyListeners();
          onError!(apiResponse.errorMessage!);
        } else if (apiResponse.messageStatus == 1) {
          isPrescriptionsDeliveryOrdersLoading = false;
          prescriptionsOrderList = apiResponse.data!;

          // Sort by created date (newest first)
          prescriptionsOrderList.sort((a, b) {
            try {
              if (a.created == null && b.created == null) return 0;
              if (a.created == null) return 1;
              if (b.created == null) return -1;

              DateTime dateA = DateTime.parse(a.created!);
              DateTime dateB = DateTime.parse(b.created!);
              return dateB.compareTo(dateA); // Descending order (newest first)
            } catch (e) {
              print('Error parsing date for sorting: $e');
              return 0;
            }
          });

          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  void serSelectedTime(DateTime dateTime) {
    selectedReminderTime = dateTime;
    notifyListeners();
  }

  void setIsPrescriptionAIAnalysisNeedsToBeShown(bool value) {
    isPrescriptionAIAnalysisNeedsToBeShown = value;
  }

  Future<void> getPrescriptionAiAnalysis({
    required List<PrescriptionDetailResponseModel> prescriptions,
    required int langId,
    required String loadingText,
    required Function(dynamic) onNavigate,
  }) async {
    LoaderBottomSheet.showLoader(
      loadingText: loadingText,
      showCloseButton: true,
      onCloseTap: () {
        setIsPrescriptionAIAnalysisNeedsToBeShown(false);
      },
    );

    // Prepare medicines payload
    List<Map<String, dynamic>> medicines = [];
    for (var prescription in prescriptions) {
      if (prescription.itemDescription != null && prescription.itemDescription!.isNotEmpty) {
        medicines.add({
          "name": prescription.itemDescription ?? "",
          "frequency": prescription.frequency ?? "",
          "duration": "${prescription.days ?? 0} Days",
        });
      }
    }

    final result = await prescriptionsRepo.getPrescriptionAiAnalysis(
      payload: medicines,
      langId: langId,
    );

    result.fold(
      (failure) async {
        LoaderBottomSheet.hideLoader();
        if (isPrescriptionAIAnalysisNeedsToBeShown) {
          await errorHandlerService.handleError(failure: failure);
        }
      },
      (apiResponse) {
        LoaderBottomSheet.hideLoader();
        if (apiResponse.messageStatus == 2) {
          // Error handling
        } else if (apiResponse.messageStatus == 1) {
          if (isPrescriptionAIAnalysisNeedsToBeShown) {
            prescriptionAnalysisResponse = apiResponse.data;
            onNavigate(apiResponse.data);
          }
        }
      },
    );
  }
}
