part of '../deliveries/deliveries.dart';

// -------------------------------------------------------------------------
// CART PAGE (Active Deliveries)
// -------------------------------------------------------------------------
class Cartpage extends StatefulWidget {
  const Cartpage({super.key});

  @override
  State<Cartpage> createState() => _CartpageState();
}

class _CartpageState extends State<Cartpage> with AutomaticKeepAliveClientMixin {
  final DeliveryProvider _provider = DeliveryProvider();
  final CreateDeliveryLogProvider _deliveryLogProvider = CreateDeliveryLogProvider();
  
  List<Map<String, dynamic>> _activeDeliveries = <Map<String, dynamic>>[];
  StreamSubscription<void>? _pollerSubscription;
  bool _fetching = false;
  final Map<String, Timer> _deliveryTimers = <String, Timer>{};
  final Map<String, Map<String, dynamic>> _deliveryBasePayload = <String, Map<String, dynamic>>{};

  @override
  bool get wantKeepAlive => true;

  @override
  void initState() {
    super.initState();
    _fetchActive();
    _startPolling();
  }

  @override
  void dispose() {
    _pollerSubscription?.cancel();
    _stopAllTimers();
    super.dispose();
  }

  void _startPolling() {
    _pollerSubscription?.cancel();
    _pollerSubscription = Stream.periodic(
      const Duration(seconds: 10),
      (_) {},
    ).asyncMap((_) async {
      if (!_fetching && mounted) {
        await _fetchActive();
      }
    }).listen(
      (_) {},
      onError: (error) {
        debugPrint('[CART][STREAM ERROR] $error');
      },
      cancelOnError: false,
    );
  }

