import 'dart:io';
import 'dart:ui';

import 'package:easy_localization/easy_localization.dart';
import 'package:geolocator/geolocator.dart';
import 'package:gms_check/gms_check.dart';
import 'package:google_maps_flutter/google_maps_flutter.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/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:huawei_location/huawei_location.dart' as HmsLocation
    show FusedLocationProviderClient, Location, LocationSettingsRequest, LocationRequest;
import 'package:location/location.dart' show Location;
import 'package:permission_handler/permission_handler.dart' show Permission, PermissionListActions, PermissionStatusGetters, openAppSettings;

class LocationUtils {
  NavigationService navigationService;
  AppState appState;

  bool isShowConfirmDialog;
  bool isShowLocationTimeoutDialog;
  bool isHuawei;
  final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;
  Future<bool?>? isGMSDevice;

  LocationUtils({
    required this.isShowConfirmDialog,
    required this.navigationService,
    required this.appState,
    this.isHuawei = false,
    this.isShowLocationTimeoutDialog = true,
  }) {
    isGMSDevice = GmsCheck().checkGmsAvailability();
  }

  // final defaultCallbackForLocationDenied = (){
  //   showCommonBottomSheetWithoutHeight(
  //     title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
  //     navigationService.navigatorKey.currentContext!,
  //     child: Utils.getWarningWidget(
  //         loadingText:
  //         "Please grant location permission from app settings to see better results"
  //             .needTranslation,
  //         isShowActionButtons: true,
  //         onCancelTap: () {
  //           navigationService.pop();
  //         },
  //         onConfirmTap: () async {
  //           navigationService.pop();
  //           openAppSettings();
  //         }),
  //     callBackFunc: () {},
  //     isFullScreen: false,
  //     isCloseButtonVisible: true,
  //   );
  // }

  void getLocation(
      {Function(LatLng)? onSuccess, VoidCallback? onFailure, bool isShowConfirmDialog = false, VoidCallback? onLocationDeniedForever}) async {
    this.isShowConfirmDialog = isShowConfirmDialog;
    if (Platform.isIOS) {
      getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess, onLocationDeniedForever: onLocationDeniedForever);
      return;
    }

