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:flutter_svg/svg.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/Utils/SharedpreferencesService.dart';
import 'package:generp/screens/LoginScreen.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/NearbyGeneratorsResponse.dart';
import '../../Utils/commonServices.dart';

class CrmNearByGeneratorsProvider extends ChangeNotifier {
  final ImagePicker _picker = ImagePicker();

  List<Nearbygenerators> _generatorslist = [];
  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;
  String _selectedItem = 'Active';
  double _currentValue = 1.0;
  Timer? _debounceTimer;

  List<Nearbygenerators> get generatorsList => _generatorslist;
  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;
  String get selectedItem => _selectedItem;
  double get currentValue => _currentValue;

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

  set selectedItem(String value) {
    _selectedItem = value;
    notifyListeners();
  }

  set markers(List<Marker> value) {
    _markers = value;
    notifyListeners();
  }

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

  void resetAll() {
    _currentValue = 1.0;
    _selectedItem = "";
    _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';
      LoadNearbyGeneratorsAPI(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> LoadNearbyGeneratorsAPI(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.loadCrmNearbyGeneratorsAPI(
        provider.empId,
        provider.session,
        _latlongs,
        _currentValue,
        _selectedItem,
      );

      if (data != null) {
        if (data.sessionExists == 1) {
          if (data.error == 0) {
            _generatorslist = data.list!;

            await updateMarkersFromApiResponse(context, data.list!);
            _isLoading = false;
            notifyListeners();
          } else {}
        } else {
          // SharedpreferencesService().clearPreferences();
          // Navigator.push(
          //   context,
          //   MaterialPageRoute(builder: (context) => LoginScreen()),
          // );
        }
      } else {
        toast(context, "Something went wrong, Please try again.");
      }
    } on Exception catch (e) {
      print("$e");
    }
  }

  Future<void> updateMarkersFromApiResponse(
    BuildContext context,
    List<Nearbygenerators> generatorslist,
  ) async {
    _markers = await createMarkersFromApiResponse(context, generatorslist);
    _addresses.clear();
    await Future.forEach(generatorslist, (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<Nearbygenerators> generatorslist,
  ) async {
    List<Marker> markers = [];

    // print("Hello Nutsby!");
    ByteData data = await rootBundle.load("assets/images/dg_set.png");
    Uint8List bytes = data.buffer.asUint8List();

    await Future.forEach(generatorslist, (generator) async {
      ui.Codec codec = await ui.instantiateImageCodec(
        bytes,
        targetWidth: 75,
        targetHeight: 95,
      );
      ui.FrameInfo fi = await codec.getNextFrame();
      Uint8List resizedBytes =
          (await fi.image.toByteData(
            format: ui.ImageByteFormat.png,
          ))!.buffer.asUint8List();

      markers.add(
        Marker(
          markerId: MarkerId(generator.generatorId.toString()),
          position: _parseLatLng(generator.loc),
          icon: BitmapDescriptor.fromBytes(resizedBytes),
          infoWindow: InfoWindow(
            onTap: () {
              print("INFO WINDOW TAP");
            },
            title: "Customer Name: ${generator.accName}",
            snippet: "Product Name: ${generator.productName}",
          ),
          zIndex: 100,
        ),
      );
    });
    return markers;
  }



  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";
  }
}
