// import 'dart:async';
// import 'dart:io';
// import 'dart:ui' as ui;
//
// import 'package:flutter/cupertino.dart';
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'package:generp/Notifiers/HomeScreenNotifier.dart';
// import 'package:generp/screens/crm/LeadDetailsByMode.dart';
// import 'package:generp/screens/genTracker/GeneratorDetails.dart';
// import 'package:generp/services/api_calling.dart';
// import 'package:geolocator/geolocator.dart';
// import 'package:google_maps_flutter/google_maps_flutter.dart';
// import 'package:image_picker/image_picker.dart';
// import 'package:geocoding/geocoding.dart' as geocoding;
// import 'package:location/location.dart' as Location;
// import 'package:permission_handler/permission_handler.dart';
// import 'package:provider/provider.dart';
//
// import '../../Models/crmModels/NearbyOpenLeadsResponse.dart';
// import '../../Utils/commonServices.dart';
//
// class crmNearbyOpenLeadsProvider extends ChangeNotifier {
//
//
//   List<LeadList> _leadslist = [];
//   TextEditingController _locationController = TextEditingController();
//   String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
//   GoogleMapController? _mapController;
//   CameraPosition? _cameraPosition;
//   LatLng _startLocation = const LatLng(17.439112226708446, 78.43292499146135);
//   String _latlongs = "";
//   List<Marker> _markers = [];
//   List<String> _addresses = [];
//   Location.LocationData? _currentLocation;
//   bool _isLocationEnabled = false;
//   bool _hasLocationPermission = false;
//   Timer? _timer;
//   File? _image;
//   bool _isLoading = true;
//   double _currentValue = 1.0;
//   Timer? _debounceTimer;
//
//
//   List<LeadList> get leadsList => _leadslist;
//   TextEditingController get LocationController => _locationController;
//   String get googleAPIKey => _googleApikey;
//   GoogleMapController? get mapController => _mapController;
//   CameraPosition? get cameraPosition => _cameraPosition;
//   LatLng get startLocation => _startLocation;
//   String get latlongs => _latlongs;
//   List<Marker> get markers => _markers;
//   List<String> get addresses => _addresses;
//   Location.LocationData? get currentLocation => _currentLocation;
//   bool get isLocationEnabled => _isLocationEnabled;
//   bool get hasLocationPermission => _hasLocationPermission;
//   bool get isLoading => _isLoading;
//   Timer? get timer => _timer;
//   File? get image => _image;
//   double get currentValue => _currentValue;
//
//   set currentValue(value){
//     _currentValue = value;
//     notifyListeners();
//   }
//
//
//   set markers(List<Marker> value){
//     _markers = value;
//     notifyListeners();
//   }
//   set mapController(value){
//     _mapController = value;
//     notifyListeners();
//   }
//
//   void resetAll(){
//     _currentValue = 1.0;
//     _markers= [];
//     _addresses = [];
//   }
//
//   Future<void> getLocationPermission(context) async {
//     // Check if location services are enabled
//     _isLocationEnabled = await Geolocator.isLocationServiceEnabled();
//
//     // Check if the app has been granted location permission
//     LocationPermission permission = await Geolocator.checkPermission();
//     _hasLocationPermission =
//         permission == LocationPermission.always ||
//             permission == LocationPermission.whileInUse;
//
//     final Location.Location location = Location.Location();
//     bool serviceEnabled;
//     Location.PermissionStatus permissionGranted;
//     serviceEnabled = await location.serviceEnabled();
//     if (!serviceEnabled) {
//       serviceEnabled = await location.requestService();
//       if (!serviceEnabled) {
//         return;
//       }
//     }
//     _isLoading = false;
//     permissionGranted = (await location.hasPermission());
//     if (permissionGranted == PermissionStatus) {
//       permissionGranted = (await location.requestPermission());
//       if (permissionGranted != PermissionStatus) {
//         return;
//       }
//     }
//     final Location.LocationData locData = await location.getLocation();
//
//     _currentLocation = locData;
//
//     if (_currentLocation != null) {
//       _mapController?.animateCamera(
//         CameraUpdate.newLatLng(
//           LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
//         ),
//       );
//       final lat = _currentLocation!.latitude;
//       final lang = _currentLocation!.longitude!;
//       _latlongs = '$lat,$lang';
//       LoadNearbyOpenLeadsAPI(context,_currentValue);
//     }
//   }
//
//   void onCameraMove(context, CameraPosition position) {
//     _timer?.cancel(); // Cancel any previous timer
//     _timer = Timer(Duration(seconds: 1), () {
//       getLocationPermission(context);
//     });
//   }
//   void debounce(VoidCallback callback, Duration duration) {
//     _debounceTimer?.cancel();
//     _debounceTimer = Timer(duration, callback);
//   }
//
//
//   Future<void> LoadNearbyOpenLeadsAPI(BuildContext context,radius) async {
//     if (_latlongs.isEmpty || _currentValue <= 0) {
//       print("Invalid parameters: latlongs=$_latlongs, currentValue=$_currentValue");
//       return;
//     }
//     try {
//       var provider = Provider.of<HomescreenNotifier>(context, listen: false);
//       final data = await ApiCalling.loadNearbyOpenLeadsAPI(
//         provider.empId,
//         provider.session,
//         _latlongs,
//           radius
//       );
//
//       if (data != null) {
//           if (data.error == 0) {
//             _leadslist = data.leadList!;
//
//             await updateMarkersFromApiResponse(context, data.leadList!);
//             _isLoading = false;
//             notifyListeners();
//           } else if(data.error==1){
//             toast(context, data.message);
//           }
//
//       } else {
//         toast(context, "Something went wrong, Please try again.");
//       }
//     } on Exception catch (e) {
//       print("$e");
//     }
//   }
//
//   Future<void> updateMarkersFromApiResponse(
//       BuildContext context,
//       List<LeadList> leadsList,
//       ) async {
//     _markers = await createMarkersFromApiResponse(context, leadsList);
//     _addresses.clear();
//     await Future.forEach(leadsList, (store) async {
//       String address = await _getAddressFromLatLng(store.loc);
//       _addresses.add(address);
//
//     });
//     notifyListeners();
//     // for (int i = 0; i < _addresses.length; i++) {
//     //   //print('List of Addresses:' "${addresses[i]}");
//     //   // print('List of Addresses:' "${addresses[1]}" );
//     // }
//   }
//
//   Future<List<Marker>> createMarkersFromApiResponse(
//       BuildContext context,
//       List<LeadList> leadsList,
//       ) async {
//     List<Marker> markers = [];
//
//     // print("Hello Nutsby!");
//     ByteData data = await rootBundle.load("assets/images/leads_ic.png");
//     Uint8List bytes = data.buffer.asUint8List();
//
//     await Future.forEach(leadsList, (leads) async {
//       ui.Codec codec = await ui.instantiateImageCodec(
//         bytes,
//       );
//       ui.FrameInfo fi = await codec.getNextFrame();
//       Uint8List resizedBytes =
//       (await fi.image.toByteData(
//         format: ui.ImageByteFormat.png,
//       ))!.buffer.asUint8List();
//
//       markers.add(
//         Marker(
//           markerId: MarkerId(leads.id.toString()),
//
//           position: _parseLatLng(leads.loc),
//           icon: BitmapDescriptor.fromBytes(resizedBytes),
//           infoWindow: InfoWindow(
//
//             onTap:() {
//               // onMarkerTap(context, leads.id);
//               Navigator.push(
//                 context, // Use the widget's BuildContext, which is valid here
//                 MaterialPageRoute(
//                   builder: (context) => LeadDetailsByMode(
//                     mode: "",
//                     pageTitleName: "Lead Details",
//                     leadId:leads.id ,
//
//                   ),
//                 ),
//               );
//             },
//             anchor: Offset(0, 0),
//             title: "${leads.name}",
//             snippet: "${leads.address}",
//
//           ),
//           zIndex: 100,
//
//           onTap: () {
//             int index = leadsList.indexWhere(
//                   (techResponse) =>
//               techResponse.id == leads.id,
//             );
//             // onMarkerTap(
//             //   context,
//             //   leads.id,
//             // );
//             // print("index:${index}");
//             //   Navigator.push(
//             //     context,
//             //     MaterialPageRoute(
//             //       builder:
//             //           (context) => Generatordetails(
//             //             activityName: "NearByGenerators",
//             //             genLocation: generator.loc,
//             //             generatorId: generator.generatorId,
//             //           ),
//             //     ),
//             //   );
//
//           },
//         ),
//       );
//     });
//     return markers;
//   }
//   Future<void> onMarkerTap(context, leadID) async {
// ///uncomment with screen navigation
//     Navigator.push(
//       context, // Use the widget's BuildContext, which is valid here
//       MaterialPageRoute(
//         builder: (context) => LeadDetailsByMode(
//           mode: "",
//           pageTitleName: "Lead Details",
//           leadId:leadID ,
//
//         ),
//       ),
//     );
//
//     _markers = markers;
//     notifyListeners();
//
//   }
//
//   LatLng _parseLatLng(String? location) {
//     if (location != null) {
//       List<String> parts = location.split(',');
//       if (parts.length == 2) {
//         double lat = double.tryParse(parts[0]) ?? 0.0;
//         double lng = double.tryParse(parts[1]) ?? 0.0;
//         return LatLng(lat, lng);
//       }
//     }
//     return const LatLng(0.0, 0.0);
//   }
//
//   Future<String> _getAddressFromLatLng(String? location) async {
//     if (location != null) {
//       List<String> parts = location.split(',');
//       if (parts.length == 2) {
//         double lat = double.tryParse(parts[0]) ?? 0.0;
//         double lng = double.tryParse(parts[1]) ?? 0.0;
//
//         List<geocoding.Placemark> placemarks = await geocoding
//             .placemarkFromCoordinates(lat, lng);
//
//         if (placemarks.isNotEmpty) {
//           final placemark = placemarks.first;
//           String address =
//               '${placemark.street ?? ''}, '
//               '${placemark.thoroughfare ?? ''} '
//           // '${placemark.subThoroughfare ?? ''}, '
//           // '${placemark.name ?? ''}, '
//               '${placemark.subLocality ?? ''}, '
//               '${placemark.locality ?? ''}, '
//               '${placemark.administrativeArea ?? ''}, '
//               '${placemark.subAdministrativeArea ?? ''} '
//               '${placemark.postalCode ?? ''}, '
//               '${placemark.country ?? ''}';
//           return address.trim();
//         }
//       }
//     }
//     return "Address not found";
//   }
//
// }
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/screens/crm/LeadDetailsByMode.dart';
import 'package:generp/services/api_calling.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:image_picker/image_picker.dart';
import 'package:geocoding/geocoding.dart' as geocoding;
import 'package:location/location.dart' as Location;
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';

