import 'package:shared_preferences/shared_preferences.dart';
import 'package:qyuota/config/api_config.dart';
import 'dart:math' show asin, cos, pow, sin, sqrt;

class LocationConfig {
  // Singleton pattern
  static final LocationConfig _instance = LocationConfig._internal();
  factory LocationConfig() => _instance;
  LocationConfig._internal();

  // Mendapatkan latitude kantor dari SharedPreferences atau default
  Future<double> getOfficeLatitude() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getDouble(ApiConfig.officeLatitudeKey) ?? ApiConfig.defaultOfficeLatitude;
  }

  // Mendapatkan longitude kantor dari SharedPreferences atau default
  Future<double> getOfficeLongitude() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getDouble(ApiConfig.officeLongitudeKey) ?? ApiConfig.defaultOfficeLongitude;
  }

  // Mendapatkan radius presensi dari SharedPreferences atau default
  Future<double> getRadiusInMeters() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getDouble(ApiConfig.radiusInMetersKey) ?? ApiConfig.defaultRadiusInMeters;
  }

  // Menyimpan konfigurasi lokasi kantor baru
  Future<bool> saveOfficeLocation(double latitude, double longitude) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setDouble(ApiConfig.officeLatitudeKey, latitude);
    return await prefs.setDouble(ApiConfig.officeLongitudeKey, longitude);
  }

  // Menyimpan radius presensi baru
  Future<bool> saveRadius(double radius) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.setDouble(ApiConfig.radiusInMetersKey, radius);
  }

  // Menghitung jarak antara dua koordinat (Haversine formula)
  double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
    const double earthRadius = 6371000; // Radius bumi dalam meter
    const double tolerance = 50.0; // Toleransi 50 meter untuk akurasi GPS
    
    // Konversi derajat ke radian
    final double dLat = _toRadians(lat2 - lat1);
    final double dLon = _toRadians(lon2 - lon1);
    
    // Rumus haversine
    final double a = pow(sin(dLat / 2), 2) + 
                     cos(_toRadians(lat1)) * 
                     cos(_toRadians(lat2)) * 
                     pow(sin(dLon / 2), 2);
    
    final double c = 2 * asin(sqrt(a));
    
    // Jarak dalam meter dengan toleransi
    double distance = (earthRadius * c) - tolerance;
    
    print('\n=== DETAIL PERHITUNGAN JARAK ===');
    print('Koordinat 1: ($lat1, $lon1)');
    print('Koordinat 2: ($lat2, $lon2)');
    print('dLat (radian): ${dLat.toStringAsFixed(6)}');
    print('dLon (radian): ${dLon.toStringAsFixed(6)}');
    print('a: ${a.toStringAsFixed(6)}');
    print('c: ${c.toStringAsFixed(6)}');
    print('Jarak akhir: ${distance.toStringAsFixed(2)} meter');
    print('Toleransi: ${tolerance.toStringAsFixed(2)} meter');
    
    return distance > 0 ? distance : 0; // Pastikan jarak tidak negatif
  }
  
  // Konversi derajat ke radian
  double _toRadians(double degree) {
    return degree * (3.141592653589793 / 180);
  }
  
  // Memeriksa apakah lokasi berada dalam radius yang ditentukan
  Future<bool> isLocationInRadius(double latitude, double longitude) async {
    double officeLatitude = await getOfficeLatitude();
    double officeLongitude = await getOfficeLongitude();
    double radiusInMeters = await getRadiusInMeters();
    
    double distance = calculateDistance(
      latitude, 
      longitude, 
      officeLatitude, 
      officeLongitude
    );
    
    return distance <= radiusInMeters;
  }
} 