// ignore_for_file: invalid_return_type_for_catch_error

part of 'deliveries.dart';

// ignore_for_file: unused_element_parameter
// Imports should be in deliveries.dart
// import 'dart:io';
// import 'package:image_picker/image_picker.dart';
// import 'package:shared_preferences/shared_preferences.dart';

// -------------------------------------------------------------------------
// DELIVERY BOTTOM SHEET (Delivered/Cancel with payment options)
// -------------------------------------------------------------------------
class _DeliveryBottomSheet extends StatefulWidget {
  final Map<String, dynamic> delivery;
  final _MyDeliveriesState? parentState;

  const _DeliveryBottomSheet({
    super.key,
    required this.delivery,
    this.parentState,
  });

  @override
  State<_DeliveryBottomSheet> createState() => _DeliveryBottomSheetState();
}

class _DeliveryBottomSheetState extends State<_DeliveryBottomSheet> {
  String selectedOption = '';
  bool isDeliveredSelected = true;
  bool showOptions = false;
  bool showSlider = true;
  bool isLoading = false;
  bool isProcessing = false; // Prevents any action until alert is dismissed
  DateTime? lastFailureTime; // Track last failure to prevent duplicate alerts

  final List<String> cancelOptions = [
    'Customer refused',
    'Not Reachable',
    'Switched Off',
    'Incorrect Location',
  ];

  final List<String> deliveredOptions = [
    'Pay Later',
    'Cash Payment',
    'QR Payment',
  ];

  @override
  void initState() {
    super.initState();
    _resetSheetState();
  }

  void _resetSheetState() {
    selectedOption = '';
    showOptions = false;
    showSlider = true;
    isDeliveredSelected = true;
    isProcessing = false;
    lastFailureTime = null;
  }

  bool _hasCollection() {
    final raw = widget.delivery['collectionamt'];
    if (raw == null) return false;
    if (raw is num) return raw > 0;
    final parsed = double.tryParse(raw.toString()) ?? 0.0;
    return parsed > 0;
  }

  double _getCollectionAmount() {
    final raw = widget.delivery['collectionamt'];
    if (raw == null) return 0.0;
    if (raw is num) return raw.toDouble();
    return double.tryParse(raw.toString()) ?? 0.0;
  }

  double _getDeliveryAmount() {
    final raw = widget.delivery['deliveryamt'];
    if (raw == null) return 0.0;
    if (raw is num) return raw.toDouble();
    return double.tryParse(raw.toString()) ?? 0.0;
  }