import '../../Models/crmModels/NearbyOpenLeadsResponse.dart';
import '../../Utils/commonServices.dart';

class crmNearbyOpenLeadsProvider extends ChangeNotifier {
  List<LeadList> _leadslist = [];
  final TextEditingController _locationController = TextEditingController();
  final String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
  GoogleMapController? _mapController;
  CameraPosition? _cameraPosition;
  final LatLng _startLocation = const LatLng(
    17.439112226708446,
    78.43292499146135,
  );
  String _latlongs = "";
  List<Marker> _markers = [];
  List<String> _addresses = [];
  Location.LocationData? _currentLocation;
  bool _isLocationEnabled = false;
  bool _hasLocationPermission = false;
  Timer? _timer;
  File? _image;
  bool _isLoading = true;
  double _currentValue = 1.0;
  Timer? _debounceTimer;
  LatLng? _mapCenter;
  bool _isFilterApplied = false; // Track if filter has been applied

  List<LeadList> get leadsList => _leadslist;
  TextEditingController get LocationController => _locationController;
  String get googleAPIKey => _googleApikey;
  GoogleMapController? get mapController => _mapController;
  CameraPosition? get cameraPosition => _cameraPosition;
  LatLng get startLocation => _startLocation;
  String get latlongs => _latlongs;
  List<Marker> get markers => _markers;
  List<String> get addresses => _addresses;
  Location.LocationData? get currentLocation => _currentLocation;
  bool get isLocationEnabled => _isLocationEnabled;
  bool get hasLocationPermission => _hasLocationPermission;
  bool get isLoading => _isLoading;
  Timer? get timer => _timer;
  File? get image => _image;
  double get currentValue => _currentValue;
  bool get isFilterApplied => _isFilterApplied;

