import 'dart:math' as math;
import 'package:latlong2/latlong.dart';

class NavigationHelper {
  static const Distance _distanceCalculator = Distance();

  /// Menghitung jarak antara dua titik dalam meter
  static double calculateDistance(LatLng p1, LatLng p2) {
    return _distanceCalculator.as(LengthUnit.Meter, p1, p2);
  }

  /// Menghitung bearing (sudut) antara dua titik (0-360 derajat)
  static double calculateBearing(LatLng p1, LatLng p2) {
    double lat1 = p1.latitude * math.pi / 180;
    double lon1 = p1.longitude * math.pi / 180;
    double lat2 = p2.latitude * math.pi / 180;
    double lon2 = p2.longitude * math.pi / 180;

    double dLon = lon2 - lon1;
    double y = math.sin(dLon) * math.cos(lat2);
    double x = math.cos(lat1) * math.sin(lat2) -
        math.sin(lat1) * math.cos(lat2) * math.cos(dLon);
    double radians = math.atan2(y, x);
    return (radians * 180 / math.pi + 360) % 360;
  }

  /// Menghitung jarak terdekat dari titik ke sebuah segmen garis (Cross Track Distance)
  static double getDistanceToSegment(LatLng p, LatLng s1, LatLng s2) {
    final double l2 = math.pow(calculateDistance(s1, s2), 2).toDouble();
    if (l2 == 0) return calculateDistance(p, s1);

    // Proyeksi titik ke garis
    double t = ((p.latitude - s1.latitude) * (s2.latitude - s1.latitude) +
            (p.longitude - s1.longitude) * (s2.longitude - s1.longitude)) /
        (math.pow(s2.latitude - s1.latitude, 2) +
            math.pow(s2.longitude - s1.longitude, 2));

    t = math.max(0, math.min(1, t));

    LatLng projection = LatLng(
      s1.latitude + t * (s2.latitude - s1.latitude),
      s1.longitude + t * (s2.longitude - s1.longitude),
    );

    return calculateDistance(p, projection);
  }

  /// Menentukan apakah ada belokan tajam di titik tertentu pada rute
  static String? detectManeuver(List<LatLng> points, int index) {
    if (index <= 0 || index >= points.length - 1) return null;

    double bearing1 = calculateBearing(points[index - 1], points[index]);
    double bearing2 = calculateBearing(points[index], points[index + 1]);

    double diff = (bearing2 - bearing1 + 360) % 360;

    if (diff > 180) diff -= 360;

    if (diff > 25 && diff < 160) {
      return "Belok Kanan";
    } else if (diff < -25 && diff > -160) {
      return "Belok Kiri";
    }

    return null;
  }
}