  @override
  Widget build(BuildContext context) {
    // For delivered orders with collection amount, show custom payment choices
    final options = isDeliveredSelected
        ? (_hasCollection()
            ? [
                'Cash (₹${_getCollectionAmount().toStringAsFixed(0)})',
                'UPI (₹${_getCollectionAmount().toStringAsFixed(0)})',
                'Not Collected',
              ]
            : deliveredOptions)
        : cancelOptions;
    final Color confirmColor = isDeliveredSelected
        ? ColorConstants.primaryColor
        : Colors.red;

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      child: SafeArea(
        top: false,
        child: SingleChildScrollView(
          physics: const BouncingScrollPhysics(),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                children: [
                  Expanded(
                    child: Text(
                      'Update Delivery Status',
                      style: TextStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                        fontFamily: FontConstants.fontFamily,
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      if (!showSlider && showOptions) {
                        setState(() => _resetSheetState());
                      } else {
                        Navigator.pop(context);
                      }
                    },
                    child: const Icon(
                      Icons.cancel,
                      color: Colors.red,
                      size: 30,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 10),
              const Divider(),
              if (!showOptions && showSlider) ...[
                _buildCustomerInfo(),
                const SizedBox(height: 10),
              ],
              if (showSlider)
                Slidable(
                  key: ValueKey(widget.delivery['deliveryid']),
                  startActionPane: ActionPane(
                    motion: const ScrollMotion(),
                    extentRatio: 0.9, // Allocate 90% of width for the 3 actions to prevent truncation
                    children: [
                      SlidableAction(
                        borderRadius: BorderRadius.circular(6),
                        onPressed: (_) {
                          setState(() {
                            isDeliveredSelected = true;
                            selectedOption = '';
                            showOptions = true;
                            showSlider = false;
                            isProcessing = false; // Reset when switching
                            lastFailureTime = null; // Clear failure cache
                          });
                        },
                        backgroundColor: Colors.green,
                        foregroundColor: Colors.white,
                        icon: Icons.check_circle,
                        label: 'Delivered',
                      ),
                      SlidableAction(
                        borderRadius: BorderRadius.circular(6),
                        onPressed: (_) {
                          setState(() {
                            isDeliveredSelected = false;
                            selectedOption = '';
                            showOptions = true;
                            showSlider = false;
                            isProcessing = false; // Reset when switching
                            lastFailureTime = null; // Clear failure cache
                          });
                        },
                        backgroundColor: Colors.red,
                        foregroundColor: Colors.white,
                        icon: Icons.cancel,
                        label: 'Cancelled',
                      ),
                      SlidableAction(
                        borderRadius: BorderRadius.circular(6),
                        onPressed: (c) async {
                          // Resolve parent state reliably
                          final resolvedParentState = widget.parentState ??
                              context
                                  .findAncestorStateOfType<_MyDeliveriesState>();

                          // Open skip sheet on TOP of this sheet (safer context usage)
                          // We await it so we know when it closes
                          await _showMyOptionsSheet(
                            context,
                            widget.delivery,
                            resolvedParentState,
                          );

                          // Close this update sheet after skip sheet is done
                          // Pass 'true' to indicate that an action *might* have been taken
                          // We could potentially return result from _showMyOptionsSheet but currently it returns void 
                          // The skip sheet handles the logic, so we can assume if we return here we are done.
                          // Actually, we should only return true if the skip sheet *actually* skipped.
                          // Since _showMyOptionsSheet returns Future<void>, we can't know for sure.
                          // BUT, since the user interacted with the skip sheet and we are closing this sheet,
                          // passing 'true' is safer to trigger a refresh check upstream.
                          if (mounted) {
                            Navigator.pop(context, true);
                          }
                        },
                        backgroundColor: Colors.orange,
                        foregroundColor: Colors.white,
                        icon: Icons.skip_next,
                        label: 'Skip',
                      ),
                    ],
                  ),
                  child: Container(
                    height: 65,
                    padding: const EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: Colors.grey.shade300,
                      borderRadius: BorderRadius.circular(6),
                    ),
                    child: const Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.swipe, color: Colors.black),
                        SizedBox(width: 10),
                        Text(
                          'Slide to Update Delivery',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                            color: Colors.black,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              const SizedBox(height: 5),
              if (showOptions) ...[
                ListView(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  children: [
                    ...options.map((option) {
                      final bool isSelected = option == selectedOption;
                      return GestureDetector(
                        onTap: () {
                          if (isLoading || isProcessing) return;
                          setState(() {
                            selectedOption = option;
                            lastFailureTime = null; // Clear on new selection
                          });
                        },
                        child: Container(
                          margin: const EdgeInsets.symmetric(vertical: 6),
                          padding: const EdgeInsets.symmetric(
                            vertical: 12,
                            horizontal: 16,
                          ),
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(12),
                            color: Colors.white,
                            border: Border.all(
                              color: isSelected
                                  ? confirmColor
                                  : Colors.grey.shade300,
                              width: isSelected ? 2 : 1,
                            ),
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Expanded(
                                child: Text(
                                  option,
                                  style: TextStyle(
                                    fontSize: 18,
                                    color: isSelected
                                        ? confirmColor
                                        : Colors.black,
                                    fontFamily: FontConstants.fontFamily,
                                    fontWeight: isSelected
                                        ? FontWeight.bold
                                        : FontWeight.normal,
                                  ),
                                ),
                              ),
                              Icon(
                                isSelected
                                    ? Icons.check_circle
                                    : Icons.radio_button_unchecked,
                                color: isSelected ? confirmColor : Colors.grey,
                              ),
                            ],
                          ),
                        ),
                      );
                    }),
                  ],
                ),
              ],
              const SizedBox(height: 15),
              // Slider enabled when a menu option is chosen.
              if (selectedOption.isNotEmpty)
                SliderButton(
                  properties: SliderButtonProperties(
                    height: 55,
                    buttonSize: 50,
                    width: MediaQuery.of(context).size.width - 40,
                    backgroundColor: confirmColor,
                    dismissThresholds: 0.90,

                    /// ACTION
                    action: () async {
                      // Prevent action if already processing
                      if (isLoading || isProcessing) {
                        debugPrint(
                          '[SLIDER] ⚠️ Already processing, ignoring slide action',
                        );
                        return false;
                      }
                      // _handleConfirm manages isLoading and isProcessing internally
                      await _handleConfirm();
                      return false; // required by slider_button_lite
                    },

                    /// LABEL
                    label: Text(
                      isDeliveredSelected
                          ? "Slide to Confirm Delivery"
                          : "Slide to Confirm Cancellation",
                      textAlign: TextAlign.left,
                      style: const TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                      ),
                    ),

                    /// SLIDER BUTTON (Icon or Loader)
                    icon: ClipOval(
                      child: Material(
                        color: Colors.white,
                        child: SizedBox(
                          width: 50,
                          height: 50,
                          child: Center(
                            child: isLoading
                                ? SizedBox(
                                    width: 24,
                                    height: 24,
                                    child: CircularProgressIndicator(
                                      strokeWidth: 3,
                                      valueColor: AlwaysStoppedAnimation<Color>(
                                        confirmColor,
                                      ),
                                    ),
                                  )
                                : Icon(
                                    isDeliveredSelected
                                        ? Icons.check
                                        : Icons.close,
                                    size: 28,
                                    color: confirmColor,
                                  ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildCustomerInfo() {
    final pickupCustomer = (widget.delivery['pickupcustomer'] ?? '')
        .toString()
        .trim();
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildInfoRow(
          'Name:',
          widget.delivery['deliverycustomer']?.toString() ?? 'Customer',
        ),
        const SizedBox(height: 10),
        if (pickupCustomer.isNotEmpty) ...[
          _buildInfoRow('Kitchen:', pickupCustomer),
          const SizedBox(height: 10),
        ],
        _buildInfoRow(
          'Address:',
          widget.delivery['deliveryaddress']?.toString() ??
              'Address not available',
          isExpanded: true,
        ),
        const SizedBox(height: 10),
        _buildInfoRow(
          'Order ID:',
          '#${widget.delivery['orderid']?.toString() ?? ''}',
        ),
      ],
    );
  }

  Widget _buildInfoRow(String title, String value, {bool isExpanded = false}) {
    final textWidget = Text(
      value,
      style: TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 18,
        fontFamily: FontConstants.fontFamily,
      ),
    );

    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '$title ',
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 18,
            fontFamily: FontConstants.fontFamily,
          ),
        ),
        const SizedBox(width: 10),
        isExpanded ? Expanded(child: textWidget) : Flexible(child: textWidget),
      ],
    );
  }

  bool _wasSkippedDelivery(
    Map<String, dynamic> delivery,
    _MyDeliveriesState? parentState,
  ) {
    final status =
        (delivery['orderstatus'] ??
                delivery['status'] ??
                delivery['orderStatus'] ??
                '')
            .toString()
            .toLowerCase();
    if (status == 'skipped') return true;
    if (parentState == null) return false;
    final key = parentState._getOrderKey(delivery);
    return parentState._skippedOrdersCache.containsKey(key);
  }

  Future<void> _handleConfirm() async {
    // CRITICAL: Prevent any re-entry during processing or alert display
    if (isLoading || isProcessing) {
      debugPrint(
        '[CONFIRM] ⚠️ Already processing or alert showing, ignoring tap',
      );
      return;
    }

    // Check if we recently had a failure (within last 4 seconds)
    // This prevents cached/duplicate alerts from showing
    if (lastFailureTime != null) {
      final timeSinceLastFailure = DateTime.now().difference(lastFailureTime!);
      if (timeSinceLastFailure.inSeconds < 4) {
        debugPrint(
          '[CONFIRM] ⚠️ Too soon after last failure (${timeSinceLastFailure.inSeconds}s), ignoring tap',
        );
        return;
      }
    }

    final d = widget.delivery;
    debugPrint('[CONFIRM] ===== DELIVERY INFO =====');
    debugPrint('[CONFIRM] deliveryid: ${d['deliveryid']}');
    debugPrint('[CONFIRM] orderid: ${d['orderid']}');
    debugPrint('[CONFIRM] orderstatus: ${d['orderstatus']}');

    final parentState =
        widget.parentState ??
        context.findAncestorStateOfType<_MyDeliveriesState>();
    final orderId = (d['orderid'] ?? '').toString();
    final deliveryId = (d['deliveryid'] ?? '').toString();

    final bool wasSkipped = _wasSkippedDelivery(d, parentState);

    if (parentState != null) {
      final key = parentState._getOrderKey(d);
      debugPrint('[CONFIRM] Generated key: $key');
      debugPrint(
        '[CONFIRM] Is in cache: ${parentState._skippedOrdersCache.containsKey(key)}',
      );
      debugPrint(
        '[CONFIRM] All cache keys: ${parentState._skippedOrdersCache.keys.toList()}',
      );
    }
    debugPrint('[CONFIRM] wasSkipped=$wasSkipped');
    debugPrint('[CONFIRM] ==========================');

    // Set BOTH flags to block all interactions
    if (mounted) {
      setState(() {
        isLoading = true;
        isProcessing = true;
      });
    }

    try {
      final dc = Get.put(DeliveriesController(), permanent: true);
      final int deliveryIdInt = int.tryParse('${d['deliveryid'] ?? 0}') ?? 0;
      final int orderHeaderId = int.tryParse('${d['orderheaderid'] ?? 0}') ?? 0;
      final int deliveryLocationId =
          int.tryParse('${d['deliverylocationid'] ?? 0}') ?? 0;

      bool apiSuccess = false;

      if (isDeliveredSelected) {
        // Delivery amount should come from API (deliveryamt), not from the
        // selected payment option text (Cash/UPI), to avoid conflicts with
        // collection amounts.
        double deliveryAmount = _getDeliveryAmount();

        // Fallback: if API did not send deliveryamt, keep old behavior of
        // parsing a numeric value from the selected option (if any).
        if (deliveryAmount == 0.0 && selectedOption.isNotEmpty) {
          final m = RegExp(r'[0-9]+(?:\.[0-9]+)?').firstMatch(selectedOption);
          if (m != null) {
            deliveryAmount = double.tryParse(m.group(0)!) ?? 0.0;
          }
        }

        // Collection amounts from API (if any)
        final double apiCollectionAmt = _getCollectionAmount();
        double collectionAmtToSend = 0.0;
        double collectedAmtToSend = 0.0;
        int collectionStatusToSend = 0; // 1 = cash, 2 = UPI, 3 = not collected

        if (apiCollectionAmt > 0) {
          collectionAmtToSend = apiCollectionAmt;
          final lower = selectedOption.toLowerCase();
          if (lower.startsWith('cash')) {
            collectedAmtToSend = apiCollectionAmt;
            collectionStatusToSend = 1; // Cash
          } else if (lower.startsWith('upi')) {
            collectedAmtToSend = apiCollectionAmt;
            collectionStatusToSend = 2; // UPI
          } else {
            collectedAmtToSend = 0.0;
            collectionStatusToSend = 3; // Not Collected
          }
        }

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

        final pickupLat = parseD(d['pickuplat'] ?? d['PickupLat'] ?? 0);
        final pickupLng = parseD(d['pickuplon'] ?? d['PickupLon'] ?? 0);
        final deliveryLat = parseD(
          d['droplat'] ?? d['DropLat'] ?? d['deliverylat'] ?? 0,
        );
        final deliveryLng = parseD(
          d['droplon'] ?? d['DropLon'] ?? d['deliverylong'] ?? 0,
        );

        // Start fetching location in background while user takes photo
        final locationFuture = Geolocator.getCurrentPosition(
            locationSettings: const LocationSettings(
              accuracy: LocationAccuracy.high,
              timeLimit: Duration(seconds: 5),
            ),
          ).then((p) => p).catchError((e) {
            debugPrint('[DELIVER] Error getting rider location: $e');
            return null;
          });

        debugPrint(
          '[DELIVER][CONFIRM] deliveryId=$deliveryIdInt orderHeaderId=$orderHeaderId deliveryLocationId=$deliveryLocationId deliveryAmount=$deliveryAmount notes="$selectedOption"',
        );

        // TRIGGER CAMERA - Proof of Delivery
        // We do this concurrently with location fetching to save time
        String? proofImageUrl;
        
          try {
            final ImagePicker picker = ImagePicker();
            // Optimize image: Resize to max 1024x1024 and 50% quality for faster upload
            final XFile? photo = await picker.pickImage(
              source: ImageSource.camera,
              imageQuality: 50,
              maxWidth: 1024,
              maxHeight: 1024,
            );

            if (photo == null) {
              // User cancelled camera, abort delivery confirmation
              if (mounted) {
                setState(() {
                  isLoading = false;
                  isProcessing = false;
                });
              }
              debugPrint('[CONFIRM] Camera cancelled by user');
              return;
            }

            // Upload Proof
            // By now, location fetching should be nearly done
            final prefs = await SharedPreferences.getInstance();
            final userId = prefs.getInt('userid') ?? 0;
            if (userId > 0) {
              proofImageUrl = await dc.uploadProofImage(
                File(photo.path),
                'delivered',
                userId,
                deliveryIdInt,
              );
            }
          } catch (e) {
            debugPrint('[CONFIRM] Camera/Upload error: $e');
          }

          // Now wait for location if it hasn't finished yet
          String riderLatStr = '0';
          String riderLngStr = '0';
          final position = await locationFuture;
          riderLatStr = position.latitude.toStringAsFixed(6);
          riderLngStr = position.longitude.toStringAsFixed(6);
        
          // Validate coordinates before API call
          final double riderLat = double.tryParse(riderLatStr) ?? 0.0;
          final double riderLng = double.tryParse(riderLngStr) ?? 0.0;
          final bool hasValidRiderLocation =
              riderLat != 0 &&
              riderLng != 0 &&
              riderLat.abs() <= 90 &&
              riderLng.abs() <= 180;
          final bool hasValidDeliveryLocation =
              deliveryLat != 0 &&
              deliveryLng != 0 &&
              deliveryLat.abs() <= 90 &&
              deliveryLng.abs() <= 180;

          if (!hasValidRiderLocation || !hasValidDeliveryLocation) {
            debugPrint(
              '[DELIVER][CONFIRM] ⚠️ Invalid coordinates - Rider: ($riderLat, $riderLng), Delivery: ($deliveryLat, $deliveryLng)',
            );
            if (mounted) {
              setState(() {
                isLoading = false;
              });
            }
            // Show error alert
            Get.snackbar(
              'Location Error',
              'Unable to get your location. Please ensure GPS is enabled and try again.',
              backgroundColor: Colors.red,
              colorText: Colors.white,
              duration: const Duration(seconds: 4),
              snackPosition: SnackPosition.TOP,
              isDismissible: true,
            );
            lastFailureTime = DateTime.now();
            await Future.delayed(const Duration(seconds: 4));
            if (mounted) {
              setState(() {
                isProcessing = false;
              });
            }
            return;
          }




          if (proofImageUrl == null) {
            if (mounted) {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(
                    content: Text('Failed to upload proof image. Please try again.')),
              );
              setState(() {
                isLoading = false;
                isProcessing = false;
              });
            }
            return;
          }
        

        apiSuccess = await dc.updateDeliveredStatus(
          deliveryId: deliveryIdInt,
          orderHeaderId: orderHeaderId,
          deliveryLocationId: deliveryLocationId,
          smsDelivery: 0,
          ridersLat: riderLatStr,
          ridersLng: riderLngStr,
          pickupLat: pickupLat.toStringAsFixed(6),
          pickupLng: pickupLng.toStringAsFixed(6),
          deliveryLat: deliveryLat.toStringAsFixed(6),
          deliveryLng: deliveryLng.toStringAsFixed(6),
          notes: selectedOption,
          deliveryAmount: deliveryAmount,
          collectionAmount: collectionAmtToSend,
          collectedAmount: collectedAmtToSend,
          collectionStatus: collectionStatusToSend,
          wasSkipped: wasSkipped,
          orderId: orderId, // ✅ Pass orderId for bonus points logic
          proofImage: proofImageUrl,
        );
        debugPrint('[DELIVER][CONFIRM] result=$apiSuccess');

        if (apiSuccess) {
          // On success, cache and clean up before navigating to done screen
          await _cacheDeliveredCancelled(
            deliveryId,
            orderId,
            isDelivered: true,
          );
          await _cleanupAfterCompletion(
            orderId,
            deliveryId,
            parentState,
            isCancelled: false,
          );
          if (!mounted) return;

          if (!mounted) return;

          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => DeliveriesDone(
                bonusPoints: dc.lastBonusPoints.value,
              ),
            ),
          );
          return;
        }
      } else {
        double parseD(dynamic v) {
          if (v == null) return 0.0;
          if (v is num) return v.toDouble();
          return double.tryParse(v.toString()) ?? 0.0;
        }

        final pickupLat = parseD(d['pickuplat'] ?? d['PickupLat'] ?? 0);
        final pickupLng = parseD(d['pickuplon'] ?? d['PickupLon'] ?? 0);

        String riderLatStr = '0';
        String riderLngStr = '0';
        try {
          final position = await Geolocator.getCurrentPosition(
            locationSettings: const LocationSettings(
              accuracy: LocationAccuracy.high,
              timeLimit: Duration(seconds: 5),
            ),
          );
          riderLatStr = position.latitude.toStringAsFixed(6);
          riderLngStr = position.longitude.toStringAsFixed(6);
        } catch (e) {
          debugPrint('[CANCEL] Error getting rider location: $e');
        }

        // Validate coordinates before API call
        final double riderLat = double.tryParse(riderLatStr) ?? 0.0;
        final double riderLng = double.tryParse(riderLngStr) ?? 0.0;
        final bool hasValidRiderLocation =
            riderLat != 0 &&
            riderLng != 0 &&
            riderLat.abs() <= 90 &&
            riderLng.abs() <= 180;

        // For cancellation, we need delivery location from the delivery data
        final double cancelDeliveryLat = parseD(
          d['droplat'] ?? d['DropLat'] ?? d['deliverylat'] ?? 0,
        );
        final double cancelDeliveryLng = parseD(
          d['droplon'] ?? d['DropLon'] ?? d['deliverylong'] ?? 0,
        );
        final bool hasValidDeliveryLocation =
            cancelDeliveryLat != 0 &&
            cancelDeliveryLng != 0 &&
            cancelDeliveryLat.abs() <= 90 &&
            cancelDeliveryLng.abs() <= 180;

        if (!hasValidRiderLocation || !hasValidDeliveryLocation) {
          debugPrint(
            '[CANCEL][CONFIRM] ⚠️ Invalid coordinates - Rider: ($riderLat, $riderLng), Delivery: ($cancelDeliveryLat, $cancelDeliveryLng)',
          );
          if (mounted) {
            setState(() {
              isLoading = false;
            });
          }
          // Show error alert
          Get.snackbar(
            'Location Error',
            'Unable to get your location. Please ensure GPS is enabled and try again.',
            backgroundColor: Colors.red,
            colorText: Colors.white,
            duration: const Duration(seconds: 4),
            snackPosition: SnackPosition.TOP,
            isDismissible: true,
          );
          lastFailureTime = DateTime.now();
          await Future.delayed(const Duration(seconds: 4));
          if (mounted) {
            setState(() {
              isProcessing = false;
            });
          }
          return;
        }

        apiSuccess = await dc.updateCancelledStatus(
          deliveryId: deliveryIdInt,
          orderHeaderId: orderHeaderId,
          ridersLat: riderLatStr,
          ridersLng: riderLngStr,
          pickupLat: pickupLat.toStringAsFixed(6),
          pickupLng: pickupLng.toStringAsFixed(6),
          deliveryLat: cancelDeliveryLat.toStringAsFixed(6),
          deliveryLng: cancelDeliveryLng.toStringAsFixed(6),
          notes: selectedOption,
          wasSkipped: wasSkipped,
        );
        debugPrint('[CANCEL][CONFIRM] result=$apiSuccess');

        if (apiSuccess) {
          // On success, cache and clean up before navigating to done screen
          await _cacheDeliveredCancelled(
            deliveryId,
            orderId,
            isDelivered: false,
          );
          await _cleanupAfterCompletion(
            orderId,
            deliveryId,
            parentState,
            isCancelled: true,
          );
          if (!mounted) return;

          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => const DeliveriesDone(isCancelled: true),
            ),
          );
          return;
        }
      }