  set currentValue(double value) {
    _currentValue = value;
    notifyListeners();
  }

  set markers(List<Marker> value) {
    _markers = value;
    if (value.isNotEmpty) {
      _isLoading = false; // Mark screen as loaded when markers are added
    }
    notifyListeners();
  }

  set mapController(GoogleMapController? value) {
    _mapController = value;
    notifyListeners();
  }

  set mapCenter(LatLng? value) {
    _mapCenter = value;
    _latlongs = value != null ? '${value.latitude},${value.longitude}' : '';
    notifyListeners();
  }

  set isLoading(bool value) {
    _isLoading = value;
    notifyListeners();
  }

  void resetAll() {
    _currentValue = 1.0;
    _markers = [];
    _addresses = [];
    _mapCenter = null;
    _latlongs = '';
    _isFilterApplied = false;
    _isLoading = true;
    notifyListeners();
  }

  Future<void> getLocationPermission(BuildContext context) async {
    _isLocationEnabled = await Geolocator.isLocationServiceEnabled();
    LocationPermission permission = await Geolocator.checkPermission();
    _hasLocationPermission =
        permission == LocationPermission.always ||
        permission == LocationPermission.whileInUse;

    final Location.Location location = Location.Location();
    bool serviceEnabled;
    Location.PermissionStatus permissionGranted;
    serviceEnabled = await location.serviceEnabled();
    if (!serviceEnabled) {
      serviceEnabled = await location.requestService();
      if (!serviceEnabled) {
        toast(context, 'Location services are disabled.');
        _isLoading = false;
        return;
      }
    }
    permissionGranted = await location.hasPermission();
    if (permissionGranted == Location.PermissionStatus.denied) {
      permissionGranted = await location.requestPermission();
      if (permissionGranted != Location.PermissionStatus.granted) {
        toast(context, 'Location permission denied.');
        _isLoading = false;
        return;
      }
    }
    final Location.LocationData locData = await location.getLocation();

    _currentLocation = locData;

    if (_currentLocation != null && _mapCenter == null) {
      _mapCenter = LatLng(
        _currentLocation!.latitude!,
        _currentLocation!.longitude!,
      );
      _latlongs =
          '${_currentLocation!.latitude},${_currentLocation!.longitude}';
      _mapController?.animateCamera(CameraUpdate.newLatLng(_mapCenter!));
      await LoadNearbyOpenLeadsAPI(context, _currentValue);
    }
    notifyListeners();
  }

