import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import 'package:siro_driver/constant/links.dart'; import 'package:siro_driver/controller/functions/crud.dart'; import 'package:siro_driver/controller/functions/tts.dart'; import 'package:siro_driver/views/widgets/error_snakbar.dart'; class DestinationController extends GetxController { bool isLoading = false; bool isSelectingDestinationOnMap = false; // Active destination details LatLng? activeLatLng; String activeName = ""; final TextEditingController searchController = TextEditingController(); List placesSuggestions = []; Timer? _debounce; @override void onInit() { super.onInit(); fetchActiveDestination(); } @override void onClose() { searchController.dispose(); _debounce?.cancel(); super.onClose(); } // --- 1. Get current active destination from backend --- Future fetchActiveDestination() async { isLoading = true; update(); try { final response = await CRUD().post( link: AppLink.saveDriverDestination, payload: {'action': 'get'}, ); if (response != null && response is Map && response['status'] == 'success') { final data = response['message']; if (data != null) { final lat = double.tryParse(data['target_latitude']?.toString() ?? '0') ?? 0.0; final lng = double.tryParse(data['target_longitude']?.toString() ?? '0') ?? 0.0; activeLatLng = LatLng(lat, lng); activeName = data['destination_name']?.toString() ?? ""; } else { activeLatLng = null; activeName = ""; } } } catch (e) { print("[DestinationController] fetchActiveDestination error: $e"); } finally { isLoading = false; update(); } } // --- 2. Autocomplete search suggestions --- void onSearchChanged(String query) { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 500), () => getPlacesSuggestions(query)); } Future getPlacesSuggestions(String query) async { if (query.trim().length < 3) { placesSuggestions = []; update(); return; } try { final url = '${AppLink.mapSaasPlaces}?q=${Uri.encodeComponent(query)}'; final response = await CRUD().getMapSaas(link: url); if (response != null && response is List) { placesSuggestions = response; } else { placesSuggestions = []; } update(); } catch (e) { print("[DestinationController] getPlacesSuggestions error: $e"); } } // --- 3. Save destination to database --- Future saveDestination(LatLng position, String name) async { isLoading = true; update(); try { final response = await CRUD().post( link: AppLink.saveDriverDestination, payload: { 'action': 'set', 'destination_lat': position.latitude.toString(), 'destination_lng': position.longitude.toString(), 'destination_name': name, }, ); if (response != null && response is Map) { if (response['status'] == 'success') { activeLatLng = position; activeName = name; mySnackbarSuccess('Destination set successfully!'.tr); } else { final msg = response['message']?.toString() ?? ""; if (msg.contains("الحد الأقصى") || msg.contains("limit")) { mySnackbarWarning('You have reached the daily limit of 2 destination settings.'.tr); } else { mySnackbarWarning('Failed to set destination. Please try again.'.tr); } } } else { mySnackbarWarning('Failed to set destination. Please try again.'.tr); } } catch (e) { print("[DestinationController] saveDestination error: $e"); mySnackbarWarning('Failed to set destination. Please try again.'.tr); } finally { isLoading = false; update(); } } // --- 4. Clear/Deactivate destination --- Future clearDestination() async { isLoading = true; update(); try { final response = await CRUD().post( link: AppLink.saveDriverDestination, payload: {'action': 'clear'}, ); if (response != null && response is Map && response['status'] == 'success') { activeLatLng = null; activeName = ""; mySnackbarSuccess('Destination cleared!'.tr); } else { mySnackbarWarning('Failed to set destination. Please try again.'.tr); } } catch (e) { print("[DestinationController] clearDestination error: $e"); mySnackbarWarning('Failed to set destination. Please try again.'.tr); } finally { isLoading = false; update(); } } // --- 5. Reverse geocoding (for map picker) --- Future reverseGeocode(LatLng location) async { final url = '${AppLink.reverseGeocoding}?lat=${location.latitude}&lng=${location.longitude}'; try { final response = await CRUD().getMapSaas(link: url); if (response != null && response is List && response.isNotEmpty) { final data = response[0]; return data['name_ar'] ?? data['name'] ?? 'Selected Location'.tr; } return 'Selected Location'.tr; } catch (e) { print("[DestinationController] reverseGeocode error: $e"); return 'Selected Location'.tr; } } // --- 6. TTS Voice Explanation Helper --- void toggleSpeaker() { final tts = Get.find(); if (tts.isSpeaking) { tts.stop(); } else { tts.speakText('Destination Tool Description'.tr); } } }