import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/common/constant.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
import 'package:rasadyar_livestock/presentation/page/root/logic.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';
  RxDouble currentZoom = 15.0.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;

/*  FMTCTileProvider tileProvider = FMTCTileProvider(
    stores: {mapStoreKey: BrowseStoreStrategy.readUpdateCreate},
  );*/

  RxList<LatLng> markerLocations = RxList();
  RootLogic rootLogic = Get.find<RootLogic>();
  LivestockRepository repository = diLiveStock.get<LivestockRepository>();

  @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);
      }
    });

    repository.addLocations(generateRandomLocations(currentLocation.value, 10, 100));
  }

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

  @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;

    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();
  }

  Future<void> getLoc() async {
    await Future.delayed(Duration(seconds: 3));
    await safeCall(
      call: () async => repository.getLocations(),
      onSuccess: (result) {
        iLog("OOOpssss => ${result.length}");
        markerLocations.addAll(result);
      },
      onError: (error, stackTrace) {},
    );
  }

  List<LatLng> generateRandomLocations(LatLng currentPosition, double radiusInKm, int count) {
    final random = Random();
    final locations = <LatLng>[];

    for (int i = 0; i < count; i++) {
      // فاصله تصادفی (۰ تا radius)
      final distance = random.nextDouble() * radiusInKm * 1000; // متر
      // زاویه تصادفی (۰ تا ۲π)
      final angle = random.nextDouble() * 2 * pi;

      // فاصله به درجه
      final dx = distance * cos(angle);
      final dy = distance * sin(angle);

      // 1 درجه lat ≈ 111km
      final newLat = currentPosition.latitude + (dy / 111000.0);

      // 1 درجه lon ≈ 111km * cos(lat)
      final newLng =
          currentPosition.longitude + (dx / (111000.0 * cos(currentPosition.latitude * pi / 180)));

      locations.add(LatLng(newLat, newLng));
    }

    return locations;
  }
}