  Future<void> _fetchActive() async {
    if (_fetching) return;

    _fetching = true;
    try {
      final prefs = await SharedPreferences.getInstance();
      final userId = prefs.getInt('userid') ?? prefs.getInt('userId') ?? 0;

      if (userId == 0) {
        debugPrint('[CART] No user ID found');
        _fetching = false;
        return;
      }

      // Get current date in YYYY-MM-DD format
      final now = DateTime.now();
      final today = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';

      // Hardcoded API endpoint for cart page only: v2/deliveries/getdeliveries
      final bool isLive = ApiConstants.mainRoute == 'live';
      final baseUrl = isLive
          ? 'https://jupiter.nearle.app/live/api/v2/deliveries/getdeliveries'
          : 'https://jupiter.nearle.app/dev/api/v2/deliveries/getdeliveries';

      final uri = Uri.parse(baseUrl).replace(queryParameters: {
        'userid': userId.toString(),
        'fromdate': today,
        'todate': today,
        't': DateTime.now().millisecondsSinceEpoch.toString(),
      });

      debugPrint('[CART] Fetching from: $uri');

      // Fetch deliveries from API directly using http
      // Hardcoded endpoint for cart page: v2/deliveries/getdeliveries
      final httpClient = http.Client();
      List<dynamic> items = [];
      try {
        final response = await httpClient.get(uri);

        if (response.statusCode >= 200 && response.statusCode < 300) {
          final decoded = json.decode(response.body);
          final data = decoded is Map<String, dynamic>
              ? (decoded['details'] ?? decoded['data'] ?? decoded)
              : decoded;

          items = data is List 
              ? data 
              : (data is Map && data['items'] is List ? data['items'] as List : []);
        } else {
          debugPrint('[CART] API error: ${response.statusCode}');
        }
      } catch (e) {
        debugPrint('[CART] Error fetching from API: $e');
      } finally {
        httpClient.close();
      }

      debugPrint('[CART] Raw API items count: ${items.length}');
      
      // Debug: Print all order statuses to see what we're getting
      for (final item in items) {
        if (item is Map<String, dynamic>) {
          final orderId = (item['orderid'] ?? '').toString();
          final status = (item['orderstatus'] ?? '').toString();
          debugPrint('[CART] Order $orderId has status: "$status" (raw: ${item['orderstatus']})');
        }
      }

      // Filter for ACTIVE status only
      final activeOrders = items
          .whereType<Map<String, dynamic>>()
          .where((order) {
            final status = (order['orderstatus']?.toString().toLowerCase() ?? '').trim();
            final isActive = status == 'active';
            if (isActive) {
              debugPrint('[CART] ✅ Found active order: ${order['orderid']}');
            } else {
              debugPrint('[CART] ❌ Order ${order['orderid']} has status: "$status" (not active)');
            }
            return isActive;
          })
          .toList();

      debugPrint('[CART] Found ${activeOrders.length} active deliveries out of ${items.length} total');

      // Sort by order ID or step number if available
      activeOrders.sort((a, b) {
        final stepA = (a['step'] ?? a['Step'] ?? 0).toString();
        final stepB = (b['step'] ?? b['Step'] ?? 0).toString();
        final stepAInt = int.tryParse(stepA) ?? 0;
        final stepBInt = int.tryParse(stepB) ?? 0;
        if (stepAInt != stepBInt) return stepAInt.compareTo(stepBInt);
        
        final orderIdA = (a['orderid'] ?? '').toString();
        final orderIdB = (b['orderid'] ?? '').toString();
        return orderIdA.compareTo(orderIdB);
      });

      if (mounted) {
        setState(() {
          _activeDeliveries = activeOrders;
        });
      }

      // Get all active order IDs
      final activeOrderIds = activeOrders
          .map((o) => (o['orderid'] ?? '').toString())
          .where((id) => id.isNotEmpty)
          .toSet();

      // ✅ CRITICAL: Start/restart timers for ALL active deliveries
      // This ensures every active delivery posts logs every 30 seconds
      for (final order in activeOrders) {
        final orderId = (order['orderid'] ?? '').toString();
        if (orderId.isEmpty) {
          debugPrint('[CART] ⚠️ Skipping order with empty orderId');
          continue;
        }

        // Always restart timer to ensure it's running (handles edge cases)
        if (_deliveryTimers.containsKey(orderId)) {
          debugPrint('[CART] 🔄 Restarting timer for active delivery: $orderId');
          _deliveryTimers[orderId]?.cancel();
          _deliveryTimers.remove(orderId);
          // Also clear base payload to force reload
          _deliveryBasePayload.remove(orderId);
        }

        debugPrint('[CART] ▶️ Starting timer for active delivery: $orderId');
        await _startDeliveryPosting(order);
        debugPrint('[CART] ✅ Timer started successfully for: $orderId');
      }

      // ✅ Stop timers for deliveries that are no longer active
      final timersToStop = _deliveryTimers.keys
          .where((id) => !activeOrderIds.contains(id))
          .toList();

      for (final id in timersToStop) {
        debugPrint('[CART] Stopping timer for orderId: $id (no longer active)');
        _stopDeliveryPosting(id);
      }

      debugPrint('[CART] Active timers: ${_deliveryTimers.keys.toList()}');
    } catch (e) {
      debugPrint('[CART] Error fetching active deliveries: $e');
    } finally {
      _fetching = false;
    }
  }

