import 'dart:async';

import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_repo.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';

import '../../services/navigation_service.dart';

class ImmediateLiveCareViewModel extends ChangeNotifier {
  ImmediateLiveCareViewModel({
    required this.immediateLiveCareRepo,
    required this.errorHandlerService,
    required this.navigationService,
    required this.myAppointmentsViewModel,
  });

  ImmediateLiveCareRepo immediateLiveCareRepo;
  ErrorHandlerService errorHandlerService;
  final NavigationService navigationService;
  MyAppointmentsViewModel myAppointmentsViewModel;

  List<GetLiveCareClinicListResponseModel> immediateLiveCareClinicsList = [];
  List<GetLiveCareClinicListResponseModel> mainLiveCareClinicList = [];
  bool isImmediateLiveCareClinicsLoading = false;
  int liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
  late GetLiveCareClinicListResponseModel immediateLiveCareSelectedClinic;
  late LiveCareImmediateAppointmentFeesList liveCareImmediateAppointmentFeesList;

  List<PatientLiveCareHistory> patientLiveCareHistoryList = [];
  bool patientHasPendingLiveCareRequest = false;

  List<LiveCareClinicScheduleResponse> liveCareClinicScheduleList = [];

  late AppState _appState;

  Duration countdownDuration = Duration(minutes: 1, seconds: 0);
  ValueNotifier<Duration> durationNotifier = ValueNotifier<Duration>(Duration(minutes: 1, seconds: 0));
  Timer? timer;

  bool isShowNotEligibleDialog = false;
  String notEligibleErrorMsg = "";

  initImmediateLiveCare() {
    _appState = getIt<AppState>();
    immediateLiveCareClinicsList = [];
    mainLiveCareClinicList = [];
    isImmediateLiveCareClinicsLoading = true;
    liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
    immediateLiveCareSelectedClinic = GetLiveCareClinicListResponseModel();
    liveCareImmediateAppointmentFeesList = LiveCareImmediateAppointmentFeesList();
  }

  setLiveCareSelectedCallType(int value) {
    liveCareSelectedCallType = value;
    notifyListeners();
  }

  setImmediateLiveCareSelectedClinic(GetLiveCareClinicListResponseModel clinic) {
    immediateLiveCareSelectedClinic = clinic;
    notifyListeners();
  }

  Future<void> getLiveCareImmediateClinicsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    immediateLiveCareClinicsList.clear();
    isImmediateLiveCareClinicsLoading = true;
    notifyListeners();

    final result = await immediateLiveCareRepo.getLiveCareImmediateClinicsList(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!);

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

