package com.aiotagro.cattletrade.business.controller;


import cn.dev33.satoken.annotation.SaCheckPermission;
import com.aiotagro.cattletrade.business.dto.DeliverListDto;
import com.aiotagro.cattletrade.business.dto.DeliveryAddDto;
import com.aiotagro.cattletrade.business.dto.DeliveryCreateDto;
import com.aiotagro.cattletrade.business.dto.DeliveryEditDto;
import com.aiotagro.cattletrade.business.dto.DeliveryQueryDto;
import com.aiotagro.cattletrade.business.dto.DeviceAssignDto;
import com.aiotagro.cattletrade.business.entity.Delivery;
import com.aiotagro.cattletrade.business.entity.DeliveryDevice;
import com.aiotagro.cattletrade.business.entity.JbqClient;
import com.aiotagro.cattletrade.business.entity.XqClient;
import com.aiotagro.cattletrade.business.service.IDeliveryService;
import com.aiotagro.cattletrade.business.service.IDeliveryDeviceService;
import com.aiotagro.cattletrade.business.service.IJbqClientService;
import com.aiotagro.cattletrade.business.service.IXqClientService;
import com.aiotagro.common.core.context.SecurityContextHolder;
import com.aiotagro.common.core.utils.SecurityUtil;
import com.aiotagro.common.core.constant.RoleConstants;
import com.aiotagro.common.core.web.domain.AjaxResult;
import com.aiotagro.common.core.web.domain.PageResultResponse;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 运送清单表 前端控制器
 *
 * @author admin
 * @since 2024-12-26
 */
@RestController
@RequestMapping("/delivery")
public class DeliveryController {

    @Autowired
    private IDeliveryService deliveryService;

    @Autowired
    private IDeliveryDeviceService deliveryDeviceService;
    
    @Autowired
    private IJbqClientService jbqClientService;
    
    @Autowired
    private IXqClientService xqClientService;
    
    @Autowired
    private com.aiotagro.cattletrade.business.mapper.IotDeviceDataMapper iotDeviceDataMapper;



