import 'package:flutter/material.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import '../models/landmark.dart'; import '../services/landmark_database.dart'; import '../services/local_sqlite_db.dart'; import '../services/offline_routing_engine.dart'; import '../services/tactical_api_service.dart'; class TacticalRoutePlannerSheet extends StatefulWidget { final LatLng currentGps; final LatLng? resectionFix; final LatLng? initialOrigin; final LatLng? initialDestination; final Function(LatLng origin, LatLng destination, TacticalVehicleProfile profile, bool autoStartNav) onRouteConfirmed; final VoidCallback onPickOriginOnMap; final VoidCallback onPickDestinationOnMap; final VoidCallback onClose; const TacticalRoutePlannerSheet({ super.key, required this.currentGps, this.resectionFix, this.initialOrigin, this.initialDestination, required this.onRouteConfirmed, required this.onPickOriginOnMap, required this.onPickDestinationOnMap, required this.onClose, }); @override State createState() => _TacticalRoutePlannerSheetState(); } class _TacticalRoutePlannerSheetState extends State { late LatLng _origin; String _originName = 'موقعي الحالي (GPS)'; LatLng? _destination; TacticalVehicleProfile _selectedProfile = TacticalVehicleProfile.convoy; // Search state final TextEditingController _destSearchCtrl = TextEditingController(); List _searchResults = []; bool _isSearching = false; @override void initState() { super.initState(); _origin = widget.initialOrigin ?? widget.resectionFix ?? widget.currentGps; if (widget.initialOrigin != null) { _originName = 'نقطة محددة من الخريطة (${widget.initialOrigin!.latitude.toStringAsFixed(4)}, ${widget.initialOrigin!.longitude.toStringAsFixed(4)})'; } else if (widget.resectionFix != null) { _originName = 'موقع الراصد المستخرج (التقاطع البصري)'; } if (widget.initialDestination != null) { _destination = widget.initialDestination; _destSearchCtrl.text = 'نقطة الهدف المحددة (${widget.initialDestination!.latitude.toStringAsFixed(4)}, ${widget.initialDestination!.longitude.toStringAsFixed(4)})'; } } @override void dispose() { _destSearchCtrl.dispose(); super.dispose(); } void _onSearch(String query) async { final cleanQuery = query.trim(); if (cleanQuery.isEmpty) { setState(() => _searchResults = []); return; } setState(() => _isSearching = true); List dbResults = []; try { dbResults = await LocalSqliteDb.searchPlaces(cleanQuery, limit: 25); } catch (_) {} final staticResults = LandmarkDatabase.search(cleanQuery); List onlineResults = []; if (dbResults.length < 5) { try { onlineResults = await TacticalApiService.searchOnlinePlaces(cleanQuery); } catch (_) {} } final combined = [...dbResults, ...onlineResults, ...staticResults]; final seen = {}; final unique = []; for (final r in combined) { if (seen.add('${r.name}_${r.lat}_${r.lng}')) { unique.add(r); } } if (mounted) { setState(() { _searchResults = unique; _isSearching = false; }); } } void _selectDestination(TacticalLandmark item) { setState(() { _destination = LatLng(item.lat, item.lng); _searchResults = []; _destSearchCtrl.text = '${item.name} (${item.region})'; }); } void _calculateAndPreview() { if (_destination == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( backgroundColor: Color(0xFFEF4444), content: Text('يرجى تحديد نقطة الوصول / الهدف أولاً.'), ), ); return; } Navigator.pop(context); widget.onRouteConfirmed(_origin, _destination!, _selectedProfile, false); } @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.only(top: 14, left: 16, right: 16, bottom: 24), decoration: const BoxDecoration( color: Color(0xF50F172A), borderRadius: BorderRadius.vertical(top: Radius.circular(24)), border: Border(top: BorderSide(color: Color(0xFF0071E3), width: 2)), boxShadow: [BoxShadow(color: Colors.black87, blurRadius: 30)], ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: const Color(0x330071E3), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0xFF0071E3)), ), child: const Icon(Icons.alt_route, color: Color(0xFF38BDF8), size: 20), ), const SizedBox(width: 10), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'مخطط مسارات القوافل التكتيكية (Routing)', style: TextStyle(color: Colors.white, fontSize: 13.5, fontWeight: FontWeight.bold), ), Text( 'حساب المسار وتضاريس الطرق وسرعة القوافل', style: TextStyle(color: Color(0xFF94A3B8), fontSize: 10.5), ), ], ), ], ), IconButton( onPressed: widget.onClose, icon: const Icon(Icons.close, color: Colors.white70, size: 20), ), ], ), const SizedBox(height: 12), // Origin & Destination Box Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xFF1E293B), borderRadius: BorderRadius.circular(14), border: Border.all(color: Colors.white12), ), child: Column( children: [ // Origin Row Row( children: [ const Icon(Icons.my_location, color: Color(0xFF22C55E), size: 18), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('نقطة الانطلاق (البداية):', style: TextStyle(color: Color(0xFF94A3B8), fontSize: 10)), Text( _originName, style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold), overflow: TextOverflow.ellipsis, ), ], ), ), IconButton( icon: const Icon(Icons.touch_app, size: 18, color: Color(0xFF38BDF8)), tooltip: 'تحديد نقطة البداية على الخريطة', onPressed: () { Navigator.pop(context); widget.onPickOriginOnMap(); }, ), ], ), const Divider(color: Colors.white12, height: 16), // Destination Search Row Row( children: [ const Icon(Icons.location_on, color: Color(0xFFEF4444), size: 18), const SizedBox(width: 10), Expanded( child: TextField( controller: _destSearchCtrl, onChanged: _onSearch, style: const TextStyle(color: Colors.white, fontSize: 12.5), decoration: InputDecoration( hintText: 'ابحث عن نقطة الوصول أو الهدف...', hintStyle: const TextStyle(color: Color(0xFF64748B), fontSize: 11.5), isDense: true, border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(vertical: 6), suffixIcon: _destSearchCtrl.text.isNotEmpty ? IconButton( icon: const Icon(Icons.clear, size: 14, color: Colors.white60), onPressed: () { _destSearchCtrl.clear(); _onSearch(''); }, ) : null, ), ), ), IconButton( icon: const Icon(Icons.touch_app, size: 18, color: Color(0xFFF59E0B)), tooltip: 'تحديد الهدف على الخريطة', onPressed: () { Navigator.pop(context); widget.onPickDestinationOnMap(); }, ), ], ), ], ), ), if (_isSearching) ...[ const SizedBox(height: 4), const LinearProgressIndicator(minHeight: 2, color: Color(0xFF0071E3), backgroundColor: Colors.transparent), ], // Search Results Dropdown if (_searchResults.isNotEmpty) ...[ const SizedBox(height: 6), Container( constraints: const BoxConstraints(maxHeight: 160), decoration: BoxDecoration( color: const Color(0xFF1E293B), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white12), ), child: ListView.separated( padding: EdgeInsets.zero, shrinkWrap: true, itemCount: _searchResults.length, separatorBuilder: (_, __) => const Divider(color: Colors.white10, height: 1), itemBuilder: (ctx, i) { final item = _searchResults[i]; return ListTile( dense: true, visualDensity: VisualDensity.compact, leading: Icon(item.typeIcon, size: 16, color: const Color(0xFF38BDF8)), title: Text(item.name, style: const TextStyle(color: Colors.white, fontSize: 11.5, fontWeight: FontWeight.bold)), subtitle: Text('${item.region} • ${item.typeLabelArabic}', style: const TextStyle(color: Color(0xFF64748B), fontSize: 10)), onTap: () => _selectDestination(item), ); }, ), ), ], const SizedBox(height: 12), // Vehicle Profiles Row( children: [ _buildProfileChip(TacticalVehicleProfile.convoy, 'قافلة عسكرية', Icons.local_shipping), const SizedBox(width: 6), _buildProfileChip(TacticalVehicleProfile.offroad4x4, 'دفع رباعي 4x4', Icons.directions_car), const SizedBox(width: 6), _buildProfileChip(TacticalVehicleProfile.rapidResponse, 'تدخل سريع', Icons.electric_bolt), ], ), const SizedBox(height: 14), // Action Button SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _calculateAndPreview, icon: const Icon(Icons.route, size: 18), label: const Text('حساب المسار وتضاريس الانحدار', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w900)), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0071E3), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 13), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ), ], ), ); } Widget _buildProfileChip(TacticalVehicleProfile prof, String label, IconData icon) { final isSelected = _selectedProfile == prof; return Expanded( child: GestureDetector( onTap: () => setState(() => _selectedProfile = prof), child: Container( padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: isSelected ? const Color(0xFF0071E3) : const Color(0xFF1E293B), borderRadius: BorderRadius.circular(10), border: Border.all(color: isSelected ? Colors.white : Colors.white12), ), child: Column( children: [ Icon(icon, size: 16, color: isSelected ? Colors.white : const Color(0xFF94A3B8)), const SizedBox(height: 3), Text( label, style: TextStyle( color: isSelected ? Colors.white : const Color(0xFF94A3B8), fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), ), ), ); } }