      // If API failed, record the failure time to prevent duplicate alerts
      lastFailureTime = DateTime.now();
      debugPrint(
        '[CONFIRM] ⚠️ API failed at $lastFailureTime, waiting for alert to dismiss...',
      );

      // Stop the loading spinner immediately
      if (mounted) {
        setState(() {
          isLoading = false;
        });
      }

      // Wait for geofence/error snackbar to show and be dismissed
      // The controller's _checkGeofence already shows the snackbar, so we just wait
      // Don't show duplicate fallback error - controller already shows error message
      await Future.delayed(const Duration(seconds: 3));

      // Now re-enable the button
      if (mounted) {
        setState(() {
          isProcessing = false;
        });
        debugPrint('[CONFIRM] ✅ Button re-enabled after alert dismissal');
      }
    } catch (e) {
      debugPrint('[CONFIRM] ❌ Exception during confirm: $e');

      // Record failure time
      lastFailureTime = DateTime.now();

      // Stop loading spinner
      if (mounted) {
        setState(() {
          isLoading = false;
        });
      }

      // Wait for potential error alert to dismiss (4 seconds)
      await Future.delayed(const Duration(seconds: 4));

      // Re-enable button
      if (mounted) {
        setState(() {
          isProcessing = false;
        });
        debugPrint('[CONFIRM] ✅ Button re-enabled after exception handling');
      }
    }
  }

  Future<void> _cacheDeliveredCancelled(
    String deliveryId,
    String orderId, {
    required bool isDelivered,
  }) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final userId = prefs.getInt('userid') ?? prefs.getInt('userId') ?? 0;
      if (userId > 0) {
        final key = 'recently_delivered_cancelled_$userId';
        final deliveredCancelledJson = prefs.getString(key);
        List<dynamic> deliveredCancelledList = [];
        if (deliveredCancelledJson != null &&
            deliveredCancelledJson.isNotEmpty) {
          deliveredCancelledList = jsonDecode(deliveredCancelledJson);
        }

        deliveredCancelledList.add({
          'deliveryId': deliveryId,
          'orderId': orderId,
          'timestamp': DateTime.now().toIso8601String(),
          'type': isDelivered ? 'delivered' : 'cancelled',
        });

        await prefs.setString(key, jsonEncode(deliveredCancelledList));
        debugPrint(
          '[${isDelivered ? 'DELIVER' : 'CANCEL'}] ✅ Stored order in SharedPreferences: deliveryId=$deliveryId, orderId=$orderId',
        );
      }
    } catch (e) {
      debugPrint(
        '[${isDelivered ? 'DELIVER' : 'CANCEL'}] Error storing order in SharedPreferences: $e',
      );
    }
  }

  Future<void> _cleanupAfterCompletion(
    String orderId,
    String deliveryId,
    _MyDeliveriesState? parentState, {
    required bool isCancelled,
  }) async {
    final label = isCancelled ? 'CANCEL' : 'DELIVER';
    if (orderId.isEmpty) {
      debugPrint('[$label] ⚠️ Empty orderId, skipping cleanup');
      return;
    }

    if (parentState == null) {
      debugPrint(
        '[$label] ⚠️ parentState null; relying on cache cleanup via SharedPreferences',
      );
      // Try to find and stop timer from cart page if it exists
      // This is a workaround - ideally we'd pass a callback
      try {
        // The cart page will handle timer cleanup on next refresh
        debugPrint('[$label] Cart page will cleanup timer on next refresh');
      } catch (_) {}
      return;
    }

    parentState._stopDeliveryPosting(orderId);
    debugPrint('[$label] Stopped timer for completed delivery: $orderId');

    final deliveryKey = 'delivery_$deliveryId';
    final orderKey = 'order_$orderId';
    final actualKey = parentState._getOrderKey(widget.delivery);

    bool cacheUpdated = false;

    void removeKey(String key, String reason) {
      if (parentState._skippedOrdersCache.remove(key) != null) {
        parentState._skippedOrderTimestamps.remove(key);
        cacheUpdated = true;
        debugPrint('[$label] ✅ Removed from cache ($reason): $key');
      }
    }

    removeKey(deliveryKey, 'delivery key');
    removeKey(orderKey, 'order key');
    removeKey(actualKey, 'actual key');

    if (!cacheUpdated) {
      final keysToRemove = <String>[];
      // NOTE: We rely on the explicitly constructed keys above to remove entries.
      // Iterating via entry values isn't supported with Map<String, String> cache.
      // If items were not found by keys above, they remain until valid keys are used.

      for (final key in keysToRemove) {
        parentState._skippedOrdersCache.remove(key);
        parentState._skippedOrderTimestamps.remove(key);
        cacheUpdated = true;
        debugPrint('[$label] ✅ Removed from cache (matched by ID): $key');
      }
    }

    if (cacheUpdated) {
      await parentState._saveSkippedOrdersCache();
      debugPrint(
        '[$label] ✅ Cache saved. Remaining: ${parentState._skippedOrdersCache.length}',
      );
    } else {
      debugPrint(
        '[$label] ⚠️ Order not found in skipped cache (cleanup will run on next fetch)',
      );
    }
  }
}
