import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:latlong2/latlong.dart';
import 'package:rasadyar_core/utils/logger_utils.dart';

import 'custom_marker.dart';

enum ErrorLocationType { serviceDisabled, permissionDenied, none }

class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
  Rx<LatLng> currentLocation = LatLng(35.824891, 50.948025).obs;
  String tileType = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';


  RxList<CustomMarker> markers = <CustomMarker>[].obs;
  RxList<LatLng> allMarkers = <LatLng>[].obs;
  Rx<MapController> mapController = MapController().obs;
  RxList<ErrorLocationType> errorLocationType = RxList();
  late final AnimatedMapController animatedMapController;
  Timer? _debounceTimer;
  RxBool isLoading = false.obs;

  @override
  void onInit() {
    super.onInit();
    animatedMapController = AnimatedMapController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
      curve: Curves.easeInOut,
      cancelPreviousAnimations: true,
    );
    locationServiceEnabled().then((value) {
      if (!value) {
        errorLocationType.add(ErrorLocationType.serviceDisabled);
      }
    });

    checkPermission().then((value) {
      if (!value) {
        errorLocationType.add(ErrorLocationType.permissionDenied);
      }
    });

    listenToLocationServiceStatus().listen((event) {
      if (!event) {
        errorLocationType.add(ErrorLocationType.serviceDisabled);
      } else {
        errorLocationType.remove(ErrorLocationType.serviceDisabled);
      }
    });
  }

  @override
  void onReady() {
    super.onReady();
    determineCurrentPosition();
  }

  @override
  void onClose() {
    super.onClose();
    _debounceTimer?.cancel();
    animatedMapController.dispose();
    mapController.close();
  }

  Stream<bool> listenToLocationServiceStatus() {
    return Geolocator.getServiceStatusStream().map((status) {
      return status == ServiceStatus.enabled;
    });
  }

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

  Future<bool> checkPermission({bool request = false}) async {
    try {
      final LocationPermission permission = await Geolocator.checkPermission();

      switch (permission) {
        case LocationPermission.denied:
          final LocationPermission requestResult =
              await Geolocator.requestPermission();
          return requestResult != LocationPermission.denied &&
              requestResult != LocationPermission.deniedForever;

        case LocationPermission.deniedForever:
          return request ? await Geolocator.openAppSettings() : false;

        case LocationPermission.always:
        case LocationPermission.whileInUse:
          return true;

        default:
          return false;
      }
    } catch (e) {
      eLog(e);
      return await Geolocator.openLocationSettings();
    }
  }

  Future<void> determineCurrentPosition() async {
    final position = await Geolocator.getCurrentPosition(
      locationSettings: AndroidSettings(accuracy: LocationAccuracy.best),
    );
    final latLng = LatLng(position.latitude, position.longitude);

    currentLocation.value = latLng;
    markers.add(
      CustomMarker(id: -1, point: latLng, ),
    );
    animatedMapController.animateTo(
      dest: latLng,
      zoom: 18,
      curve: Curves.easeInOut,
      duration: const Duration(milliseconds: 1500),
    );
  }

  void debouncedUpdateVisibleMarkers({required LatLng center}) {
    _debounceTimer?.cancel();
    _debounceTimer = Timer(const Duration(milliseconds: 300), () {
      final filtered = filterNearbyMarkers({
        'markers': allMarkers,
        'centerLat': center.latitude,
        'centerLng': center.longitude,
        'radius': 1000.0,
      });

    //  markers.addAll(filtered);
    });
  }

  List<LatLng> filterNearbyMarkers(Map<String, dynamic> args) {
    final List<LatLng> rawMarkers = args['markers'];
    final double centerLat = args['centerLat'];
    final double centerLng = args['centerLng'];
    final double radiusInMeters = args['radius'];
    final center = LatLng(centerLat, centerLng);
    final distance = Distance();

    return rawMarkers
        .where((marker) => distance(center, marker) <= radiusInMeters)
        .toList();
  }

  void addMarker(CustomMarker marker) {
    markers.add(marker);
  }

  void setMarkers(List<CustomMarker> newMarkers) {
    markers.value = newMarkers;
  }

  void clearMarkers() {
    markers.clear();
  }

}