          mainLiveCareClinicList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));
          immediateLiveCareClinicsList.clear();
          immediateLiveCareClinicsList.addAll(mainLiveCareClinicList);

          isImmediateLiveCareClinicsLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }
  void filterClinic(String query){
    if(query.isEmpty){
      immediateLiveCareClinicsList.clear();
      immediateLiveCareClinicsList.addAll(mainLiveCareClinicList);
    }else{

      // bool isArabic = getIt.get<AppState>().isArabic();
      immediateLiveCareClinicsList = mainLiveCareClinicList.where((clinic) => clinic.serviceName!.toLowerCase().contains(query.toLowerCase()) || clinic.serviceNameN!.toLowerCase().contains(query.toLowerCase()
      )).toList();
    }
    notifyListeners();
  }

  Future<void> getLiveCareImmediateAppointmentFees({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await immediateLiveCareRepo.getLiveCareImmediateAppointmentFees(
        _appState.getAuthenticatedUser()!.age ?? 22, _appState.getAuthenticatedUser()!.gender ?? 1, immediateLiveCareSelectedClinic.serviceID ?? 1);

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          onError!(apiResponse.errorMessage ?? "Unknown error occurred");
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          liveCareImmediateAppointmentFeesList = apiResponse.data!;

          if ((liveCareImmediateAppointmentFeesList.isCash!)) {
            isShowNotEligibleDialog = false;
          } else {
            if (liveCareImmediateAppointmentFeesList.isInsured! && liveCareImmediateAppointmentFeesList.isEligible!) {
              isShowNotEligibleDialog = false;
            } else {
              if (liveCareImmediateAppointmentFeesList.isInsured! && liveCareImmediateAppointmentFeesList.isEligible!) {
                isShowNotEligibleDialog = true;
                notEligibleErrorMsg = LocaleKeys.invalidEligibility.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!);
              } else {
                isShowNotEligibleDialog = true;
                notEligibleErrorMsg = LocaleKeys.invalidInsurance.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!);
              }
            }
          }

          if (isShowNotEligibleDialog) {
            LoaderBottomSheet.hideLoader();
            showCommonBottomSheetWithoutHeight(GetIt.instance<NavigationService>().navigatorKey.currentContext!,
                child: Padding(
                  padding: EdgeInsets.only(
                    left: 24.w,
                    top: 24.h,
                    right: 24.w,
                    bottom: 12.h,
                  ),
                  child: Utils.getWarningWidget(
                      loadingText: notEligibleErrorMsg,
                      confirmText: LocaleKeys.updateInsuranceInfo.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
                      cancelText: LocaleKeys.continueCash.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
                      isShowActionButtons: true,
                      onCancelTap: () {
                        Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
                        LoaderBottomSheet.showLoader();
                        myAppointmentsViewModel.convertPatientToCash(
                            projectID: ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat ? 15 : 12,
                            onSuccess: (val) {
                              LoaderBottomSheet.hideLoader();
                              LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingFeesPleaseWait.tr());
                              getLiveCareImmediateAppointmentFees();
                            },
                            onError: (err) {
                              LoaderBottomSheet.hideLoader();
                              showCommonBottomSheetWithoutHeight(
                                title: LocaleKeys.notice.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
                                GetIt.instance<NavigationService>().navigatorKey.currentContext!,
                                child: Utils.getErrorWidget(loadingText: err.toString()),
                                callBackFunc: () {
                                  Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
                                  Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
                                },
                                isFullScreen: false,
                                isCloseButtonVisible: true,
                              );
                            });
                      },
                      onConfirmTap: () async {
                        Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);

                        //Call the API to attempt updating patient insurance
                        LoaderBottomSheet.showLoader();
                        myAppointmentsViewModel.sendPatientUpdateRequest(onSuccess: (val) {
                          LoaderBottomSheet.hideLoader();
                          getLiveCareImmediateAppointmentFees();
                        }, onError: (err) {
                          LoaderBottomSheet.hideLoader();
                          Navigator.push(
                            GetIt.instance<NavigationService>().navigatorKey.currentContext!,
                            CustomPageRoute(
                              page: InsuranceHomePage(),
                            ),
                          );
                        });
                      }),
                ), callBackFunc: () {
              // Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
            }, isFullScreen: false, isCloseButtonVisible: false, isDismissible: false);
          }

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

  Future<void> addNewCallRequestForImmediateLiveCare(String transID, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await immediateLiveCareRepo.addNewCallRequestForImmediateLiveCare(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!,
        immediateLiveCareSelectedClinic.serviceID!, transID, liveCareSelectedCallType, false, _appState.deviceToken, await Utils.getStringFromPrefs(CacheConst.voipToken));

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          onError!(apiResponse.errorMessage ?? "Unknown error occurred");
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> addInsuranceUpdateRequestForLiveCare({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await immediateLiveCareRepo.addInsuranceUpdateRequestForLiveCare("${_appState.getAuthenticatedUser()?.firstName ?? ''} ${_appState.getAuthenticatedUser()?.lastName ?? ''}",
        _appState.getAuthenticatedUser()!.mobileNumber ?? "", _appState.getAuthenticatedUser()!.patientId.toString() ?? "");

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          onError!(apiResponse.errorMessage ?? "Unknown error occurred");
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPatientLiveCareHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    patientLiveCareHistoryList = [];
    patientHasPendingLiveCareRequest = false;
    timer?.cancel();
    notifyListeners();

    final result = await immediateLiveCareRepo.getPatientLiveCareHistory();

    result.fold(
      (failure) async {
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          if (onError != null) {
            onError(apiResponse.errorMessage ?? "Unknown error occurred");
          }
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientLiveCareHistoryList = apiResponse.data!;
          if (patientLiveCareHistoryList.isNotEmpty) {
            if (patientLiveCareHistoryList[0].callStatus! < 4) {
              patientHasPendingLiveCareRequest = true;
              countdownDuration = Duration(minutes: patientLiveCareHistoryList.first.watingtimeInteger!, seconds: 0);
              durationNotifier.value = countdownDuration;
              // Start timer if not already running
              if (timer == null || !timer!.isActive) {
                startTimer();
              }
            } else {
              patientHasPendingLiveCareRequest = false;
              stopTimer(); // Stop timer if call status >= 4
            }
          } else {
            patientHasPendingLiveCareRequest = false;
            stopTimer(); // Stop timer if no history
          }
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getLiveCareImmediateClinicSchedule({int? serviceID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    liveCareClinicScheduleList.clear();
    notifyListeners();

    final result =
        await immediateLiveCareRepo.getLiveCareImmediateClinicSchedule(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, serviceID!);

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

          // immediateLiveCareClinicsList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));

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

  void startTimer() {
    // Only start timer if it's not already active
    if (timer == null || !timer!.isActive) {
      timer = Timer.periodic(const Duration(seconds: 1), (_) {
        addTime();
      });
    }
  }

  void addTime() {
    final currentSeconds = durationNotifier.value.inSeconds;

    if (currentSeconds <= 0) {
      // Timer has reached zero, stop it
      timer?.cancel();
      durationNotifier.value = Duration.zero;
    } else {
      // Decrease by 1 second and continue
      durationNotifier.value = Duration(seconds: currentSeconds - 1);
    }
  }

  void stopTimer() {
    timer?.cancel();
  }

  @override
  void dispose() {
    timer?.cancel();
    durationNotifier.dispose();
    super.dispose();
  }
}
