import 'dart:convert';
import 'dart:math';

import 'package:get/get.dart';
import 'package:siro_driver/constant/box_name.dart';
import 'package:siro_driver/constant/links.dart';
import 'package:siro_driver/controller/functions/crud.dart';

import '../../../constant/table_names.dart';
import '../../../main.dart';
import '../../../print.dart';

class DriverBehaviorController extends GetxController {
  Future<List<Map<String, dynamic>>> getAllData() async {
    return await sql.getAllData(TableName.behavior);
  }

  var isLoading = false.obs;
  var overallScore = 100.0.obs;
  var lastTrips = [].obs;

  Future<void> fetchDriverBehavior() async {
    isLoading.value = true;
    try {
      final response = await CRUD().get(
        link: AppLink.get_driver_behavior,
        payload: {"driver_id": box.read(BoxName.driverID).toString()},
      );

      if (response != 'failure') {
        final json = jsonDecode(response);

        overallScore.value =
            double.parse(json['message']['overall_behavior_score'].toString());
        lastTrips.value = json['message']['last_10_trips'];
      } else {
        // Get.snackbar("Error", json['message'] ?? "Unknown error");
      }
    } catch (e) {
      // Get.snackbar("Error", "Exception: $e");
      Log.print('e: ${e}');
    } finally {
      isLoading.value = false;
    }
  }

  Future<Map<String, dynamic>> analyzeData() async {
    final data = await getAllData();
    if (data.isEmpty) return {};

    double maxSpeed = 0;
    double totalSpeed = 0;
    int hardBrakes = 0;
    double totalDistance = 0;

    // متغيرات للمقارنة مع النقطة السابقة
    double? prevLat, prevLng;
    DateTime? prevTime;

    // ترتيب البيانات حسب الوقت لضمان دقة الحساب (اختياري لكن مفضل)
    // data.sort((a, b) => a['created_at'].compareTo(b['created_at']));

    for (var item in data) {
      // 1. قراءة البيانات بالأسماء الصحيحة من الجدول
      double lat = item['latitude'] ?? item['lat'] ?? 0.0;
      double lng = item['longitude'] ?? item['lng'] ?? 0.0;
      double acc = item['acceleration'] ?? 0.0;

      // قراءة الوقت لحساب السرعة
      DateTime currentTime =
          DateTime.tryParse(item['created_at'].toString()) ?? DateTime.now();

      double currentSpeed = 0;

      // 2. حساب السرعة والمسافة إذا وجدت نقطة سابقة
      if (prevLat != null && prevLng != null && prevTime != null) {
        double distKm = _calculateDistance(prevLat, prevLng, lat, lng);
        int timeDiffSeconds = currentTime.difference(prevTime).inSeconds;

        if (timeDiffSeconds > 0) {
          // السرعة (كم/س) = (المسافة بالكيلومتر * 3600) / الزمن بالثواني
          currentSpeed = (distKm * 3600) / timeDiffSeconds;
        }

        totalDistance += distKm;
      }

      // تحديث القيم الإحصائية
      if (currentSpeed > maxSpeed) maxSpeed = currentSpeed;
      totalSpeed += currentSpeed;

      // حساب الفرملة القوية (يعتمد على التسارع المحفوظ مسبقاً)
      if (acc.abs() > 3.0) hardBrakes++;

      // حفظ النقطة الحالية لتكون هي "السابقة" في الدورة التالية
      prevLat = lat;
      prevLng = lng;
      prevTime = currentTime;
    }

    // تجنب القسمة على صفر
    double avgSpeed = (data.length > 1) ? totalSpeed / (data.length - 1) : 0;

    // حساب تقييم السلوك
    double behaviorScore = 100 - (hardBrakes * 5) - ((maxSpeed > 100) ? 10 : 0);
    behaviorScore = behaviorScore.clamp(0.0, 100.0);

    return {
      'max_speed': maxSpeed,
      'avg_speed': avgSpeed,
      'hard_brakes': hardBrakes,
      'total_distance': totalDistance,
      'behavior_score': behaviorScore,
    };
  }

  Future<void> sendSummaryToServer(String driverId, String tripId) async {
    final summary = await analyzeData();
    if (summary.isEmpty) return;

    final Map<String, dynamic> body = {
      'driver_id': driverId,
      'trip_id': tripId,
      ...summary, // فيه doubles
    };

    // اجبر كل القيم على String
    final payload = body.map((k, v) => MapEntry(k, v?.toString() ?? ''));

    await CRUD().post(link: AppLink.saveBehavior, payload: payload);
    await clearData();
  }

  Future<void> clearData() async {
    await sql.deleteAllData(TableName.behavior);
  }

  double _calculateDistance(
      double lat1, double lon1, double lat2, double lon2) {
    const p = 0.017453292519943295;
    final a = 0.5 -
        cos((lat2 - lat1) * p) / 2 +
        cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2;
    return 12742 * asin(sqrt(a)); // distance in km
  }
}