  void onCameraMove(BuildContext context, CameraPosition position) {
    _timer?.cancel();
    _mapCenter = position.target;
    _latlongs = '${_mapCenter!.latitude},${_mapCenter!.longitude}';
    _timer = Timer(Duration(seconds: 1), () {
      LoadNearbyOpenLeadsAPI(context, _currentValue);
    });
    notifyListeners();
  }

  void debounce(VoidCallback callback, Duration duration) {
    _debounceTimer?.cancel();
    _debounceTimer = Timer(duration, callback);
  }

  Future<void> applyFilter(BuildContext context, double radius) async {
    _isLoading = true;
    _isFilterApplied = true;
    notifyListeners();
    await LoadNearbyOpenLeadsAPI(context, radius);
  }

  Future<void> LoadNearbyOpenLeadsAPI(
    BuildContext context,
    double radius,
  ) async {
    if (_latlongs.isEmpty || radius <= 0) {
      print("Invalid parameters: latlongs=$_latlongs, radius=$radius");
      toast(context, 'Invalid location or radius.');
      _isLoading = false;
      notifyListeners();
      return;
    }
    try {
      var provider = Provider.of<HomescreenNotifier>(context, listen: false);
      final data = await ApiCalling.loadNearbyOpenLeadsAPI(
        provider.empId,
        provider.session,
        _latlongs,
        radius,
      );

      if (data != null) {
        if (data.error == 0) {
          _isLoading = false;
          _leadslist =
              data.leadList?.where((lead) => lead != null).toList() ?? [];
          await updateMarkersFromApiResponse(context, _leadslist);
          if (_leadslist.isEmpty) {
            toast(context, 'No leads found within the selected radius.');
          }
        } else {
          toast(context, data.message ?? 'Failed to load leads.');
          _isLoading = false;
          notifyListeners();
        }
      } else {
        toast(context, "Something went wrong, please try again.");
        _isLoading = false;
        notifyListeners();
      }
    } on Exception catch (e, s) {
      print("LoadNearbyOpenLeadsAPI error: $e, stack: $s");
      toast(context, 'An error occurred while loading leads.');
      _isLoading = false;
      notifyListeners();
    }
  }

