// ignore_for_file: unuse, unused_element, duplicate_ignore, unnecessary_cast
library;

import 'dart:async';
import 'dart:convert';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:lottie/lottie.dart' hide Marker;
import 'package:nearle/views/helpers/constants/Colorconstants.dart';
import 'package:nearle/views/helpers/constants/Font_constant.dart';
import 'package:slider_button_lite/feature/presentation/slider_button/slider.dart';
import 'package:slider_button_lite/feature/presentation/slider_button/slider_button_prop.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:nearle/providers/delivery/delivery_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:nearle/controllers/deliveries_controller.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:nearle/widget/Bottom_page.dart';
import 'package:circular_countdown_timer/circular_countdown_timer.dart';
import 'dart:math' as math;
import 'package:nearle/controllers/riderlog.dart';
import 'package:nearle/providers/deliverylog/deliverylog_provider.dart';
import 'package:nearle/views/helpers/constants/apiconstants.dart';
import 'dart:io' show Platform, File;
import 'package:image_picker/image_picker.dart';
import 'package:flutter/services.dart';
import 'package:floating/floating.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:http/http.dart' as http;
import 'package:scratcher/scratcher.dart';
import 'package:confetti/confetti.dart';

part 'card.dart';
part 'map.dart';
part 'nav.dart';
part 'pip.dart';
part 'sheet.dart';
part 'map_btn.dart';
part 'multi_map.dart';
part 'done.dart';
part 'skip_sheet.dart';
part '../Cart/cartpage.dart';

/// Helper function to launch phone dialer - works in both debug and release builds
/// In release builds, canLaunchUrl may fail due to R8/ProGuard, so we always try to launch
Future<bool> launchPhoneDialer(String phoneNumber) async {
  try {
    // Sanitize phone number: keep only digits and '+'
    final phone = phoneNumber.replaceAll(RegExp(r'[^\d+]'), '');

    if (phone.isEmpty) {
      debugPrint(
        '[PHONE] Empty phone number after sanitization, skipping dial',
      );
      return false;
    }

    final Uri uri = Uri(scheme: 'tel', path: phone);

    // Try canLaunchUrl first (works in debug, may fail in release)
    bool canLaunch = false;
    try {
      canLaunch = await canLaunchUrl(uri);
      debugPrint('[PHONE] canLaunchUrl result: $canLaunch');
    } catch (e) {
      debugPrint('[PHONE] canLaunchUrl check failed (common in release): $e');
      // Continue anyway - launch might still work
    }

    // Always attempt to launch, even if canLaunchUrl returned false
    // Using LaunchMode.platformDefault is often safer for system intents like dialing
    try {
      final launched = await launchUrl(uri, mode: LaunchMode.platformDefault);
      if (launched) {
        debugPrint('[PHONE] Successfully launched dialer for: $phone');
        return true;
      } else {
        debugPrint('[PHONE] launchUrl returned false for: $phone');
      }
    } catch (e) {
      debugPrint('[PHONE] Failed to launch dialer: $e');
    }
    return false;
  } catch (e) {
    debugPrint('[PHONE] Error in launchPhoneDialer: $e');
    return false;
  }
}

class MyDeliveries extends StatefulWidget {
  const MyDeliveries({super.key});

  @override
  State<MyDeliveries> createState() => _MyDeliveriesState();

  // ✅ Public static method to navigate to delivery map screen from outside (e.g., home page)
  static Future<void> navigateToDeliveryMap(
    BuildContext context,
    Map<String, dynamic> delivery,
  ) async {
    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => _RiderNavigationScreen(
          delivery: delivery,
          parentState: null, // No parent state when called from outside
        ),
      ),
    );
  }
}