    /**
     * 小程序运送清单-分页查询
     *
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:list")
    @PostMapping(value = "/pageQuery")
    public PageResultResponse<Delivery> pageQuery(@RequestBody DeliveryQueryDto dto) {
        return deliveryService.pageQuery(dto);
    }

    /**
     * 小程序运送清单-我要装车
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:add")
    @PostMapping(value = "/add")
    public AjaxResult add(@RequestBody DeliveryAddDto dto) {
        try{
           return deliveryService.addDelivery(dto);
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 运送清单-创建（PC端新增接口）
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:add")
    @PostMapping(value = "/create")
    public AjaxResult create(@Validated @RequestBody DeliveryCreateDto dto) {
        try{
           return deliveryService.createDelivery(dto);
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 装车订单-新增（PC端装车订单创建接口）
     * @param params
     * @return
     */
    @SaCheckPermission("delivery:add")
    @PostMapping(value = "/addDeliveryOrder")
    public AjaxResult addDeliveryOrder(@RequestBody Map<String, Object> params) {
        try {
            // 获取参数值
            String deliveryTitle = (String) params.get("deliveryTitle");
            Integer ratedQuantity = null;
            if (params.get("ratedQuantity") != null) {
                Object ratedQuantityObj = params.get("ratedQuantity");
                if (ratedQuantityObj instanceof Integer) {
                    ratedQuantity = (Integer) ratedQuantityObj;
                } else if (ratedQuantityObj instanceof String) {
                    try {
                        ratedQuantity = Integer.parseInt((String) ratedQuantityObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("装车数量格式不正确");
                    }
                }
            }
            
            String supplierId = (String) params.get("supplierId");
            
            Integer fundId = null;
            if (params.get("fundId") != null) {
                Object fundIdObj = params.get("fundId");
                if (fundIdObj instanceof Integer) {
                    fundId = (Integer) fundIdObj;
                } else if (fundIdObj instanceof String) {
                    try {
                        fundId = Integer.parseInt((String) fundIdObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("资金方ID格式不正确");
                    }
                }
            }
            
            Integer driverId = null;
            if (params.get("driverId") != null) {
                Object driverIdObj = params.get("driverId");
                if (driverIdObj instanceof Integer) {
                    driverId = (Integer) driverIdObj;
                } else if (driverIdObj instanceof String) {
                    try {
                        driverId = Integer.parseInt((String) driverIdObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("司机ID格式不正确");
                    }
                }
            }
            
            Integer buyerId = null;
            if (params.get("buyerId") != null) {
                Object buyerIdObj = params.get("buyerId");
                if (buyerIdObj instanceof Integer) {
                    buyerId = (Integer) buyerIdObj;
                } else if (buyerIdObj instanceof String) {
                    try {
                        buyerId = Integer.parseInt((String) buyerIdObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("采购商ID格式不正确");
                    }
                }
            }
            
            Double buyerPrice = null;
            if (params.get("buyerPrice") != null) {
                Object buyerPriceObj = params.get("buyerPrice");
                if (buyerPriceObj instanceof Double) {
                    buyerPrice = (Double) buyerPriceObj;
                } else if (buyerPriceObj instanceof String) {
                    try {
                        buyerPrice = Double.parseDouble((String) buyerPriceObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("采购价格格式不正确");
                    }
                }
            }
            
            Double salePrice = null;
            if (params.get("salePrice") != null) {
                Object salePriceObj = params.get("salePrice");
                if (salePriceObj instanceof Double) {
                    salePrice = (Double) salePriceObj;
                } else if (salePriceObj instanceof String) {
                    try {
                        salePrice = Double.parseDouble((String) salePriceObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("销售价格格式不正确");
                    }
                }
            }
            
            Double firmPrice = null;
            if (params.get("firmPrice") != null) {
                Object firmPriceObj = params.get("firmPrice");
                if (firmPriceObj instanceof Double) {
                    firmPrice = (Double) firmPriceObj;
                } else if (firmPriceObj instanceof String) {
                    try {
                        firmPrice = Double.parseDouble((String) firmPriceObj);
                    } catch (NumberFormatException e) {
                        return AjaxResult.error("约定单价格式不正确");
                    }
                }
            }
            String startLocation = (String) params.get("startLocation");
            
            String startLat = null;
            if (params.get("startLat") != null) {
                Object startLatObj = params.get("startLat");
                if (startLatObj instanceof String) {
                    startLat = (String) startLatObj;
                } else if (startLatObj instanceof Double) {
                    startLat = String.valueOf((Double) startLatObj);
                } else if (startLatObj instanceof Integer) {
                    startLat = String.valueOf((Integer) startLatObj);
                }
            }
            
            String startLon = null;
            if (params.get("startLon") != null) {
                Object startLonObj = params.get("startLon");
                if (startLonObj instanceof String) {
                    startLon = (String) startLonObj;
                } else if (startLonObj instanceof Double) {
                    startLon = String.valueOf((Double) startLonObj);
                } else if (startLonObj instanceof Integer) {
                    startLon = String.valueOf((Integer) startLonObj);
                }
            }
            
            String endLocation = (String) params.get("endLocation");
            
            String endLat = null;
            if (params.get("endLat") != null) {
                Object endLatObj = params.get("endLat");
                if (endLatObj instanceof String) {
                    endLat = (String) endLatObj;
                } else if (endLatObj instanceof Double) {
                    endLat = String.valueOf((Double) endLatObj);
                } else if (endLatObj instanceof Integer) {
                    endLat = String.valueOf((Integer) endLatObj);
                }
            }
            
            String endLon = null;
            if (params.get("endLon") != null) {
                Object endLonObj = params.get("endLon");
                if (endLonObj instanceof String) {
                    endLon = (String) endLonObj;
                } else if (endLonObj instanceof Double) {
                    endLon = String.valueOf((Double) endLonObj);
                } else if (endLonObj instanceof Integer) {
                    endLon = String.valueOf((Integer) endLonObj);
                }
            }

            // 参数验证
            if (deliveryTitle == null || deliveryTitle.trim().isEmpty()) {
                return AjaxResult.error("订单标题不能为空");
            }
            if (ratedQuantity == null || ratedQuantity <= 0) {
                return AjaxResult.error("装车数量必须大于0");
            }
            if (startLocation == null || startLocation.trim().isEmpty()) {
                return AjaxResult.error("起始地不能为空");
            }
            if (endLocation == null || endLocation.trim().isEmpty()) {
                return AjaxResult.error("目的地不能为空");
            }

            // 获取当前登录用户
            Integer userId = SecurityUtil.getCurrentUserId();
            String userName = SecurityContextHolder.getUserName(); // 使用SecurityContextHolder获取用户名
            
            // 生成运输单号
            LocalDateTime now = LocalDateTime.now();
            String deliveryNumber = "ZC" + now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            
            // 创建装车订单
            Delivery delivery = new Delivery();
            delivery.setDeliveryNumber(deliveryNumber);
            delivery.setDeliveryTitle(deliveryTitle);
            delivery.setRatedQuantity(ratedQuantity);
            delivery.setSupplierId(supplierId);
            delivery.setFundId(fundId);
            delivery.setDriverId(driverId);
            delivery.setBuyerId(buyerId);
            delivery.setBuyerPrice(buyerPrice);
            delivery.setSalePrice(salePrice);
            delivery.setFirmPrice(firmPrice);
            delivery.setStartLocation(startLocation);
            delivery.setStartLat(startLat);
            delivery.setStartLon(startLon);
            delivery.setEndLocation(endLocation);
            delivery.setEndLat(endLat);
            delivery.setEndLon(endLon);
            delivery.setStatus(1); // 待装车
            delivery.setCreatedBy(userId);
            delivery.setCreateByName(userName);
            delivery.setCreateTime(new Date());
            
            // 保存装车订单
            boolean saved = deliveryService.save(delivery);
            if (!saved) {
                return AjaxResult.error("创建装车订单失败");
            }
            
            return AjaxResult.success("装车订单创建成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("创建装车订单失败：" + e.getMessage());
        }
    }

    /**
     * 运送清单-编辑（PC端编辑接口）
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:edit")
    @PostMapping(value = "/updateDeliveryInfo")
    public AjaxResult updateDeliveryInfo(@Validated @RequestBody DeliveryEditDto dto) {
        try{
           return deliveryService.updateDeliveryInfo(dto);
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 小程序运送清单-查询详情
     * @param id
     * @return
     */
    @SaCheckPermission("delivery:view")
    @GetMapping(value = "/view")
    public AjaxResult view(@RequestParam Integer id) {
        return deliveryService.viewDelivery(id);
    }


    /**
     * 小程序运送清单-核验提交
     * @param delivery
     * @return
     */
    @SaCheckPermission("delivery:check")
    @PostMapping(value = "/submitCheck")
    public AjaxResult submitCheck(@RequestBody Delivery delivery) {
        try{
            //查询当前的登录用户，即核验人
            delivery.setCheckBy(SecurityUtil.getCurrentUserId());
            delivery.setCheckTime(new Date());
            delivery.setCheckByName(SecurityUtil.getUserName());
            boolean b = deliveryService.updateById(delivery);
            if(b){
                return AjaxResult.success("核验提交成功！");
            }else{
                return AjaxResult.error("核验提交失败！");
            }
        }catch (Exception e){
            return AjaxResult.error("核验提交失败！");
        }
    }

    /**
     * 后台系统运送清单-分页查询
     *
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:list")
    @PostMapping(value = "/pageQueryList")
    public PageResultResponse<Delivery> pageQueryList(@RequestBody DeliveryQueryDto dto) {
        return deliveryService.pageQuery(dto);
    }

    /**
     * 后台系统运送清单-分页查询（别名）
     *
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:list")
    @PostMapping(value = "/pageDeliveryOrderList")
    public PageResultResponse<Delivery> pageDeliveryOrderList(@RequestBody DeliverListDto dto) {
        return deliveryService.pageQueryListLog(dto);
    }

    /**
     * 后台运单详情
     */
    @SaCheckPermission("delivery:view")
    @GetMapping("/detail")
    public AjaxResult detail(@RequestParam Integer id) {
        return deliveryService.detail(id);
    }

    /**
     * 查看运送订单详情（别名）
     */
    @SaCheckPermission("delivery:view")
    @GetMapping("/viewDeliveryOrder")
    public AjaxResult viewDeliveryOrder(@RequestParam Integer deliveryId) {
        return deliveryService.detail(deliveryId);
    }

    /**
     * 测试司机信息查询
     */
    @GetMapping("/testDriverQuery/{deliveryId}")
    public AjaxResult testDriverQuery(@PathVariable("deliveryId") Integer deliveryId) {
        try {
            AjaxResult result = deliveryService.detail(deliveryId);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("测试失败: " + e.getMessage());
        }
    }

    /**
     * 调试用户信息接口
     */
    @GetMapping("/debugUserInfo")
    public AjaxResult debugUserInfo() {
        try {
            Map<String, Object> debugInfo = new HashMap<>();
            
            // 获取当前用户信息
            Integer userId = SecurityUtil.getCurrentUserId();
            String userName = SecurityUtil.getUserName();
            String userMobile = SecurityUtil.getUserMobile();
            Integer roleId = SecurityUtil.getRoleId();
            boolean isSuperAdmin = SecurityUtil.isSuperAdmin();
            
            debugInfo.put("userId", userId);
            debugInfo.put("userName", userName);
            debugInfo.put("userMobile", userMobile);
            debugInfo.put("roleId", roleId);
            debugInfo.put("isSuperAdmin", isSuperAdmin);
            debugInfo.put("superAdminRoleId", RoleConstants.SUPER_ADMIN_ROLE_ID);
            
            
            return AjaxResult.success("调试信息获取成功", debugInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("调试失败: " + e.getMessage());
        }
    }

    /**
     * 分配设备（支持智能耳标和智能项圈）
     * @param dto
     * @return
     */
    @SaCheckPermission("delivery:assign")
    @PostMapping(value = "/arrangeJbq")
    public AjaxResult arrangeJbq(@RequestBody DeviceAssignDto dto) {
        try {
            if (dto.getDeviceIds() == null || dto.getDeviceIds().isEmpty()) {
                return AjaxResult.error("请选择要分配的设备");
            }
            
            // 按设备类型分组
            Map<Integer, List<DeviceAssignDto.DeviceInfo>> deviceGroups = dto.getDeviceIds().stream()
                .collect(Collectors.groupingBy(DeviceAssignDto.DeviceInfo::getDeviceTypeId));
            
            // 处理每种设备类型
            for (Map.Entry<Integer, List<DeviceAssignDto.DeviceInfo>> entry : deviceGroups.entrySet()) {
                Integer deviceType = entry.getKey();
                List<DeviceAssignDto.DeviceInfo> devices = entry.getValue();
                
                // 先删除该运单的现有设备分配（按设备类型）
                deliveryDeviceService.lambdaUpdate()
                    .eq(DeliveryDevice::getDeliveryId, dto.getDeliveryId())
                    .eq(DeliveryDevice::getDeviceType, deviceType)
                    .remove();
                
                // 添加新的设备分配
                for (DeviceAssignDto.DeviceInfo deviceInfo : devices) {
                    DeliveryDevice deliveryDevice = new DeliveryDevice();
                    deliveryDevice.setDeliveryId(dto.getDeliveryId());
                    deliveryDevice.setDeviceId(deviceInfo.getDeviceId());
                    deliveryDevice.setDeviceType(deviceType);
                    deliveryDeviceService.save(deliveryDevice);
                    
                    // 更新设备的运单号和车牌号
                    updateDeviceDeliveryInfo(deviceInfo.getDeviceId(), deviceType, dto.getDeliveryId(), dto.getLicensePlate());
                }
            }
            
            return AjaxResult.success("设备分配成功！");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("设备分配失败：" + e.getMessage());
        }
    }
    
    /**
     * 更新设备的运单号和车牌号
     */
    private void updateDeviceDeliveryInfo(String deviceId, Integer deviceType, Integer deliveryId, String licensePlate) {
        try {
            // 获取运单号
            Delivery delivery = deliveryService.getById(deliveryId);
            String deliveryNumber = delivery != null ? delivery.getDeliveryNumber() : "";
            
            if (deviceType == 2) {
                // 更新智能耳标
                LambdaUpdateWrapper<JbqClient> jbqUpdateWrapper = new LambdaUpdateWrapper<>();
                jbqUpdateWrapper.eq(JbqClient::getDeviceId, deviceId);
                jbqUpdateWrapper.set(JbqClient::getDeliveryNumber, deliveryNumber);
                jbqUpdateWrapper.set(JbqClient::getLicensePlate, licensePlate);
                jbqClientService.update(jbqUpdateWrapper);
            } else if (deviceType == 3) {
                // 更新智能项圈 - 兼容deviceId和sn两种字段
                LambdaUpdateWrapper<XqClient> xqUpdateWrapper = new LambdaUpdateWrapper<>();
                xqUpdateWrapper.and(w -> w.eq(XqClient::getDeviceId, deviceId)
                                          .or()
                                          .eq(XqClient::getSn, Long.parseLong(deviceId)));
                xqUpdateWrapper.set(XqClient::getDeliveryId, deliveryId);
                xqUpdateWrapper.set(XqClient::getDeliveryNumber, deliveryNumber);
                xqUpdateWrapper.set(XqClient::getLicensePlate, licensePlate);
                xqClientService.update(xqUpdateWrapper);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 修改运送清单状态
     * 状态值：1-准备中，2-运输中，3-已结束
     */
    @SaCheckPermission("delivery:edit")
    @PostMapping("/updateStatus")
    public AjaxResult updateStatus(@RequestBody Map<String, Object> params) {
        try {
            Integer id = (Integer) params.get("id");
            Integer status = (Integer) params.get("status");
            
            
            if (id == null || status == null) {
                return AjaxResult.error("运单ID和状态不能为空");
            }
            
            if (status < 1 || status > 3) {
                return AjaxResult.error("状态值无效，只能为1（准备中）、2（运输中）、3（已结束）");
            }
            
            // 查询运单是否存在
            Delivery existDelivery = deliveryService.getById(id);
            if (existDelivery == null) {
                return AjaxResult.error("运单不存在");
            }
            
            
            Delivery delivery = new Delivery();
            delivery.setId(id);
            delivery.setStatus(status);
            
            boolean success = deliveryService.updateById(delivery);
            
            if (success) {
                String statusText = status == 1 ? "准备中" : (status == 2 ? "运输中" : "已结束");
                return AjaxResult.success("状态更新成功");
            } else {
                return AjaxResult.error("状态更新失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("状态更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除装车订单（物理删除）
     * 删除订单时同时清空关联设备的delivery_id和weight
     */
    @SaCheckPermission("delivery:delete")
    @GetMapping("/deleteDelivery")
    public AjaxResult deleteDelivery(@RequestParam Integer id) {
        try {
            if (id == null) {
                return AjaxResult.error("订单ID不能为空");
            }
            
            
            // 查询订单是否存在
            Delivery delivery = deliveryService.getById(id);
            if (delivery == null) {
                return AjaxResult.error("订单不存在");
            }
            
            // 权限检查：只有创建者或超级管理员可以删除
            Integer userId = SecurityUtil.getCurrentUserId();
            if (!SecurityUtil.isSuperAdmin() && !userId.equals(delivery.getCreatedBy())) {
                return AjaxResult.error("无权限删除此订单");
            }
            
            // 1. 先清空关联设备的delivery_id和weight
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.aiotagro.cattletrade.business.entity.IotDeviceData> queryWrapper = 
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
            queryWrapper.eq("delivery_id", id);
            List<com.aiotagro.cattletrade.business.entity.IotDeviceData> devices = iotDeviceDataMapper.selectList(queryWrapper);
            
            int updatedCount = 0;
            for (com.aiotagro.cattletrade.business.entity.IotDeviceData device : devices) {
                device.setDeliveryId(null);
                device.setWeight(null);
                device.setCarNumber(null);
                iotDeviceDataMapper.updateById(device);
                updatedCount++;
            }
            
            
            // 2. 删除订单记录
            boolean deleted = deliveryService.removeById(id);
            
            if (deleted) {
                return AjaxResult.success("订单删除成功，已清空 " + updatedCount + " 个设备的绑定信息");
            } else {
                return AjaxResult.error("订单删除失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 逻辑删除运送清单
     * 只标记为已删除，不清空设备绑定关系，保留历史记录
     */
    @SaCheckPermission("delivery:delete")
    @PostMapping("/deleteLogic")
    public AjaxResult deleteLogic(@RequestParam Integer id) {
        try {
            if (id == null) {
                return AjaxResult.error("运单ID不能为空");
            }
            
            
            // 查询订单是否存在
            Delivery delivery = deliveryService.getById(id);
            if (delivery == null) {
                return AjaxResult.error("运单不存在");
            }
            
            // 权限检查：只有创建者或超级管理员可以删除
            Integer userId = SecurityUtil.getCurrentUserId();
            if (!SecurityUtil.isSuperAdmin() && !userId.equals(delivery.getCreatedBy())) {
                return AjaxResult.error("无权限删除此运单");
            }
            
            
            // 使用 MyBatis-Plus 的逻辑删除功能
            boolean deleted = deliveryService.removeById(id);
            
            if (deleted) {
                return AjaxResult.success("运单删除成功");
            } else {
                return AjaxResult.error("运单删除失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除运单失败：" + e.getMessage());
        }
    }
    
    /**
     * 打包下载运送清单文件（图片、视频、信息）
     * 包含所有相关的照片、视频和详细信息
     */
    @SaCheckPermission("delivery:view")
    @GetMapping("/downloadPackage")
    public void downloadPackage(@RequestParam Integer id, HttpServletResponse response) {
        
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ZipOutputStream zipOut = null;
        
        try {
            if (id == null) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("运单ID不能为空");
                return;
            }
            
            // 查询运单详情
            Delivery delivery = deliveryService.getById(id);
            if (delivery == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("运单不存在");
                return;
            }
            
            
            zipOut = new ZipOutputStream(byteArrayOutputStream);
            zipOut.setLevel(9); // 设置压缩级别
            
            // 1. 创建信息文本文件
            addDeliveryInfoToZip(zipOut, delivery);
            
            // 2. 下载并添加所有照片
            int photoCount = 0;
            photoCount += addFileToZip(zipOut, delivery.getQuarantineTickeyUrl(), "照片/检疫票.jpg");
            photoCount += addFileToZip(zipOut, delivery.getPoundListImg(), "照片/纸质磅单.jpg");
            photoCount += addFileToZip(zipOut, delivery.getEmptyVehicleFrontPhoto(), "照片/空车过磅车头照片.jpg");
            photoCount += addFileToZip(zipOut, delivery.getLoadedVehicleFrontPhoto(), "照片/装车过磅车头照片.jpg");
            photoCount += addFileToZip(zipOut, delivery.getLoadedVehicleWeightPhoto(), "照片/装车过磅磅单.jpg");
            photoCount += addFileToZip(zipOut, delivery.getCarFrontPhoto(), "照片/车头照片.jpg");
            photoCount += addFileToZip(zipOut, delivery.getCarBehindPhoto(), "照片/车尾照片.jpg");
            photoCount += addFileToZip(zipOut, delivery.getDriverIdCardPhoto(), "照片/司机身份证照片.jpg");
            photoCount += addFileToZip(zipOut, delivery.getDestinationPoundListImg(), "照片/到地磅单.jpg");
            photoCount += addFileToZip(zipOut, delivery.getDestinationVehicleFrontPhoto(), "照片/到地车辆过重磅车头照片.jpg");
            
            
            // 3. 下载并添加所有视频
            int videoCount = 0;
            videoCount += addFileToZip(zipOut, delivery.getEmptyWeightVideo(), "视频/空车过磅视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getEntruckWeightVideo(), "视频/装车过磅视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getEntruckVideo(), "视频/装车视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getControlSlotVideo(), "视频/消毒槽视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getCattleLoadingCircleVideo(), "视频/牛只装车环视视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getUnloadCattleVideo(), "视频/卸牛视频.mp4");
            videoCount += addFileToZip(zipOut, delivery.getDestinationWeightVideo(), "视频/到地过磅视频.mp4");
            
            
            zipOut.finish();
            zipOut.close();
            
            // 设置响应头
            byte[] zipBytes = byteArrayOutputStream.toByteArray();
            String fileName = "运送清单_" + delivery.getDeliveryNumber() + "_" + System.currentTimeMillis() + ".zip";
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
            response.setContentLength(zipBytes.length);
            
            OutputStream out = response.getOutputStream();
            out.write(zipBytes);
            out.flush();
            out.close();
            
            
        } catch (Exception e) {
            e.printStackTrace();
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("打包文件失败：" + e.getMessage());
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        } finally {
            try {
                if (zipOut != null) {
                    zipOut.close();
                }
                byteArrayOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 添加运送清单信息到ZIP文件
     */
    private void addDeliveryInfoToZip(ZipOutputStream zipOut, Delivery delivery) throws IOException {
        StringBuilder info = new StringBuilder();
        info.append("====== 运送清单详细信息 ======\n\n");
        info.append("【基础信息】\n");
        info.append("运单号: ").append(delivery.getDeliveryNumber()).append("\n");
        info.append("车牌号: ").append(delivery.getLicensePlate()).append("\n");
        info.append("司机姓名: ").append(delivery.getDriverName()).append("\n");
        info.append("司机手机: ").append(delivery.getDriverMobile()).append("\n");
        info.append("起始地: ").append(delivery.getStartLocation()).append("\n");
        info.append("目的地: ").append(delivery.getEndLocation()).append("\n");
        info.append("预计送达时间: ").append(delivery.getEstimatedDeliveryTime()).append("\n");
        info.append("创建时间: ").append(delivery.getCreateTime()).append("\n\n");
        
        info.append("【重量信息】\n");
        info.append("空车过磅重量: ").append(delivery.getEmptyWeight()).append(" kg\n");
        info.append("装车过磅重量: ").append(delivery.getEntruckWeight()).append(" kg\n");
        info.append("落地过磅重量: ").append(delivery.getLandingEntruckWeight()).append(" kg\n\n");
        
        info.append("【状态信息】\n");
        String statusText = delivery.getStatus() == 1 ? "准备中" : (delivery.getStatus() == 2 ? "运输中" : "已结束");
        info.append("运输状态: ").append(statusText).append("\n\n");
        
        info.append("====== 文件生成时间: ").append(LocalDateTime.now()).append(" ======\n");
        
        ZipEntry entry = new ZipEntry("运送清单信息.txt");
        zipOut.putNextEntry(entry);
        zipOut.write(info.toString().getBytes(StandardCharsets.UTF_8));
        zipOut.closeEntry();
        
    }
    
    /**
     * 从URL下载文件并添加到ZIP
     * @return 成功添加返回1，失败或URL为空返回0
     */
    private int addFileToZip(ZipOutputStream zipOut, String fileUrl, String fileName) {
        if (fileUrl == null || fileUrl.trim().isEmpty()) {
            return 0;
        }
        
        InputStream inputStream = null;
        try {
            
            URL url = new URL(fileUrl);
            inputStream = url.openStream();
            
            ZipEntry entry = new ZipEntry(fileName);
            zipOut.putNextEntry(entry);
            
            byte[] buffer = new byte[8192];
            int bytesRead;
            int totalBytes = 0;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                zipOut.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }
            
            zipOut.closeEntry();
            return 1;
            
        } catch (Exception e) {
            return 0;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

