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

import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart' hide BaseLogic;
import 'package:rasadyar_inspection/data/model/response/hatching_details/hatching_details.dart';
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart';

class MapLogic extends GetxController with GetTickerProviderStateMixin {
  RxBool isLoading = false.obs;
  RxBool isSelectedDetailsLocation = false.obs;
  RxDouble currentZoom = (15.0).obs;
  Rx<MapController> mapController = MapController().obs;
  BaseLogic baseLogic = Get.find<BaseLogic>();
  InspectionRepositoryImp inspectionRepository = diInspection.get<InspectionRepositoryImp>();

  Rx<LatLng> currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs;
  RxBool hasFilterOrSearch = false.obs;

  Timer? _debounceTimer;

  final distance = Distance();

  late final AnimatedMapController animatedMapController;

  Rx<Resource<List<PoultryLocationModel>>> markerLocations =
      Resource<List<PoultryLocationModel>>.initial().obs;

  Rx<Resource<List<PoultryLocationModel>>> allLocations =
      Resource<List<PoultryLocationModel>>.initial().obs;

  Rx<Resource<List<PoultryLocationModel>>> filteredLocations =
      Resource<List<PoultryLocationModel>>.initial().obs;

  Rx<Resource<List<HatchingDetails>>> hatchingDetails =
      Resource<List<HatchingDetails>>.initial().obs;

  @override
  void onInit() {
    super.onInit();
    animatedMapController = AnimatedMapController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
      curve: Curves.easeInOut,
      cancelPreviousAnimations: true,
    );

    ever(hasFilterOrSearch, (callback) {
      if (callback) {
        markerLocations.value = filteredLocations.value;
      } else {
        markerLocations.value = allLocations.value;
      }
    });

    ever(allLocations, (_) {
      if (!hasFilterOrSearch.value) {
        markerLocations.value = allLocations.value;
      }
    });

    ever(filteredLocations, (_) {
      if (hasFilterOrSearch.value) {
        markerLocations.value = filteredLocations.value;
      }
    });
  }

  @override
  void onReady() {
    // TODO: implement onReady
    super.onReady();
  }

  @override
  void onClose() {
    // TODO: implement onClose
    super.onClose();
  }

  double _deg2rad(double deg) => deg * (pi / 180);

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

    /*currentLocation.value = latLng;
    markers.add(PoultryLocationModel(
      lat: latLng.latitude,
      long: latLng.longitude
    ));*/
    animatedMapController.animateTo(
      dest: latLng,
      zoom: 18,
      curve: Curves.easeInOut,
      duration: const Duration(seconds: 1),
    );
    isLoading.value = false;
  }

  /*
    void debouncedUpdateVisibleMarkers({required LatLng center, required double zoom}) {
    _debounceTimer?.cancel();
    _debounceTimer = Timer(const Duration(milliseconds: 300), () {
      final radius = getVisibleRadiusKm(
        zoom: zoom,
        screenWidthPx: Get.width.toDouble(),
        latitude: center.latitude,
      );

      final filtered = filterNearbyMarkers(
        all.value.data ?? [],
        center.latitude,
        center.longitude,
        radius,
      );
      final existingIds = markers2.map((e) => e.id).toSet();
      final uniqueFiltered = filtered.where((e) => !existingIds.contains(e.id)).toList();
      markers2.addAll(uniqueFiltered);
    });
  }
*/

  List<LatLng> filterNearbyMarkers(
    List<LatLng> allMarkers,
    double centerLat,
    double centerLng,
    double radiusInMeters,
  ) {
    final center = LatLng(centerLat, centerLng);

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

  double getVisibleRadiusKm({required LatLng center, required LatLng corner}) {
    const earthRadius = 6371; // Km

    final dLat = _deg2rad(corner.latitude - center.latitude);
    final dLng = _deg2rad(corner.longitude - center.longitude);

    final a =
        sin(dLat / 2) * sin(dLat / 2) +
        cos(_deg2rad(center.latitude)) *
            cos(_deg2rad(corner.latitude)) *
            sin(dLng / 2) *
            sin(dLng / 2);

    final c = 2 * atan2(sqrt(a), sqrt(1 - a));
    return earthRadius * c;
  }

  bool isInVisibleBounds(LatLng point, LatLngBounds bounds) {
    return point.latitude <= bounds.north &&
        point.latitude >= bounds.south &&
        point.longitude >= bounds.west &&
        point.longitude <= bounds.east;
  }

  Future<void> getFullDetailsLocation(PoultryLocationModel model) async {
    hatchingDetails.value = Resource<List<HatchingDetails>>.loading();
    await safeCall(
      call: () => inspectionRepository.getHatchingDetails(
        code: model.breedingUniqueId,
        active: (model.hatching != null && model.hatching!.isNotEmpty),
      ),
      onSuccess: (result) {
        if (result != null && result.isNotEmpty) {
          hatchingDetails.value = Resource<List<HatchingDetails>>.success(result);
        } else {
          hatchingDetails.value = Resource<List<HatchingDetails>>.empty();
        }
      },
      onError: (error, stackTrace) {
        hatchingDetails.value = Resource<List<HatchingDetails>>.error('$error / $stackTrace');
      },
    );
  }

  void cleanDataAfterBottomSheet() {
    eLog('cleanDataAfterBottomSheet');
    hatchingDetails.value = Resource<List<HatchingDetails>>.initial();
  }
}