class _MyDeliveriesState extends State<MyDeliveries>
    with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
  final DeliveryProvider _provider = DeliveryProvider();
  final CreateDeliveryLogProvider _deliveryLogProvider =
      CreateDeliveryLogProvider();
  List<Map<String, dynamic>> _picked = <Map<String, dynamic>>[];
  List<Map<String, dynamic>> _activeDeliveries =
      <Map<String, dynamic>>[]; // Track active deliveries for banner

  StreamSubscription<void>? _pollerSubscription;
  bool _fetching = false;
  Position? _currentLocation;
  final Map<String, Timer> _deliveryTimers = <String, Timer>{};
  final Map<String, Map<String, dynamic>> _deliveryBasePayload =
      <String, Map<String, dynamic>>{};
  // Preserve original step numbers so they don't change when deliveries are completed
  final Map<String, int> _preservedStepNumbers = <String, int>{};
  String? _activeDeliveryOrderId;
  // Cache for skipped orders
  final Map<String, String> _skippedOrdersCache = {};
  final Map<String, int> _skippedOrderTimestamps = {};

  Future<void> _saveSkippedOrdersCache() async {
    // Implementation can be empty if we rely on API now, 
    // or strictly local. For now, we'll keep it simple or empty 
    // to satisfy the interface expected by child widgets.
    // If child widgets call this, they expect it to exist.
  }

  @override
  bool get wantKeepAlive => true;

  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;
  }

  int _getStepNumber(Map<String, dynamic> order) {
    final dynamic raw = order['step'] ?? order['Step'];
    final int step = raw == null
        ? 0
        : (raw is num ? raw.toInt() : int.tryParse(raw.toString()) ?? 0);
    return step;
  }

  String _getOrderKey(Map<String, dynamic> order) {
    // Use deliveryId as primary key, fallback to orderId
    final deliveryId = (order['deliveryid'] ?? '').toString();
    final orderId = (order['orderid'] ?? '').toString();
    return deliveryId.isNotEmpty ? 'delivery_$deliveryId' : 'order_$orderId';
  }

  int _getPreservedOrCurrentStep(Map<String, dynamic> order) {
    final orderKey = _getOrderKey(order);
    // If we have a preserved step number, use it; otherwise use current API step
    if (_preservedStepNumbers.containsKey(orderKey)) {
      return _preservedStepNumbers[orderKey]!;
    }
    final currentStep = _getStepNumber(order);
    // Preserve the step number if it's valid (> 0)
    if (currentStep > 0) {
      _preservedStepNumbers[orderKey] = currentStep;
    }
    return currentStep;
  }

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

    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);
    }

    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';
  }

  double _calculateDistanceFromCurrent(Map<String, dynamic> order) {
    if (_currentLocation == null) return double.infinity;

    final double dropLat = _parseD(order['droplat'] ?? order['deliverylat']);
    final double dropLon = _parseD(order['droplon'] ?? order['deliverylong']);

    if (dropLat == 0 || dropLon == 0) return double.infinity;

    return _haversineKm(
      _currentLocation!.latitude,
      _currentLocation!.longitude,
      dropLat,
      dropLon,
    );
  }

  List<Map<String, dynamic>> _sortOrders(List<Map<String, dynamic>> orders) {
    if (orders.isEmpty) return orders;

    // Use preserved step numbers for sorting to maintain original order
    final ordersWithStep = orders
        .where((o) => _getPreservedOrCurrentStep(o) > 0)
        .toList();
    final ordersWithoutStep = orders
        .where((o) => _getPreservedOrCurrentStep(o) == 0)
        .toList();

    ordersWithStep.sort(
      (a, b) => _getPreservedOrCurrentStep(
        a,
      ).compareTo(_getPreservedOrCurrentStep(b)),
    );

    if (_currentLocation != null && ordersWithoutStep.isNotEmpty) {
      ordersWithoutStep.sort((a, b) {
        final distA = _calculateDistanceFromCurrent(a);
        final distB = _calculateDistanceFromCurrent(b);
        return distA.compareTo(distB);
      });
    }

    return [...ordersWithStep, ...ordersWithoutStep];
  }

  int _getDisplayStepNumber(List<Map<String, dynamic>> allOrders, int index) {
    final order = allOrders[index];
    // Use preserved step number if available, otherwise get current step
    final step = _getPreservedOrCurrentStep(order);

    if (step > 0) return step;

    // For orders without step numbers, calculate based on orders that have step numbers
    final ordersWithStep = allOrders
        .where((o) => _getPreservedOrCurrentStep(o) > 0)
        .length;
    return ordersWithStep + (index - ordersWithStep) + 1;
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    WakelockPlus.enable();
    
    // Listen for external refresh triggers
    try {
      final dc = Get.isRegistered<DeliveriesController>() 
          ? Get.find<DeliveriesController>() 
          : Get.put(DeliveriesController());
          
      ever(dc.refreshTrigger, (_) {
        if (mounted) {
           debugPrint('[MYDELIVERIES] External trigger -> Refreshing picked orders');
           _fetchPicked();
        }
      });
    } catch (_) {}
    
    // Run these in parallel
    _restoreActiveDelivery();
    _initializeLocation(); // Don't block
    _fetchPicked(); 
    _startPollingStream();
  }

  Future<void> _restoreActiveDelivery() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final savedActiveId = prefs.getString('active_delivery_order_id');
      if (savedActiveId != null && savedActiveId.isNotEmpty) {
        _activeDeliveryOrderId = savedActiveId;
        debugPrint(
          '[MYDELIVERIES] Restored active delivery orderId: $savedActiveId',
        );
      }
    } catch (e) {
      debugPrint('[MYDELIVERIES] Error restoring active delivery: $e');
    }
  }

  void _startPollingStream() {
    _pollerSubscription?.cancel();
    _pollerSubscription = Stream.periodic(const Duration(seconds: 3), (_) {})
        .asyncMap((_) async {
          if (mounted && !_fetching) {
            await _fetchPicked();
          }
        })
        .listen(
          (_) {}, // Success handler
          onError: (error) {
            // Handle errors gracefully without crashing
            debugPrint('[MYDELIVERIES][STREAM ERROR] $error');
          },
          cancelOnError: false, // Continue even on errors
        );
  }

  Future<void> _initializeLocation() async {
    try {
      // 1. Try Last Known Position (Instant & Preferred)
      try {
        final lastPos = await Geolocator.getLastKnownPosition();
        if (lastPos != null && mounted) {
          setState(() {
            _currentLocation = lastPos;
          });
          // If we have a cached location, don't block waiting for fresh GPS
          // We can let the background stream update it later
          return;
        }
      } catch (_) {}

      // 2. Try Current Position (Optimized)
      final bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) return;

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

      if (permission == LocationPermission.deniedForever ||
          permission == LocationPermission.denied) {
        return;
      }

      // Single attempt with balanced accuracy/timeout
      try {
        final position = await Geolocator.getCurrentPosition(
          locationSettings: const LocationSettings(
            accuracy: LocationAccuracy.high,
            timeLimit: Duration(seconds: 3),
          ),
        );

        if (mounted) {
          setState(() => _currentLocation = position);
        }
      } catch (_) {
        // Fallback to low accuracy if high fails
        try {
           final position = await Geolocator.getCurrentPosition(
            locationSettings: const LocationSettings(
              accuracy: LocationAccuracy.low,
              timeLimit: Duration(seconds: 2),
            ),
          );
          if (mounted) {
            setState(() => _currentLocation = position);
          }
        } catch (_) {}
      }
    } catch (e) {
      debugPrint('[MYDELIVERIES] Error initializing location: $e');
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _pollerSubscription?.cancel();
    for (final timer in _deliveryTimers.values) {
      timer.cancel();
    }
    _deliveryTimers.clear();
    _deliveryBasePayload.clear();
    // Persist current live deliveries state for other screens
    SharedPreferences.getInstance()
        .then((p) => p.setBool('has_live_deliveries', _picked.isNotEmpty))
        // ignore: body_might_complete_normally_catch_error
        .catchError((_) {});
    WakelockPlus.disable();
    super.dispose();
  }

  bool _shallowMapEquals(Map<String, dynamic> a, Map<String, dynamic> b) {
    if (identical(a, b)) return true;
    if (a.length != b.length) return false;
    for (final entry in a.entries) {
      if (b[entry.key] != entry.value) {
        return false;
      }
    }
    return true;
  }

  // Helper to check if two lists of orders are effectively equal
  // This prevents unnecessary rebuilds when polling
  bool _areOrdersEqual(
    List<Map<String, dynamic>> oldList,
    List<Map<String, dynamic>> newList,
  ) {
    if (oldList.length != newList.length) return false;

    for (int i = 0; i < oldList.length; i++) {
      final oldItem = oldList[i];
      final newItem = newList[i];

      // Compare critical fields that affect UI or logic
      if (oldItem['orderid'] != newItem['orderid']) return false;
      if (oldItem['orderstatus'] != newItem['orderstatus']) return false;
      if (oldItem['step'] != newItem['step']) return false;

      // Compare location data (important for map updates)
      if (oldItem['riderslat'] != newItem['riderslat']) return false;
      if (oldItem['riderslon'] != newItem['riderslon']) return false;
      if (oldItem['deliverylat'] != newItem['deliverylat']) return false;
      if (oldItem['deliverylong'] != newItem['deliverylong']) return false;

      // Compare notes/instructions if they might change
      if (oldItem['notes'] != newItem['notes']) return false;
    }

    return true;
  }

  // Manually mark skipped to trigger immediate refresh
  void markOrderAsSkipped(Map<String, dynamic> order, String reason) {
    if (!mounted) return;
    debugPrint('[MYDELIVERIES] Mark skipped -> Refreshing from API...');
    // We don't update local state manually anymore, we trust the API to return the 'skipped' status.
    // Just trigger a fetch.
    _fetchPicked();
  }

  // ✅ Check if there's an active delivery (blocks all actions)
  bool _hasActiveDelivery() {
    return _activeDeliveries.isNotEmpty;
  }

  // Previously showed a blocking dialog; now we just disable conflicting buttons in the UI.
  void _showActiveDeliveryBlockMessage() {}

  Future<void> startDelivery(Map<String, dynamic> item) async {
    if (!mounted) return;

    // ✅ BLOCK: Check if there's already an active delivery (and this isn't it)
    final currentOrderId = (item['orderid'] ?? '').toString();
    final activeOrderIds = _activeDeliveries
        .map((d) => (d['orderid'] ?? '').toString())
        .where((id) => id.isNotEmpty)
        .toSet();

    // Allow if this IS the active delivery, block if there's a different active delivery
    if (_hasActiveDelivery() && !activeOrderIds.contains(currentOrderId)) {
      // Just ignore taps on other cards when a different active delivery exists.
      return;
    }

    // Verify status is updated to ACTIVE before navigating
    final dc = Get.put(DeliveriesController());
    final dId = int.tryParse((item['deliveryid'] ?? 0).toString()) ?? 0;
    final ohId = int.tryParse((item['orderheaderid'] ?? 0).toString()) ?? 0;
    
    if (dId > 0 && ohId > 0) {
      // We don't block navigation on failure, but we try to update
      // This ensures 'starttime' is generated and saved
      await dc.updateActiveStatus(
        deliveryId: dId,
        orderHeaderId: ohId,
        orderId: (item['orderid'] ?? '').toString(),
      );
    }

    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) =>
            _RiderNavigationScreen(delivery: item, parentState: this),
      ),
    );
  }

  Future<void> resumeDelivery(Map<String, dynamic> item) async {
    // ✅ BLOCK: Check if there's already an active delivery (and this isn't it)
    final currentOrderId = (item['orderid'] ?? '').toString();
    final activeOrderIds = _activeDeliveries
        .map((d) => (d['orderid'] ?? '').toString())
        .where((id) => id.isNotEmpty)
        .toSet();

    // Allow if this IS the active delivery, block if there's a different active delivery
    if (_hasActiveDelivery() && !activeOrderIds.contains(currentOrderId)) {
      // Ignore resume taps when some other delivery is active.
      return;
    }

    // For now, resume behaves same as start (navigates to nav screen)
    // You can add specific resume logic here if needed (e.g. un-skip)
    await startDelivery(item);
  }

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

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

      // ✅ CRITICAL: Fetch from v3 API (picked orders) AND v2 API (all statuses) IN PARALLEL

      // Define V2 fetcher function
      Future<List<dynamic>> fetchV2() async {
        try {
          final now = DateTime.now();
          final today =
              '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';
          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(),
            },
          );

          final httpClient = http.Client();
          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;
              return data is List
                  ? data
                  : (data is Map && data['items'] is List
                        ? data['items'] as List
                        : []);
            }
          } finally {
            httpClient.close();
          }
        } catch (e) {
          debugPrint('[MYDELIVERIES] Error fetching from v2 API: $e');
        }
        return [];
      }

      // Execute in parallel
      final results = await Future.wait([
        _provider.getDeliveryQueuesPicked(live: true, userid: userId),
        fetchV2(),
      ]);

      final itemsV3 = results[0] as List<dynamic>;
      final itemsV2 = results[1] as List<dynamic>;

      // Merge v3 orders (picked) with v2 orders (all statuses)
      final Map<String, Map<String, dynamic>> mergedOrders = {};

      // First add v3 orders (picked)
      for (final order in itemsV3.whereType<Map<String, dynamic>>()) {
        final key = _getOrderKey(order);
        mergedOrders[key] = order;
      }

      // Then add/update with v2 orders - V2 STATUS TAKES PRECEDENCE
      for (final order in itemsV2.whereType<Map<String, dynamic>>()) {
        final key = _getOrderKey(order);
        final existing = mergedOrders[key];
        
        if (existing == null) {
          mergedOrders[key] = order;
        } else {
           // If it exists in V3 (picked) but V2 says something else, trust V2.
           // Especially for 'skipped', 'delivered', 'cancelled'.
           mergedOrders[key] = {
             ...existing,
             ...order, // Overwrite with V2 data
           };
        }
      }

      final items = mergedOrders.values.toList();
      debugPrint('[MYDELIVERIES] Merged items count: ${items.length}');
      
      final dedupedList = items; // Already deduped by key map

      // Preserve step numbers for existing orders
      for (final order in dedupedList) {
        final orderKey = _getOrderKey(order);
        final currentStep = _getStepNumber(order);
        if (currentStep > 0 && !_preservedStepNumbers.containsKey(orderKey)) {
          _preservedStepNumbers[orderKey] = currentStep;
        }
      }

      // Sort the list
      final sortedList = _sortOrders(dedupedList);

      // Filter out ACTIVE orders from top list (they go to banner)
      final listForTop = sortedList.where((o) {
        final status = (o['orderstatus']?.toString().toLowerCase() ?? '')
            .trim();
        return status != 'active';
      }).toList();

      final skippedInFinal = listForTop.where((m) {
        final status = (m['orderstatus']?.toString().toLowerCase() ?? '')
            .trim();
        return status == 'skipped';
      }).length;
      
      debugPrint(
        '[MYDELIVERIES] Final top list: ${listForTop.length} (skipped: $skippedInFinal)',
      );

      // Check if data has actually changed before rebuilding
      // This avoids unnecessary setState calls during polling
      final bool hasChanged = !_areOrdersEqual(_picked, listForTop);

      if (hasChanged) {
        if (mounted) {
          setState(() {
            _picked = listForTop;
          });
          debugPrint(
            '[MYDELIVERIES] 🔄 UI Updated: ${listForTop.length} orders ($skippedInFinal skipped)',
          );
        }
      } else {
         // No changes
      }

      // Get all order IDs from the current list
      final currentOrderIds = sortedList
          .map((o) => (o['orderid'] ?? '').toString())
          .where((id) => id.isNotEmpty)
          .toSet();

      // ✅ Find all ACTIVE deliveries and ensure timers are running
      final activeOrders = sortedList.where((o) {
        final status = (o['orderstatus']?.toString().toLowerCase() ?? '')
            .trim();
        return status == 'active';
      }).toList();

      debugPrint(
        '[MYDELIVERIES] Found ${activeOrders.length} active deliveries',
      );

      // ✅ CRITICAL: Only set has_live_deliveries to true if there are ACTIVE orders (status = "active")
      // Don't set it to true for "picked" or other statuses - only for "active"
      try {
        final hasActiveOrders = activeOrders.isNotEmpty;
        await prefs.setBool('has_live_deliveries', hasActiveOrders);
        debugPrint(
          '[MYDELIVERIES] Set has_live_deliveries: $hasActiveOrders (${activeOrders.length} active orders)',
        );

        // Clear active_delivery_order_id if no active deliveries
        if (!hasActiveOrders) {
          final activeOrderId = prefs.getString('active_delivery_order_id');
          if (activeOrderId != null && activeOrderId.isNotEmpty) {
            debugPrint(
              '[MYDELIVERIES] Clearing stale active_delivery_order_id: $activeOrderId (no active deliveries)',
            );
            await prefs.remove('active_delivery_order_id');
          }
        }
      } catch (_) {}

      // Update active deliveries list for banner display
      if (mounted) {
        setState(() {
          _activeDeliveries = activeOrders;
        });
      }

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

      // ✅ CRITICAL: Start timers ONLY for active deliveries that don't have one yet
      // This ensures logs are posted every 30 seconds WITHOUT restarting timers on every fetch
      for (final order in activeOrders) {
        final orderId = (order['orderid'] ?? '').toString();
        if (orderId.isEmpty) continue;

        // ✅ ONLY start timer if it doesn't already exist
        // This prevents restarting timers on every _fetchPicked() call (which happens frequently)
        if (!_deliveryTimers.containsKey(orderId)) {
          debugPrint(
            '[MYDELIVERIES] Active delivery: $orderId - Starting delivery log posting (timer not found)',
          );
          // ✅ RE-ENABLED: Delivery logs now posted from deliveries page with robust validation
          await _startDeliveryPosting(order);
        } else {
          debugPrint(
            '[MYDELIVERIES] Active delivery: $orderId - Timer already running, skipping restart',
          );
        }

        _activeDeliveryOrderId = orderId; // Track the active delivery

        // Persist active delivery ID so it survives app restarts
        try {
          final prefs = await SharedPreferences.getInstance();
          await prefs.setString('active_delivery_order_id', orderId);
        } catch (e) {
          debugPrint('[MYDELIVERIES] Error saving active delivery ID: $e');
        }
      }

      // ✅ Stop timers ONLY for deliveries that are no longer active or in the list
      final timersToStop = _deliveryTimers.keys
          .where(
            (id) =>
                !activeOrderIds.contains(id) || !currentOrderIds.contains(id),
          )
          .toList();

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

      debugPrint(
        '[MYDELIVERIES] Active timers: ${_deliveryTimers.keys.toList()}',
      );
      debugPrint(
        '[MYDELIVERIES] Active delivery orderId: $_activeDeliveryOrderId',
      );
    } catch (e) {
      debugPrint('[MYDELIVERIES] Error fetching picked orders: $e');
    } finally {
      _fetching = false;
    }
  }

  // ignore: unused_element
  Map<String, dynamic> _createBasePayload(Map<String, dynamic> it) {
    return <String, dynamic>{
      'logid': 0,
      'tenantid': it['tenantid'] ?? 0,
      'partnerid': it['partnerid'] ?? 0,
      'locationid': it['locationid'] ?? 0,
      'orderheaderid': it['orderheaderid'] ?? 0,
      'deliveryid': it['deliveryid'] ?? 0,
      'userid': it['userid'] ?? 0,
      'orderid': (it['orderid'] ?? '').toString(),
      'orderstatus': 'active',
    };
  }

  // Stop posting logs for a specific delivery
  void _stopDeliveryPosting(String orderId) {
    final timer = _deliveryTimers.remove(orderId);
    if (timer != null) {
      timer.cancel();
      debugPrint('[DELIVERYLOG] Stopped posting logs for orderId: $orderId');
    } else {
      debugPrint('[DELIVERYLOG] No timer to stop for orderId: $orderId');
    }
  }

  Future<(String lat, String lng)?> _getValidCoordinates({
    int retryCount = 0,
  }) async {
    const maxRetries = 3;

    try {
      final bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        debugPrint(
          '[DELIVERIES][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(
            '[DELIVERIES][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(
          '[DELIVERIES][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(
            '[DELIVERIES][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(
          '[DELIVERIES][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(
            '[DELIVERIES][COORDS] ✅ Got valid coordinates: $lat, $lng',
          );
          return (lat, lng);
        } else {
          debugPrint(
            '[DELIVERIES][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(
              '[DELIVERIES][COORDS] ✅ Using cached coordinates: $lat, $lng',
            );
            return (lat, lng);
          }
        }
      } catch (_) {}

      // Retry if we haven't exceeded max retries
      if (retryCount < maxRetries) {
        debugPrint(
          '[DELIVERIES][COORDS] ⚠️ Retry ${retryCount + 1}/$maxRetries to get coordinates',
        );
        await Future.delayed(const Duration(milliseconds: 500));
        return _getValidCoordinates(retryCount: retryCount + 1);
      }

      debugPrint(
        '[DELIVERIES][COORDS] ❌ Failed to get valid coordinates after $maxRetries retries',
      );
      return null;
    } catch (e) {
      debugPrint('[DELIVERIES][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;
    }
  }

  Future<void> _startDeliveryPosting(Map<String, dynamic> order) async {
    final orderId = (order['orderid'] ?? '').toString();
    if (orderId.isEmpty) {
      debugPrint(
        '[DELIVERIES][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(
        '[DELIVERIES][DELIVERYLOG] ⚠️ Timer already exists for $orderId, canceling old one',
      );
      _deliveryTimers[orderId]?.cancel();
      _deliveryTimers.remove(orderId);
    }

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

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

    // REMOVED: Do not reset cumulative distance here.
    // It is already reset in DeliveriesController.updateActiveStatus when the status actually changes.
    // Resetting here causes data loss if the app is restarted while a delivery is in progress.

    // START FOREGROUND SERVICE PROTECTION
    // Ensure the RiderLogController knows we are active so the Foreground Service stays alive
    // This protects THIS timer from being killed by the OS
    try {
      if (Get.isRegistered<RiderLogController>()) {
        final riderLog = Get.find<RiderLogController>();
        debugPrint(
          '[DELIVERIES][DELIVERYLOG] 🛡️ Activating Foreground Service via RiderLogController...',
        );
        // Force 30s interval to match delivery logging
        riderLog.startAutoCreateLoginLoop(seconds: 30);
      }
    } catch (e) {
      debugPrint('[DELIVERIES][DELIVERYLOG] ⚠️ Could not start Foreground Service: $e');
    }

    final deliveryId = (order['deliveryid'] ?? 0).toString();

    // 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();

      // Method 1: Get from SharedPreferences (saved when order became active)
      startTime = prefs.getString('delivery_starttime_$deliveryId') ?? '';
      if (startTime.isNotEmpty) {
        debugPrint(
          '[DELIVERIES][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(
            '[DELIVERIES][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(
            '[DELIVERIES][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(
          '[DELIVERIES][DELIVERYLOG] ⚠️ Using current time as starttime fallback: $startTime',
        );
      }
    } catch (e) {
      debugPrint('[DELIVERIES][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(
        '[DELIVERIES][DELIVERYLOG] ⚠️ Final fallback: starttime was empty, using: $startTime',
      );
    }

    debugPrint(
      '[DELIVERIES][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('[DELIVERIES][DELIVERYLOG] Error saving payload: $e');
    }

    // Post once immediately (don't await - let it run in background)
    _postDeliveryLog(orderId, order);
    debugPrint(
      '[DELIVERIES][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(
        '[DELIVERIES][DELIVERYLOG] ⏰ Timer tick for orderId: $orderId (30 seconds elapsed)',
      );
      _postDeliveryLog(orderId, order);
    });

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

  // Reset cumulative distance when order becomes active
  Future<void> _resetCumulativeDistance(String deliveryId) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.remove('delivery_tracking_${deliveryId}_lastLat');
      await prefs.remove('delivery_tracking_${deliveryId}_lastLng');
      await prefs.remove('delivery_tracking_${deliveryId}_cumulativeKm');
      debugPrint(
        '[DELIVERIES] 🧹 Reset cumulative distance tracking for deliveryId: $deliveryId',
      );
    } catch (e) {
      debugPrint('[DELIVERIES] Error resetting cumulative distance: $e');
    }
  }

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

    debugPrint(
      '[DELIVERIES][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(
        '[DELIVERIES][DELIVERYLOG][POST] 🔄 Starting _performPost for orderId: $orderId',
      );

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

      if (base == null) {
        debugPrint(
          '[DELIVERIES][DELIVERYLOG][POST] Base is null, loading from SharedPreferences',
        );
        try {
          final prefs = await SharedPreferences.getInstance();
          if (!mounted) {
            debugPrint(
              '[DELIVERIES][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(
            '[DELIVERIES][DELIVERYLOG][POST] Base loaded from prefs: $base',
          );
        } catch (e) {
          debugPrint('[DELIVERIES][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('[DELIVERIES][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(
            '[DELIVERIES][DELIVERYLOG][POST] ❌ Coordinate timeout after retries',
          );
          return null;
        },
      );

      if (!mounted) {
        debugPrint(
          '[DELIVERIES][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(
          '[DELIVERIES][DELIVERYLOG][POST] ❌ SKIPPING POST: Invalid coordinates (lat=${coords?.$1 ?? 'null'}, lng=${coords?.$2 ?? 'null'})',
        );
        debugPrint(
          '[DELIVERIES][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(
          '[DELIVERIES][DELIVERYLOG][POST] ❌ SKIPPING POST: Invalid coordinate ranges (lat=$latDouble, lng=$lngDouble)',
        );
        debugPrint(
          '[DELIVERIES][DELIVERYLOG][POST] ⚠️ Will retry on next timer tick (30 seconds)',
        );
        return; // Skip this post - don't send invalid coordinates
      }

      debugPrint(
        '[DELIVERIES][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(
          '[DELIVERIES][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(
          '[DELIVERIES][DELIVERYLOG][POST] ⚠️ WARNING: Missing fields in payload: $missingFields',
        );
      }

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

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

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

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

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

    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (didPop, result) async {
        if (didPop) return;

        if (_picked.isNotEmpty) {
          final confirm = await showDialog<bool>(
            context: context,
            builder: (ctx) => AlertDialog(
              title: const Text('Pending deliveries'),
              content: const Text(
                'Are you sure you want to close? There are deliveries pending.',
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.pop(ctx, false),
                  child: const Text('No'),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(ctx, true),
                  child: const Text('Yes'),
                ),
              ],
            ),
          );
          if (confirm == true && context.mounted) {
            Navigator.pop(context);
          }
        } else {
          Navigator.pop(context);
        }
      },
      child: SafeArea(
        child: Scaffold(
          backgroundColor: Colors.grey.shade200,
          appBar: AppBar(
            backgroundColor: Colors.grey.shade200,
            elevation: 0,
            centerTitle: false,
            toolbarHeight: 70, // Same as your summary page
            titleSpacing: 0,
            title: Padding(
              padding: const EdgeInsets.only(left: 16),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Transform.translate(
                    offset: Offset(0, 6),
                    child: Text(
                      "DELIVERIES",
                      style: TextStyle(
                        fontSize: FontConstants.xxxLarge(context).sp,
                        fontWeight: FontWeight.bold,
                        fontFamily: FontConstants.fontFamily,
                        color: Colors.black87,
                      ),
                    ),
                  ),

                  /// Map view row on right side
                  Transform.translate(
                    offset: Offset(-20, 2),
                    child: MapViewRow(
                      deliveries: _picked,
                      preservedStepNumbers: _preservedStepNumbers,
                    ),
                  ),
                ],
              ),
            ),

            /// Divider under AppBar (same as summary page)
            bottom: PreferredSize(
              preferredSize: Size.fromHeight(1),
              child: Divider(color: Colors.grey, height: 1),
            ),
          ),
          body: Stack(
            children: [
              _picked.isEmpty
                  ? Center(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const SizedBox(height: 80),
                          Transform.translate(
                            offset: Offset(0, -1.5),
                            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: Offset(0, -1.5),
                            child: Text(
                              "No Deliveries at the moment",
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                fontSize: FontConstants.xxxLarge(context),
                                fontFamily: FontConstants.fontFamily,
                                color: Colors.grey.shade500,
                              ),
                            ),
                          ),
                        ],
                      ),
                    )
                  : RefreshIndicator(
                      onRefresh: _fetchPicked,
                      child: ListView.builder(
                        padding: EdgeInsets.only(
                          left: 2,
                          right: 2,
                          top: 8,
                          bottom: _activeDeliveries.isNotEmpty
                              ? 80
                              : 8, // Add bottom padding for banner
                        ),
                        itemCount: _picked.length,
                        itemBuilder: (context, index) {
                          final item = _picked[index];
                          final int displayStep = _getDisplayStepNumber(
                            _picked,
                            index,
                          );
                          final String distanceStr = _distanceKmDisplay(item);
                          final String orderId = (item['orderid'] ?? '')
                              .toString();
                          final String status =
                              (item['orderstatus']?.toString().toLowerCase() ??
                                      '')
                                  .trim();

                          // Logic for enabling cards:
                          // 1. Skipped orders are ALWAYS enabled (so they can be un-skipped or completed)
                          // 2. The first non-skipped, non-cancelled, non-delivered order is enabled
                          // 3. All other orders are disabled

                          final bool isSkipped = status == 'skipped';
                          final bool isCancelledOrDelivered =
                              status == 'cancelled' || status == 'delivered';
                          final bool hasActive = _hasActiveDelivery();

                          // Don't show cancelled or delivered orders
                          if (isCancelledOrDelivered) {
                            return const SizedBox.shrink();
                          }

                          // Skipped orders: only enable when there is NO other active delivery
                          if (isSkipped && !isCancelledOrDelivered) {
                            return DeliveryCard(
                              key: ValueKey('delivery_$orderId'),
                              item: item,
                              displayStep: displayStep,
                              distanceStr: distanceStr,
                              enabled: !hasActive,
                              isSkipped: true,
                            );
                          }

                          // Find the first non-skipped order to enable
                          int firstEnabledIndex = -1;
                          for (int i = 0; i < _picked.length; i++) {
                            final orderStatus =
                                (_picked[i]['orderstatus']
                                            ?.toString()
                                            .toLowerCase() ??
                                        '')
                                    .trim();
                            if (orderStatus != 'skipped' &&
                                orderStatus != 'cancelled' &&
                                orderStatus != 'delivered') {
                              firstEnabledIndex = i;
                              break;
                            }
                          }

                          // Enable if this is the first available non-skipped order
                          // AND there is no active delivery running.
                          final bool enabled =
                              !hasActive &&
                              firstEnabledIndex >= 0 &&
                              index == firstEnabledIndex;

                          return DeliveryCard(
                            key: ValueKey('delivery_$orderId'),
                            item: item,
                            displayStep: displayStep,
                            distanceStr: distanceStr,
                            enabled: enabled,
                            isSkipped: false,
                          );
                        },
                      ),
                    ),
              // Bottom banner for active deliveries (Swiggy/Zomato style)
              if (_activeDeliveries.isNotEmpty)
                Positioned(
                  left: 0,
                  right: 0,
                  bottom: 0,
                  child: _ActiveDeliveryBanner(
                    activeDeliveries: _activeDeliveries,
                    onTap: (delivery) async {
                      await startDelivery(delivery);
                      // Refresh after returning from map screen
                      if (mounted) {
                        await Future.delayed(const Duration(milliseconds: 500));
                        _fetchPicked();
                      }
                    },
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

// -------------------------------------------------------------------------
// ACTIVE DELIVERY BANNER (Swiggy/Zomato style)
// -------------------------------------------------------------------------
class _ActiveDeliveryBanner extends StatelessWidget {
  final List<Map<String, dynamic>> activeDeliveries;
  final Function(Map<String, dynamic>) onTap;

  const _ActiveDeliveryBanner({
    required this.activeDeliveries,
    required this.onTap,
  });

  String _getDeliveryAddress(Map<String, dynamic> delivery) {
    final address =
        delivery['deliveryaddress'] ??
        delivery['DeliveryAddress'] ??
        delivery['address'] ??
        '';
    if (address.toString().length > 40) {
      return '${address.toString().substring(0, 40)}...';
    }
    return address.toString();
  }

  @override
  Widget build(BuildContext context) {
    if (activeDeliveries.isEmpty) {
      return const SizedBox.shrink();
    }

    // Show first active delivery (or show count if multiple)
    final delivery = activeDeliveries.first;
    final count = activeDeliveries.length;

    return Container(
      margin: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Colors.green,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.2),
            blurRadius: 8,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          onTap: () => onTap(delivery),
          borderRadius: BorderRadius.circular(12),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
            child: Row(
              children: [
                // Active indicator icon
                Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: Colors.white.withValues(alpha: 0.2),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: const Icon(
                    Icons.two_wheeler,
                    color: Colors.white,
                    size: 24,
                  ),
                ),
                const SizedBox(width: 12),
                // Delivery info
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Row(
                        children: [
                          Text(
                            count > 1
                                ? '$count Active Deliveries'
                                : 'Active Delivery',
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 19,
                              fontWeight: FontWeight.bold,
                              fontFamily: FontConstants.fontFamily,
                            ),
                          ),
                          if (count > 1) ...[
                            const SizedBox(width: 8),
                            Container(
                              padding: const EdgeInsets.symmetric(
                                horizontal: 8,
                                vertical: 2,
                              ),
                              decoration: BoxDecoration(
                                color: Colors.white.withValues(alpha: 0.3),
                                borderRadius: BorderRadius.circular(12),
                              ),
                              child: Text(
                                '$count',
                                style: TextStyle(
                                  color: Colors.white,
                                  fontSize: FontConstants.small(context).sp,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                          ],
                        ],
                      ),
                      const SizedBox(height: 4),
                      Text(
                        _getDeliveryAddress(delivery),
                        style: TextStyle(
                          color: Colors.white.withValues(alpha: 0.9),
                          fontSize: 17,
                          fontFamily: FontConstants.fontFamily,
                        ),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ],
                  ),
                ),
                // Arrow icon
                const Icon(
                  Icons.arrow_forward_ios,
                  color: Colors.white,
                  size: 20,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