  Future<void> _startDeliveryPosting(Map<String, dynamic> order) async {
    final orderId = (order['orderid'] ?? '').toString();
    if (orderId.isEmpty) {
      debugPrint('[CART][DELIVERYLOG] ⚠️ Cannot start timer: empty orderId');
      return;
    }

    // Safety check: If timer already exists, cancel it first (shouldn't happen after cleanup above)
    if (_deliveryTimers.containsKey(orderId)) {
      debugPrint('[CART][DELIVERYLOG] ⚠️ Timer already exists for $orderId, canceling old one');
      _deliveryTimers[orderId]?.cancel();
      _deliveryTimers.remove(orderId);
    }

    debugPrint('[CART][DELIVERYLOG] 🚀 Starting 30-second timer for orderId: $orderId');

    // Get starttime from SharedPreferences (saved when order became active via updateActiveStatus)
    // If not found, use activetime from order data, or current time as fallback
    String startTime = '';
    try {
      final prefs = await SharedPreferences.getInstance();
      final deliveryId = (order['deliveryid'] ?? 0).toString();
      
      // Method 1: Get from SharedPreferences (saved when order became active)
      startTime = prefs.getString('delivery_starttime_$deliveryId') ?? '';
      if (startTime.isNotEmpty) {
        debugPrint('[CART][DELIVERYLOG] ✅ Loaded starttime from SharedPreferences: $startTime');
      }
      
      // Method 2: Fallback - try to get from order data (starttime field)
      if (startTime.isEmpty) {
        startTime = (order['starttime'] ?? order['startTime'] ?? '').toString();
        if (startTime.isNotEmpty) {
          debugPrint('[CART][DELIVERYLOG] ✅ Loaded starttime from order data: $startTime');
        }
      }
      
      // Method 3: Fallback - try activetime from order data
      if (startTime.isEmpty) {
        final activetime = (order['activetime'] ?? order['activTime'] ?? '').toString();
        if (activetime.isNotEmpty) {
          startTime = activetime;
          debugPrint('[CART][DELIVERYLOG] ✅ Loaded starttime from activetime: $startTime');
        }
      }
      
      // Method 4: Last fallback - current time (shouldn't happen if updateActiveStatus was called)
      if (startTime.isEmpty) {
        final now = DateTime.now();
        startTime = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}';
        debugPrint('[CART][DELIVERYLOG] ⚠️ Using current time as starttime fallback: $startTime');
      }
    } catch (e) {
      debugPrint('[CART][DELIVERYLOG] ❌ Error getting starttime: $e');
      // Set a fallback starttime even on error
      final now = DateTime.now();
      startTime = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}';
    }
    
    // CRITICAL: Ensure starttime is never empty
    if (startTime.isEmpty) {
      final now = DateTime.now();
      startTime = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}';
      debugPrint('[CART][DELIVERYLOG] ⚠️ Final fallback: starttime was empty, using: $startTime');
    }
    
    debugPrint('[CART][DELIVERYLOG] 📝 Final starttime for orderId $orderId: $startTime');

    // Create base payload with starttime
    final base = <String, dynamic>{
      'logid': 0,
      'tenantid': order['tenantid'] ?? 0,
      'partnerid': order['partnerid'] ?? 0,
      'locationid': order['locationid'] ?? 0,
      'orderheaderid': order['orderheaderid'] ?? 0,
      'deliveryid': order['deliveryid'] ?? 0,
      'userid': order['userid'] ?? 0,
      'orderid': orderId,
      'orderstatus': 'active',
      'starttime': startTime, // Include starttime in base payload
    };

    _deliveryBasePayload[orderId] = base;

    // Save to SharedPreferences for persistence
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('deliverylog_${orderId}_tenantid', (base['tenantid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_partnerid', (base['partnerid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_locationid', (base['locationid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_orderheaderid', (base['orderheaderid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_deliveryid', (base['deliveryid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_userid', (base['userid'] ?? 0).toString());
      await prefs.setString('deliverylog_${orderId}_orderid', orderId);
      await prefs.setString('deliverylog_${orderId}_orderstatus', 'active');
      await prefs.setString('deliverylog_${orderId}_starttime', startTime); // Save starttime
    } catch (e) {
      debugPrint('[CART][DELIVERYLOG] Error saving payload: $e');
    }

    // Post once immediately (don't await - let it run in background)
    _postDeliveryLog(orderId, order);
    debugPrint('[CART][DELIVERYLOG] 📤 Posted initial log for orderId: $orderId');

    // Then every 30 seconds - CRITICAL: This ensures logs are posted every 30 seconds
    final timer = Timer.periodic(const Duration(seconds: 30), (t) {
      debugPrint('[CART][DELIVERYLOG] ⏰ Timer tick for orderId: $orderId (30 seconds elapsed)');
      _postDeliveryLog(orderId, order);
    });

    _deliveryTimers[orderId] = timer;
    debugPrint('[CART][DELIVERYLOG] ✅ Timer registered for orderId: $orderId (will post every 30 seconds)');
  }

  void _postDeliveryLog(String orderId, Map<String, dynamic> order) {
    if (!mounted) {
      debugPrint('[CART][DELIVERYLOG][POST] Widget disposed, skipping');
      return;
    }

    debugPrint('[CART][DELIVERYLOG][POST] ⏰ Posting log for orderId: $orderId at ${DateTime.now()}');

    // Use Future.microtask to ensure the async operation runs independently
    Future.microtask(() => _performPost(orderId));
  }

  Future<void> _performPost(String orderId) async {
    try {
      debugPrint('[CART][DELIVERYLOG][POST] 🔄 Starting _performPost for orderId: $orderId');

      Map<String, dynamic>? base = _deliveryBasePayload[orderId];

      if (base == null) {
        debugPrint('[CART][DELIVERYLOG][POST] Base is null, loading from SharedPreferences');
        try {
          final prefs = await SharedPreferences.getInstance();
          if (!mounted) {
            debugPrint('[CART][DELIVERYLOG][POST] Widget unmounted after prefs load');
            return;
          }

          base = {
            'logid': 0,
            'tenantid': int.tryParse(prefs.getString('deliverylog_${orderId}_tenantid') ?? '0') ?? 0,
            'partnerid': int.tryParse(prefs.getString('deliverylog_${orderId}_partnerid') ?? '0') ?? 0,
            'locationid': int.tryParse(prefs.getString('deliverylog_${orderId}_locationid') ?? '0') ?? 0,
            'orderheaderid': int.tryParse(prefs.getString('deliverylog_${orderId}_orderheaderid') ?? '0') ?? 0,
            'deliveryid': int.tryParse(prefs.getString('deliverylog_${orderId}_deliveryid') ?? '0') ?? 0,
            'userid': int.tryParse(prefs.getString('deliverylog_${orderId}_userid') ?? '0') ?? 0,
            'orderid': prefs.getString('deliverylog_${orderId}_orderid') ?? orderId,
            'orderstatus': prefs.getString('deliverylog_${orderId}_orderstatus') ?? 'active',
            'starttime': prefs.getString('deliverylog_${orderId}_starttime') ?? '', // Load starttime
          };
          debugPrint('[CART][DELIVERYLOG][POST] Base loaded from prefs: $base');
        } catch (e) {
          debugPrint('[CART][DELIVERYLOG][POST] Error loading base: $e');
          return;
        }
      }

      // At this point, base is guaranteed to be non-null (either from cache or created above)
      final basePayload = base; // Flow analysis ensures base is non-null here

      debugPrint('[CART][DELIVERYLOG][POST] Getting coordinates...');

      // CRITICAL: Get coordinates with retry logic - NEVER post with null or '0' coordinates
      final coords = await _getValidCoordinates().timeout(
        const Duration(seconds: 10), // Increased timeout to allow retries
        onTimeout: () {
          debugPrint('[CART][DELIVERYLOG][POST] ❌ Coordinate timeout after retries');
          return null;
        },
      );

      if (!mounted) {
        debugPrint('[CART][DELIVERYLOG][POST] Widget unmounted after coords');
        return;
      }

      // CRITICAL: Validate coordinates - NEVER post with null, '0', or invalid coordinates
      if (coords == null || coords.$1.isEmpty || coords.$2.isEmpty || 
          coords.$1 == '0' || coords.$2 == '0') {
        debugPrint('[CART][DELIVERYLOG][POST] ❌ SKIPPING POST: Invalid coordinates (lat=${coords?.$1 ?? 'null'}, lng=${coords?.$2 ?? 'null'})');
        debugPrint('[CART][DELIVERYLOG][POST] ⚠️ Will retry on next timer tick (30 seconds)');
        return; // Skip this post - don't send invalid coordinates
      }

      // Validate coordinate ranges
      final latDouble = double.tryParse(coords.$1) ?? 0.0;
      final lngDouble = double.tryParse(coords.$2) ?? 0.0;
      if (latDouble == 0 || lngDouble == 0 || 
          latDouble.abs() > 90 || lngDouble.abs() > 180) {
        debugPrint('[CART][DELIVERYLOG][POST] ❌ SKIPPING POST: Invalid coordinate ranges (lat=$latDouble, lng=$lngDouble)');
        debugPrint('[CART][DELIVERYLOG][POST] ⚠️ Will retry on next timer tick (30 seconds)');
        return; // Skip this post - don't send invalid coordinates
      }

      debugPrint('[CART][DELIVERYLOG][POST] ✅ Valid coordinates: lat=${coords.$1}, lng=${coords.$2}');

      // Cumulative KM is tracked exclusively by LiveTrackingService (high-frequency, every 3s).
      // Do not accumulate here to avoid race conditions with concurrent writers.

      final now = DateTime.now();
      final logdate = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}';

      // CRITICAL: Ensure starttime is always included in payload
      final starttimeValue = basePayload['starttime']?.toString() ?? '';
      if (starttimeValue.isEmpty) {
        debugPrint('[CART][DELIVERYLOG][POST] ⚠️ WARNING: starttime is empty in basePayload, using fallback');
      }

      // CRITICAL: Use validated coordinates - guaranteed to be non-null and valid at this point
      final payload = {
        ...basePayload,
        'logdate': logdate,
        'latitude': coords.$1, // Guaranteed non-null and valid
        'longitude': coords.$2, // Guaranteed non-null and valid
        'starttime': starttimeValue.isNotEmpty ? starttimeValue : '', // CRITICAL: Always include starttime
      };

      // Validate payload has all required fields
      final requiredFields = ['tenantid', 'partnerid', 'locationid', 'orderheaderid', 'deliveryid', 'userid', 'orderid', 'orderstatus', 'starttime'];
      final missingFields = requiredFields.where((field) => payload[field] == null || payload[field] == '').toList();
      if (missingFields.isNotEmpty) {
        debugPrint('[CART][DELIVERYLOG][POST] ⚠️ WARNING: Missing fields in payload: $missingFields');
      }

      final url = ApiConstants.mainRoute == 'live'
          ? ApiConstants.createDeliveryLogLive
          : ApiConstants.createDeliveryLogDev;

      debugPrint('[CART][DELIVERYLOG][POST] 📤 Sending to API: $url');
      debugPrint('[CART][DELIVERYLOG][POST] 📦 Payload: $payload');
      debugPrint('[CART][DELIVERYLOG][POST] ✅ starttime in payload: "${payload['starttime']}"');

      await _deliveryLogProvider
          .createDeliveryLog(url, payload)
          .timeout(
            const Duration(seconds: 8),
            onTimeout: () {
              debugPrint('[CART][DELIVERYLOG][POST] ⚠️ API timeout for orderId: $orderId');
              throw TimeoutException('API timeout', const Duration(seconds: 8));
            },
          );

      debugPrint('[CART][DELIVERYLOG][POST] ✅ SUCCESS for orderId: $orderId at ${DateTime.now()}');
    } catch (e, stackTrace) {
      debugPrint('[CART][DELIVERYLOG][POST] ❌ ERROR for orderId: $orderId - $e');
      debugPrint('[CART][DELIVERYLOG][POST] Stack trace: $stackTrace');
    }
  }

  Future<(String lat, String lng)?> _getValidCoordinates({int retryCount = 0}) async {
    const maxRetries = 3;
    
    try {
      final bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        debugPrint('[CART][COORDS] Location service disabled, trying last known position');
        final lastPos = await Geolocator.getLastKnownPosition();
        if (lastPos != null && lastPos.latitude != 0 && lastPos.longitude != 0) {
          final lat = lastPos.latitude.toString();
          final lng = lastPos.longitude.toString();
          debugPrint('[CART][COORDS] ✅ Using last known position: $lat, $lng');
          return (lat, lng);
        }
        // Retry if we haven't exceeded max retries
        if (retryCount < maxRetries) {
          await Future.delayed(const Duration(milliseconds: 500));
          return _getValidCoordinates(retryCount: retryCount + 1);
        }
        return null;
      }

      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
      }

      if (permission == LocationPermission.deniedForever ||
          permission == LocationPermission.denied) {
        debugPrint('[CART][COORDS] Permission denied, trying last known position');
        final lastPos = await Geolocator.getLastKnownPosition();
        if (lastPos != null && lastPos.latitude != 0 && lastPos.longitude != 0) {
          final lat = lastPos.latitude.toString();
          final lng = lastPos.longitude.toString();
          debugPrint('[CART][COORDS] ✅ Using last known position: $lat, $lng');
          return (lat, lng);
        }
        // Retry if we haven't exceeded max retries
        if (retryCount < maxRetries) {
          await Future.delayed(const Duration(milliseconds: 500));
          return _getValidCoordinates(retryCount: retryCount + 1);
        }
        return null;
      }

      Position? position;
      try {
        // Try to get current position with higher accuracy
        position = await Geolocator.getCurrentPosition(
          locationSettings: const LocationSettings(
            accuracy: LocationAccuracy.high, // Changed to high for better accuracy
            timeLimit: Duration(seconds: 8), // Increased timeout
          ),
        ).timeout(const Duration(seconds: 8));
      } catch (e) {
        debugPrint('[CART][COORDS] Timeout getting current position: $e, trying last known');
        position = await Geolocator.getLastKnownPosition();
      }

      if (position != null && position.latitude != 0 && position.longitude != 0) {
        final lat = position.latitude.toString();
        final lng = position.longitude.toString();
        
        // Validate coordinates are within valid GPS ranges
        final latDouble = double.tryParse(lat) ?? 0.0;
        final lngDouble = double.tryParse(lng) ?? 0.0;
        if (latDouble.abs() <= 90 && lngDouble.abs() <= 180) {
          try {
            final prefs = await SharedPreferences.getInstance();
            await prefs.setString('last_lat', lat);
            await prefs.setString('last_lng', lng);
          } catch (_) {}
          debugPrint('[CART][COORDS] ✅ Got valid coordinates: $lat, $lng');
          return (lat, lng);
        } else {
          debugPrint('[CART][COORDS] ⚠️ Invalid coordinate ranges: $lat, $lng');
        }
      }

      // Fallback to SharedPreferences cached coordinates
      try {
        final prefs = await SharedPreferences.getInstance();
        final lat = (prefs.getString('last_lat') ?? '').trim();
        final lng = (prefs.getString('last_lng') ?? '').trim();
        if (lat.isNotEmpty && lng.isNotEmpty && lat != '0' && lng != '0') {
          final latDouble = double.tryParse(lat) ?? 0.0;
          final lngDouble = double.tryParse(lng) ?? 0.0;
          if (latDouble != 0 && lngDouble != 0 && latDouble.abs() <= 90 && lngDouble.abs() <= 180) {
            debugPrint('[CART][COORDS] ✅ Using cached coordinates: $lat, $lng');
            return (lat, lng);
          }
        }
      } catch (_) {}
      
      // Retry if we haven't exceeded max retries
      if (retryCount < maxRetries) {
        debugPrint('[CART][COORDS] ⚠️ Retry ${retryCount + 1}/$maxRetries to get coordinates');
        await Future.delayed(const Duration(milliseconds: 500));
        return _getValidCoordinates(retryCount: retryCount + 1);
      }
      
      debugPrint('[CART][COORDS] ❌ Failed to get valid coordinates after $maxRetries retries');
      return null;
    } catch (e) {
      debugPrint('[CART][COORDS] ❌ Error getting coordinates: $e');
      // Retry if we haven't exceeded max retries
      if (retryCount < maxRetries) {
        await Future.delayed(const Duration(milliseconds: 500));
        return _getValidCoordinates(retryCount: retryCount + 1);
      }
      return null;
    }
  }

  void _stopDeliveryPosting(String orderId) {
    _deliveryTimers[orderId]?.cancel();
    _deliveryTimers.remove(orderId);
    _deliveryBasePayload.remove(orderId);
    debugPrint('[CART][DELIVERYLOG] Stopped timer for orderId: $orderId');
  }

  void _stopAllTimers() {
    for (final timer in _deliveryTimers.values) {
      timer.cancel();
    }
    _deliveryTimers.clear();
    _deliveryBasePayload.clear();
    debugPrint('[CART][DELIVERYLOG] Stopped all timers');
  }

  // Method to stop delivery posting for a specific order (called when order is completed)
  void stopDeliveryPostingForOrder(String orderId) {
    _stopDeliveryPosting(orderId);
    // Refresh the list to remove completed orders
    if (mounted) {
      _fetchActive();
    }
  }

  double _parseD(dynamic v) {
    if (v == null) return 0.0;
    if (v is num) return v.toDouble();
    return double.tryParse(v.toString()) ?? 0.0;
  }

  double _haversineKm(double lat1, double lon1, double lat2, double lon2) {
    const double R = 6371.0;
    final double dLat = _toRadians(lat2 - lat1);
    final double dLon = _toRadians(lon2 - lon1);
    final double a = math.sin(dLat / 2) * math.sin(dLat / 2) +
        math.cos(_toRadians(lat1)) *
            math.cos(_toRadians(lat2)) *
            math.sin(dLon / 2) *
            math.sin(dLon / 2);
    final double c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
    return R * c;
  }

  double _toRadians(double degrees) {
    return degrees * math.pi / 180.0;
  }

  String _distanceKmDisplay(Map<String, dynamic> m) {
    // Try API distance first
    final String apiKmsStr = (m['actualkms'] ?? m['distance'] ?? '0').toString();
    final double apiKms = double.tryParse(apiKmsStr) ?? 0.0;
    if (apiKms > 0) {
      return apiKms < 10 ? apiKmsStr : apiKms.toStringAsFixed(0);
    }

    // Try rider location to delivery location
    final double rLat = _parseD(m['riderslat']);
    final double rLon = _parseD(m['riderslon']);
    final double dLat = _parseD(m['droplat'] ?? m['deliverylat']);
    final double dLon = _parseD(m['droplon'] ?? m['deliverylong']);

    if (rLat != 0 && rLon != 0 && dLat != 0 && dLon != 0) {
      final double km = _haversineKm(rLat, rLon, dLat, dLon);
      return km.toStringAsFixed(km < 10 ? 1 : 0);
    }

    // Fallback: pickup to delivery
    final double pLat = _parseD(m['pickuplat']);
    final double pLon = _parseD(m['pickuplon']);
    if (pLat != 0 && pLon != 0 && dLat != 0 && dLon != 0) {
      final double km = _haversineKm(pLat, pLon, dLat, dLon);
      return km.toStringAsFixed(km < 10 ? 1 : 0);
    }

    return '0';
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      appBar: AppBar(
        backgroundColor: Colors.grey.shade200,
        elevation: 0,
        centerTitle: false,
        toolbarHeight: 70,
        title: Padding(
          padding: const EdgeInsets.only(top: 12),
          child: Text(
            "Active Deliveries",
            style: TextStyle(
              fontSize: 26,
              fontWeight: FontWeight.bold,
              fontFamily: FontConstants.fontFamily,
              color: Colors.black,
            ),
          ),
        ),
        bottom: const PreferredSize(
          preferredSize: Size.fromHeight(1),
          child: Divider(height: 1, color: Colors.grey),
        ),
      ),
      body: SafeArea(
        child: _activeDeliveries.isEmpty
      ? Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const SizedBox(height: 80),
                      Transform.translate(
                      offset: const Offset(0, -11),
                        child: Image.asset(
                          "assets/images/Nearle Bike.png",
                          errorBuilder: (c, e, s) => const Icon(
                            Icons.delivery_dining,
                            size: 120,
                            color: Colors.grey,
                          ),
                        ),
                      ),
                      const SizedBox(height: 16),
                      Transform.translate(
                      offset: const Offset(0, -11),
                        child: Text(
                        "No Active Deliveries",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 24,
                            fontFamily: FontConstants.fontFamily,
                          color: Colors.grey,
                          ),
                        ),
                      ),
                    ],
                  ),
                )
            : RefreshIndicator(
                onRefresh: _fetchActive,
                child: ListView.builder(
          padding: const EdgeInsets.only(bottom: 20),
                  itemCount: _activeDeliveries.length,
          itemBuilder: (context, index) {
                    final item = _activeDeliveries[index];
                    final customerName = (item['deliverycustomer'] ?? item['customer'] ?? 'Customer').toString();
                    final address = (item['deliveryaddress'] ?? item['address'] ?? 'Address not available').toString();
                    final storeName = (item['pickupcustomer'] ?? item['store'] ?? 'Store').toString();
                    final orderId = (item['orderid'] ?? '').toString();
                    final distance = _distanceKmDisplay(item);

            return Container(
              margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.1),
                    blurRadius: 6,
                    offset: const Offset(0, 3),
                  ),
                ],
              ),
              child: Padding(
                padding: const EdgeInsets.all(12),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // -------------------------------------------
                    // TOP CUSTOMER DETAILS
                    // -------------------------------------------
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Column(
                          children: [
                            Container(
                              width: 12,
                              height: 12,
                              decoration: const BoxDecoration(
                                color: Colors.orange,
                                shape: BoxShape.circle,
                              ),
                            ),
                            Container(
                              width: 2,
                              height: 30,
                              color: Colors.grey.shade300,
                            ),
                            Container(
                              width: 12,
                              height: 12,
                              decoration: const BoxDecoration(
                                color: Colors.green,
                                shape: BoxShape.circle,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(width: 10),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Transform.translate(
                                offset: const Offset(0, -3),
                                child: Text(
                                  customerName,
                                  style: TextStyle(
                                    fontWeight: FontWeight.w600,
                                    fontSize: 18,
                                    color: Colors.black,
                                    fontFamily: FontConstants.fontFamily,
                                  ),
                                ),
                              ),
                              const SizedBox(height: 8),
                              Transform.translate(
                                offset: const Offset(0, 8),
                                child: Text(
                                  address,
                                  style: TextStyle(
                                    fontSize: 18,
                                    color: Colors.black87,
                                    fontFamily: FontConstants.fontFamily,
                                  ),
                                ),
                              ),
                              const SizedBox(height: 8),
                              Text(
                                'Distance: $distance km',
                                style: TextStyle(
                                  fontSize: 16,
                                  color: Colors.blueGrey,
                                  fontFamily: FontConstants.fontFamily,
                                ),
                              ),
                            ],
                          ),
                        ),
                        InkWell(
                          onTap: () async {
                            // Just launch dialer; PiP is handled only from navigation screen
                            final phone =
                                (item['deliverycontactno'] ?? '').toString();
                            final bool success = await launchPhoneDialer(
                              phone.isNotEmpty ? phone : '9876543210',
                            );
                            if (!success && context.mounted) {
                              ScaffoldMessenger.of(context).showSnackBar(
                                const SnackBar(
                                  content: Text('Could not launch dialer'),
                                ),
                              );
                            }
                          },
                          child: Image.asset(
                            'assets/images/phone-call .png',
                            height: 27,
                            width: 27,
                            errorBuilder: (c, e, s) =>
                                const Icon(Icons.phone, size: 27, color: Colors.green),
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 8),
                    const Divider(),
                    const SizedBox(height: 8),
                    // -------------------------------------------
                    // STORE DETAILS
                    // -------------------------------------------
                    Row(
                      children: [
                        Image.asset(
                          'assets/images/shoppingbag.png',
                          height: 32,
                          width: 32,
                          errorBuilder: (c, e, s) => const Icon(
                            Icons.shopping_bag,
                            size: 32,
                            color: Colors.orange,
                          ),
                        ),
                        const SizedBox(width: 8),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Text(
                                    storeName,
                                style: TextStyle(
                                  fontWeight: FontWeight.w600,
                                  fontSize: 18,
                                  color: Colors.black,
                                  fontFamily: FontConstants.fontFamily,
                                ),
                                  ),
                                  InkWell(
                                    onTap: () async {
                                      _showMyOptionsSheet(
                                        context,
                                        item,
                                        null, // No parent state for cart page
                                      );
                                      // Refresh cart page after skip (order will no longer be active)
                                      if (mounted) {
                                        await Future.delayed(const Duration(seconds: 1));
                                        _fetchActive();
                                      }
                                    },
                                    child: Transform.translate(
                                      offset: const Offset(0, -5),
                                      child: Text(
                                        'Skip>>',
                                        style: TextStyle(
                                          fontSize: 20,
                                          fontWeight: FontWeight.bold,
                                          fontFamily: FontConstants.fontFamily,
                                          color: ColorConstants.primaryColor,
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                              Text(
                                "Order ID: #$orderId",
                                style: TextStyle(
                                  fontSize: 18,
                                  color: Colors.black54,
                                  fontFamily: FontConstants.fontFamily,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 15),
                    // -------------------------------------------
                    // SLIDER BUTTON
                    // -------------------------------------------
                    SliderButton(
                      properties: SliderButtonProperties(
                        height: 50,
                        buttonSize: 45,
                        width: MediaQuery.of(context).size.width - 56,
                        backgroundColor: ColorConstants.primaryColor,
                        dismissThresholds: 0.90,
                        action: () async {
                          await Future.delayed(const Duration(milliseconds: 400));
                          if (!context.mounted) return false;
                          
                          // Navigate to delivery map screen (same as deliveries page)
                          await Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => _DeliveryMapScreen(
                                delivery: item,
                                parentState: null, // No parent state for cart page
                              ),
                            ),
                          );
                          
                          // Refresh cart page when returning from map screen
                          // (in case delivery was completed/cancelled)
                          if (mounted) {
                            await Future.delayed(const Duration(milliseconds: 500));
                            _fetchActive();
                          }
                          
                          return false;
                        },
                        label: const Text(
                          'Slide to start Delivery',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.w500,
                            color: Colors.white,
                          ),
                        ),
                        icon: ClipOval(
                          child: Material(
                            color: Colors.white,
                            child: SizedBox(
                              width: 45,
                              height: 45,
                              child: Center(
                                child: Text(
                                  '${index + 1}', 
                                  style: const TextStyle(
                                    fontSize: 24,
                                    fontWeight: FontWeight.bold,
                                    color: Colors.black,
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            );
          },
                ),
        ),
      ),
);
  }
}