    if (await isGMSDevice ?? true) {
      getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess, onLocationDeniedForever: onLocationDeniedForever);
      return;
    }

    getHMSLocation(onFailure: onFailure, onSuccess: onSuccess, onLocationDeniedForever: onLocationDeniedForever);
  }

  void getCurrentLocation({Function(LatLng)? onSuccess, VoidCallback? onFailure, VoidCallback? onLocationDeniedForever}) async {
    var location = Location();

    bool isLocationEnabled = await location.serviceEnabled();
    //if the location service is not enabled, ask the user to enable it
    if (!isLocationEnabled) {
      isLocationEnabled = await location.requestService();
      if (!isLocationEnabled) {
        appState.resetLocation();
        onFailure?.call();
        return;
      }
    }

    LocationPermission permissionGranted =  await Geolocator.checkPermission();
    if (permissionGranted == LocationPermission.denied) {
      permissionGranted = await Geolocator.requestPermission();
      if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
        appState.resetLocation();
        if (onFailure == null && isShowConfirmDialog) {
          showCommonBottomSheetWithoutHeight(
            title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
            navigationService.navigatorKey.currentContext!,
            child: Utils.getWarningWidget(
                loadingText: LocaleKeys.grantLocationPermission.tr(),
                isShowActionButtons: true,
                onCancelTap: () {
                  navigationService.pop();
                },
                onConfirmTap: () async {
                  navigationService.pop();
                  openAppSettings();
                }),
            callBackFunc: () {},
            isFullScreen: false,
            isCloseButtonVisible: true,
          );
        } else {
          onFailure?.call();
        }
        return;
      }
    } else if (permissionGranted == LocationPermission.deniedForever) {
      appState.resetLocation();
      if (onLocationDeniedForever == null && isShowConfirmDialog) {
        showCommonBottomSheetWithoutHeight(
          title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
          navigationService.navigatorKey.currentContext!,
          child: Utils.getWarningWidget(
              loadingText: LocaleKeys.grantLocationPermission.tr(),
              isShowActionButtons: true,
              onCancelTap: () {
                navigationService.pop();
              },
              onConfirmTap: () async {
                navigationService.pop();
                openAppSettings();
              }),
          callBackFunc: () {},
          isFullScreen: false,
          isCloseButtonVisible: true,
        );
      }
      onLocationDeniedForever?.call();
      return;
    }

    Position? currentLocation = await Geolocator.getLastKnownPosition();

    if (currentLocation?.latitude == null || currentLocation?.longitude == null) {
      currentLocation = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
    }

    LatLng locationData = LatLng(currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0);
    saveLatLngToAppState(locationData);
    onSuccess?.call(locationData);
  }

  Future<bool> checkIfGPSIsEnabled() async {
    return await Geolocator.isLocationServiceEnabled();
  }

  Future<bool> _handlePermission() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await _geolocatorPlatform.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return false;
    }

    permission = await _geolocatorPlatform.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await _geolocatorPlatform.requestPermission();
      if (permission == LocationPermission.denied) {
        return false;
      }
    }

    if (permission == LocationPermission.deniedForever) {
      return false;
    }
    return true;
  }

  // showLocationTimeOutDialog({Function()? failureCallBack}) {
  //   ConfirmDialog dialog = new ConfirmDialog(
  //       context: context,
  //       confirmMessage: TranslationBase.of(context).locationTimeoutError,
  //       okText: TranslationBase.of(context).ok,
  //       cancelText: TranslationBase.of(context).cancel_nocaps,
  //       okFunction: () {
  //         ConfirmDialog.closeAlertDialog(context);
  //         Navigator.of(context).canPop();
  //         if (failureCallBack != null) {
  //           failureCallBack();
  //         }
  //       },
  //       cancelFunction: () {
  //         if (failureCallBack != null) {
  //           failureCallBack();
  //         }
  //       });
  //   return dialog.showAlertDialog(context);
  // }

  showErrorLocationDialog(bool isPermissionError, {Function()? failureCallBack}) {
    setLocation(null);
    // ConfirmDialog dialog = new ConfirmDialog(
    //     context: context,
    //     confirmMessage: TranslationBase.of(context).locationDialogMessage,
    //     okText: TranslationBase.of(context).confirm,
    //     cancelText: TranslationBase.of(context).cancel_nocaps,
    //     okFunction: () {
    //       ConfirmDialog.closeAlertDialog(context);
    //       if (isPermissionError)
    //         Geolocator.openAppSettings();
    //       else
    //         Geolocator.openLocationSettings();
    //       Navigator.of(context).canPop();
    //       if (failureCallBack != null) {
    //         failureCallBack();
    //       }
    //     },
    //     cancelFunction: () {
    //       if (failureCallBack != null) {
    //         failureCallBack();
    //       }
    //     });
    // return dialog.showAlertDialog(context);
  }

  void setLocation(Position? position) {
    Utils.saveNumFromPrefs(CacheConst.userLat, position?.latitude ?? 0.0);
    Utils.saveNumFromPrefs(CacheConst.userLong, position?.longitude ?? 0.0);

    appState.setUserLat = position?.latitude ?? 0.0;
    appState.setUserLong = position?.longitude ?? 0.0;

    // projectViewModel.setLatitudeLongitude(position?.latitude ?? 0.0, position?.longitude ?? 0.0);
  }

  void setZeroLocation() {
    Utils.saveNumFromPrefs(CacheConst.userLat, 0.0);
    Utils.saveNumFromPrefs(CacheConst.userLong, 0.0);

    appState.setUserLat = 0.0;
    appState.setUserLong = 0.0;
  }

  Future<bool> requestPermissions() async {
    var result = await [
      Permission.location,
    ].request();
    return (result[Permission.location]!.isGranted || result[Permission.locationAlways]!.isGranted);
  }

  void saveLatLngToAppState(LatLng locationData) {
    appState.userLat = locationData.latitude;
    appState.userLong = locationData.longitude;
  }

  Future<bool> isLocationPermissionEnabled() async {
    if (Platform.isIOS || (await isGMSDevice ?? true)) {
      return await _isGMSLocationPermissionEnabled();
    } else {
      return await _isHMSLocationPermissionEnabled();
    }
  }

  Future<bool> _isGMSLocationPermissionEnabled() async {
    bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) return false;

    LocationPermission permission = await Geolocator.checkPermission();
    return permission == LocationPermission.whileInUse || permission == LocationPermission.always;
  }

  Future<bool> _isHMSLocationPermissionEnabled() async {
    bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) return false;

    LocationPermission permission = await Geolocator.checkPermission();
    return permission == LocationPermission.whileInUse || permission == LocationPermission.always;
  }

  void getHMSLocation({VoidCallback? onFailure, Function(LatLng p1)? onSuccess, VoidCallback? onLocationDeniedForever}) async {
    try {
      var location = Location();
      HmsLocation.FusedLocationProviderClient locationService = HmsLocation.FusedLocationProviderClient()..initFusedLocationService();

      bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
      //if the location service is not enabled, ask the user to enable it
      if (!isLocationEnabled) {
        HmsLocation.LocationRequest locationRequest = HmsLocation.LocationRequest()..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY;

        HmsLocation.LocationSettingsRequest request = HmsLocation.LocationSettingsRequest(
          alwaysShow: true,
          needBle: false,
          requests: [locationRequest],
        );

        await locationService.checkLocationSettings(request);
      }
      LocationPermission permissionGranted = await Geolocator.checkPermission();
      if (permissionGranted == LocationPermission.denied) {
        permissionGranted = await Geolocator.requestPermission();
        if (permissionGranted == LocationPermission.deniedForever) {
          appState.resetLocation();
          if (onLocationDeniedForever == null && isShowConfirmDialog) {
            showCommonBottomSheetWithoutHeight(
              title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
              navigationService.navigatorKey.currentContext!,
              child: Utils.getWarningWidget(
                  loadingText: LocaleKeys.grantLocationPermission.tr(),
                  isShowActionButtons: true,
                  onCancelTap: () {
                    navigationService.pop();
                  },
                  onConfirmTap: () async {
                    navigationService.pop();
                    openAppSettings();
                  }),
              callBackFunc: () {},
              isFullScreen: false,
              isCloseButtonVisible: true,
            );
          }
          onLocationDeniedForever?.call();
          return;
        } else if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
          appState.resetLocation();
          onFailure?.call();
          return;
        }
      }

      HmsLocation.Location data = await locationService.getLastLocation();
      if (data.latitude == null || data.longitude == null) {
        appState.resetLocation();
        HmsLocation.LocationRequest request = HmsLocation.LocationRequest()
          ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY
          ..interval = 1000 // 1 second
          ..numUpdates = 1;
        locationService.requestLocationUpdates(request);
        locationService.onLocationData?.listen((location) {
          data = location;
          if (data.latitude == null || data.longitude == null) {
            appState.resetLocation();
            onFailure?.call();
            return;
          }
          var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);
          saveLatLngToAppState(locationData);
          onSuccess?.call(locationData);
        });
      } else {
        var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);

        saveLatLngToAppState(locationData);
        onSuccess?.call(locationData);
      }
    } catch (e) {
      appState.resetLocation();
      onFailure?.call();
    }
  }



 void  onFailureDilouge(){
    return  showCommonBottomSheetWithoutHeight(
      title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
      navigationService.navigatorKey.currentContext!,
      child: Utils.getWarningWidget(
          loadingText: LocaleKeys.grantLocationPermission.tr(),
          isShowActionButtons: true,
          onCancelTap: () {
            navigationService.pop();
          },
          onConfirmTap: () async {
            navigationService.pop();
            openAppSettings();
          }),
      callBackFunc: () {},
      isFullScreen: false,
      isCloseButtonVisible: true,
    );
  }
}