  Future<void> updateMarkersFromApiResponse(
    BuildContext context,
    List<LeadList> leadsList,
  ) async {
    _markers = await createMarkersFromApiResponse(context, leadsList);
    _addresses.clear();
    await Future.forEach(leadsList, (store) async {
      String address = await _getAddressFromLatLng(store.loc);
      _addresses.add(address);
    });
    notifyListeners();
  }

  Future<List<Marker>> createMarkersFromApiResponse(
    BuildContext context,
    List<LeadList> leadsList,
  ) async {
    List<Marker> markers = [];
    ByteData data = await rootBundle.load("assets/images/maps_ic.png");
    Uint8List bytes = data.buffer.asUint8List();

    await Future.forEach(leadsList, (leads) async {
      if (leads.loc == null || leads.id == null || leads.name == null) {
        print(
          'Skipping invalid lead: id=${leads.id}, name=${leads.name}, loc=${leads.loc}',
        );
        return;
      }

      ui.Codec codec = await ui.instantiateImageCodec(bytes);
      ui.FrameInfo fi = await codec.getNextFrame();
      Uint8List resizedBytes =
          (await fi.image.toByteData(
            format: ui.ImageByteFormat.png,
          ))!.buffer.asUint8List();

      markers.add(
        Marker(
          markerId: MarkerId(leads.id.toString()),
          position: _parseLatLng(leads.loc),
          icon: BitmapDescriptor.fromBytes(resizedBytes),
          infoWindow: InfoWindow(
            title: leads.name ?? 'Unknown Lead',
            snippet: leads.address ?? 'No address available',
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder:
                      (context) => LeadDetailsByMode(
                        mode: "",
                        pageTitleName: "Lead Details",
                        leadId: leads.id,
                      ),
                ),
              );
            },
            anchor: const Offset(0.5, 1.0),
          ),
          zIndex: 100,
          onTap: () {
            _mapController?.showMarkerInfoWindow(MarkerId(leads.id.toString()));
            print('Marker tapped: id=${leads.id}, name=${leads.name}');
          },
        ),
      );
    });
    return markers;
  }

  Future<void> onMarkerTap(BuildContext context, String leadID) async {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder:
            (context) => LeadDetailsByMode(
              mode: "",
              pageTitleName: "Lead Details",
              leadId: leadID,
            ),
      ),
    );
    notifyListeners();
  }

  LatLng _parseLatLng(String? location) {
    if (location != null) {
      List<String> parts = location.split(',');
      if (parts.length == 2) {
        double lat = double.tryParse(parts[0]) ?? 0.0;
        double lng = double.tryParse(parts[1]) ?? 0.0;
        if (lat != 0.0 && lng != 0.0) {
          return LatLng(lat, lng);
        }
      }
    }
    print('Invalid location string: $location');
    return const LatLng(0.0, 0.0);
  }

  Future<String> _getAddressFromLatLng(String? location) async {
    if (location != null) {
      List<String> parts = location.split(',');
      if (parts.length == 2) {
        double lat = double.tryParse(parts[0]) ?? 0.0;
        double lng = double.tryParse(parts[1]) ?? 0.0;
        if (lat != 0.0 && lng != 0.0) {
          try {
            List<geocoding.Placemark> placemarks = await geocoding
                .placemarkFromCoordinates(lat, lng);
            if (placemarks.isNotEmpty) {
              final placemark = placemarks.first;
              String address =
                  '${placemark.street ?? ''}, '
                  '${placemark.thoroughfare ?? ''} '
                  '${placemark.subLocality ?? ''}, '
                  '${placemark.locality ?? ''}, '
                  '${placemark.administrativeArea ?? ''}, '
                  '${placemark.subAdministrativeArea ?? ''} '
                  '${placemark.postalCode ?? ''}, '
                  '${placemark.country ?? ''}';
              return address.trim();
            }
          } catch (e) {
            print('Geocoding error for location $location: $e');
          }
        }
      }
    }
    return "Address not found";
  }
}
