package com.ruoyi.app.order;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.ruoyi.app.order.dto.OrderPositionInfo;
import com.ruoyi.app.order.dto.OrderPushBodyDto;
import com.ruoyi.app.order.dto.PositionDto;
import com.ruoyi.app.order.dto.QsDto;
import com.ruoyi.app.order.dto.AdminOrderActionRequest;
import com.ruoyi.app.order.dto.AdminOrderStatusContext;
import com.ruoyi.app.pay.LinePayService;
import com.ruoyi.app.pay.LinePayRefundService;
import com.ruoyi.app.order.dto.AdminOrderStatusUpdateRequest;
import com.ruoyi.app.service.UserService;
import com.ruoyi.app.service.WalletService;
import com.ruoyi.app.user.dto.StoreOutput;
import com.ruoyi.app.utils.DateUtil;
import com.ruoyi.app.utils.OperatingUtil;
import com.ruoyi.app.utils.PayPush;
import com.ruoyi.app.utils.event.PushEventService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.OrderDTO;
import com.ruoyi.system.domain.vo.PosOrderInvoiceVo;
import com.ruoyi.system.mapper.PosFoodMapper;
import com.ruoyi.system.mapper.PosOrderMapper;
import com.ruoyi.system.mapper.PosOrderPromotionMapper;
import com.ruoyi.system.mapper.UserBillingMapper;
import com.ruoyi.system.omgpay.domain.OmgPaymentAttempt;
import com.ruoyi.system.omgpay.service.IOmgPaymentAttemptService;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.Auth;
import com.ruoyi.system.utils.AuthContext;
import com.ruoyi.system.utils.GetArea;
import com.ruoyi.system.utils.JwtUtil;
import com.ruoyi.system.utils.OrderLogHelper;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.core.domain.entity.SysUser;
import lombok.SneakyThrows;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * posorderController
 *
 * @author ruoyi
 * @date 2023-05-23
 */
@RestController
@RequestMapping("/system/order")
public class PosOrderController extends BaseController {
    @Autowired
    private IPosOrderService posOrderService;
    @Autowired
    private IInfoUserService infoUserService;
    @Autowired
    private IPosStoreService posStoreService;
    @Autowired
    private IInfoAddressService infoAddressService;
    @Autowired
    private IUserFootprintService userFootprintService;
    @Autowired
    private PosOrderMapper posOrderMapper;
    @Autowired
    private IRiderPositionService riderPositionService;
    @Autowired
    private IUserBillingService userBillingService;
    @Autowired
    private UserBillingMapper userBillingMapper;
    @Autowired
    private IPosMarginService posMarginService;
    @Autowired
    private ISalesPromotionService salesPromotionService;
    @Autowired
    private IPosAppealService posAppealService;
    @Autowired  //商品
    private IPosFoodService posFoodService;
    @Autowired  //经营时间
    private IOperatingHoursService operatingHoursService;
    @Autowired
    private IVipUserQuanyiService userQuanyiService;
    @Autowired
    private ISysPointControlService pointControlService;
    @Autowired
    private IUserWalletService userWalletService;
    @Autowired
    private IPointsTransactionService pointsTransactionService;

    @Autowired
    private PushEventService pushEventService;
    @Autowired
    private DeliveryOrderNotificationService deliveryOrderNotificationService;
    @Autowired
    private MerchantNotificationRouter merchantNotificationRouter;
    @Autowired
    private IPosOrderRatingService posOrderRatingService;
    @Autowired
    private IFoodStatisticsService foodStatisticsService;
    @Autowired
    private IOrderParentService orderParentService;
    @Autowired
    private WalletService walletService;
    @Autowired
    private PosFoodMapper posFoodMapper;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private UserService userService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PosOrderShOprateController shOprateController;
    @Autowired
    private OrderLogHelper orderLogHelper;
    @Autowired
    private PosOrderPromotionMapper posOrderPromotionMapper;

    @Autowired
    private OrderInvoiceService orderInvoiceService;
    @Autowired
    private OrderLifecycleService orderLifecycleService;
    @Autowired
    private LinePayService linePayService;
    @Autowired
    private LinePayRefundService linePayRefundService;
    @Autowired
    private com.ruoyi.app.pay.LinePayOrderGuard linePayOrderGuard;
    @Autowired
    private IPosOrderLinePaymentService linePaymentService;
    @Autowired
    private IOmgPaymentAttemptService omgPaymentAttemptService;
    @Autowired
    private MerchantStoreAccessService merchantStoreAccessService;


    //查询用户足迹
    @Anonymous
    @Auth
    @GetMapping("/getuserfootlist")
    public AjaxResult getuserfootlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size) {
        JwtUtil jwtUtil = new JwtUtil();
        String id = jwtUtil.getusid(token);
        IPage<UserFootprint> palist = new Page<>(page, size);
        QueryWrapper<UserFootprint> queryWrapper = new QueryWrapper<>();
        queryWrapper.select().orderByDesc("cretim");
        queryWrapper.eq("user_id", id);
        IPage<UserFootprint> list = userFootprintService.page(palist, queryWrapper);
        List<UserFootprint> footprints = list.getRecords();
        // 收集所有门店ID（Integer类型）
        List<Long> storeIds = footprints.stream()
                .map(UserFootprint::getMdId)
                .toList();

        // 使用MyBatis Plus一次性查询所有门店的商品（避免N+1查询问题）
        Map<Integer, List<PosFood>> foodMap = new java.util.HashMap<>();
        if (!storeIds.isEmpty()) {
            // 将Integer类型的门店ID转换为Long类型用于查询（因为mdid是Long类型）
            List<Long> storeIdsLong = storeIds.stream()
                    .map(x -> x)
                    .collect(Collectors.toList());

            // 使用MyBatis Plus的Mapper方法，在数据库查询时就限制每个门店只返回6条商品
            List<PosFood> allFoods = posFoodMapper.selectFoodsByStoreIdsWithLimit(storeIdsLong, "3", 6);

            // 按门店ID分组（查询结果已经限制为每个门店最多6条）
            foodMap = allFoods.stream()
                    .collect(Collectors.groupingBy(food -> food.getMdid().intValue()));
        }

        // 转换为StoreOutput并设置每个门店的商品列表（每个门店最多6条）
        List<StoreOutput> storeOutputList = new ArrayList<>();
        for (UserFootprint collect : footprints) {
            PosStore store = posStoreService.getById(collect.getMdId());
            if (store != null) {
                StoreOutput storeOutput = new StoreOutput();
                // 复制PosStore的所有属性
                BeanUtils.copyProperties(store, storeOutput);
                // 从分组结果中获取该门店的商品列表（已限制为最多6条）
                List<PosFood> foodList = foodMap.getOrDefault(store.getId(), new ArrayList<>());
                storeOutput.setFoodList(foodList);
                storeOutputList.add(storeOutput);
            }
        }
        Page<StoreOutput> result = new Page<>(page, 10);
        result.setTotal(list.getTotal());
        result.setRecords(storeOutputList);
        return success(result);
    }


    //修改订单
    @Anonymous
    @Auth(session = true)
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @PostMapping("/setorderuzt")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult setorderuzt(@RequestHeader String token, @RequestBody PosOrder posOrder) {
        PayPush push = new PayPush();
        Long loginUserId = AuthContext.requireUserId();
        String id = String.valueOf(loginUserId);
        PosOrder persisted = posOrder.getId() == null ? null : posOrderService.getById(posOrder.getId());
        InfoUser actor = infoUserService.getById(loginUserId);
        if (actor != null && ("1".equals(actor.getUserType()) || "5".equals(actor.getUserType()))) {
            merchantStoreAccessService.requireOrderAccess(loginUserId,
                    persisted == null ? null : persisted.getId());
        } else {
            linePayOrderGuard.requireLegacyOrderActor(persisted, actor, posOrder.getState());
        }
        boolean actualLineOrder = persisted != null && linePaymentService != null
                && !linePaymentService.getByDdId(String.valueOf(persisted.getDdId())).isEmpty();
        if (actualLineOrder) {
            throw new ServiceException(lineMessage("line.pay.legacy.endpoint.disabled",
                    "LINE Pay order must use the dedicated order operation endpoint"));
        }
        if (posOrder.getState() != null) {
            if (posOrder.getId() != null && posOrder.getState() != 0L) {
                linePayOrderGuard.requirePaidBeforeAccept(persisted);
            }
            //状态为送达，设置送达时间
            if (posOrder.getState() == 12) {
                posOrder.setSdTime(new Date());
            }
            System.out.println("修改订单状态信息：" + JSON.toJSONString(posOrder));
            //设置支付类型为货到付款
            if (!actualLineOrder && posOrder.getState() == 0
                    && "1".equals(posOrder.getCollectPayment())) {
                System.out.println("进入设置paytype等于1");
                posOrder.setPayType("1");
            }
            //取餐时设置预计送达时间
            setYjsdTime(posOrder);
            if (posOrder.getState() == 5) {
                return setOrderState5(posOrder);
            } else if (posOrder.getState() == 2) {
                return setOrderState2(posOrder, id);
            } else if (posOrder.getState() == 3 || posOrder.getState() == 4 || posOrder.getState() == 12) {
                return setOrderQsState(posOrder, id, push);
            } else if (posOrder.getState() == 7) {
                return setOrderState7(posOrder);
            } else {

                boolean org = posOrderService.saveOrUpdate(posOrder);
                PosOrder order = posOrderService.getById(posOrder.getId());
                if (order.getState() == 0 && order.getCollectPayment().equals("1")) {
                    sendHdfkMessage(order);
                }
                //作废退回积分
                if (posOrder.getState() == 10 && order.getPoints() != null && order.getPoints() > 0) {
                    returnPoints(order.getUserId(), Long.valueOf(order.getDdId()), Long.valueOf(order.getPoints()));
                }
                if (org) {
                    // 平台管理员修改订单状态，添加操作日志
                    SysUser adminUser = SecurityUtils.getLoginUser().getUser();
                    String adminName = adminUser != null ? adminUser.getNickName() : "";
                    PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
                    String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
                    orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                        "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

                    return success(MessageUtils.message("no.modify.success"), posOrder.getId());
                } else {
                    return error();
                }
            }
        } else {
            return setOrderNoState(posOrder, id);
        }
    }

    //骑手接单、取餐、送达
    private AjaxResult setOrderQsState(PosOrder posOrder, String qsId, PayPush push) {
        String lockKey = "order:qs:lock:" + posOrder.getId();
        RLock lock = redissonClient.getLock(lockKey);
        try {
            var local = LocaleContextHolder.getLocale();
            logger.info("骑手接单local信息：" + local.getLanguage());
            logger.info(JSON.toJSONString(local));
            // 尝试获取锁
            if (lock.tryLock(20L, 10L, TimeUnit.SECONDS)) {
                boolean releaseInfinally = true;
                try {
                    userService.checkUserStatus(Long.valueOf(qsId));
                    PosOrder orst = posOrderService.getById(posOrder.getId());
                    if (orst.getState() == 3 && posOrder.getState() == 3) {
                        throw new ServiceException(MessageUtils.message("no.order.snatched"));
                    }
                    if (posOrder.getState() == 3) {
                        QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();
                        wrapper.eq("qs_id", qsId);
                        wrapper.in("state", 3, 4);
                        List<PosOrder> orsts = posOrderService.list(wrapper);
                        if (orsts.size() > 0) {
                            throw new ServiceException(MessageUtils.message("no.exist.undelivered.order"));
                        }
                    }
                    String userMessage = MessageUtils.message("no.message.push.delivery.personnel.receiving.order");
                    if (posOrder.getState() == 4) {
                        userMessage = MessageUtils.message("no.message.push.delivery.personnel.qspsz.order");
                    } else if (posOrder.getState() == 12) {
                        userMessage = MessageUtils.message("no.message.push.delivery.personnel.qsysd.order");
                    }

                    boolean org = posOrderService.saveOrUpdate(posOrder);
                    if (org) {
                        // 平台管理员修改订单状态（骑手操作），添加操作日志
                        SysUser adminUser = SecurityUtils.getLoginUser().getUser();
                        String adminName = adminUser != null ? adminUser.getNickName() : "";
                        PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
                        String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
                        orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                            "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

                        //到付订单,设置用户账单为完成
                        if (posOrder.getState() == 3 && "1".equals(orst.getCollectPayment())) {
                            updateUserBill(orst.getDdId(), orst.getUserId(), orst.getQsId());
                        }
                        InfoUser user = infoUserService.getById(orst.getUserId());
                        String finalUserMessage = userMessage;
                        releaseInfinally = false;
                        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                            @Override
                            public void afterCommit() {
                                if (lock.isHeldByCurrentThread()) {
                                    lock.unlock();
                                }
                                // 给用户推送（骑手已接单/配送中/已送达）
                                if (!StringUtils.isEmpty(user.getCid())) {
                                    String userTitle = "no.message.push.message";
                                    String userContent = "no.message.push.delivery.personnel.receiving.order";
                                    if (posOrder.getState() == 4) {
                                        userContent = "no.message.push.delivery.personnel.qspsz.order";
                                    } else if (posOrder.getState() == 12) {
                                        userContent = "no.message.push.delivery.personnel.qsysd.order";
                                    }
                                    final String finalUserContent = userContent;
                                    String userBody = OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState()));
                                    Long userUserId = user.getUserId();
                                    String userCid = user.getCid();
                                    String userCidType = "";
                                    String userDdId = String.valueOf(orst.getDdId());
                                    AsyncManager.me().execute(new TimerTask() {
                                        @Override
                                        public void run() {
                                            PayPush.userPushHandleLocal(push, pushEventService, userUserId, userCid, userTitle, finalUserContent, userBody, userCidType, userDdId);
                                        }
                                    });
                                }
                                // 给商家推送（骑手已接单时）
                                if (posOrder.getState() == 3) {
                                    String shTitle = "no.message.push.message";
                                    String shContent = "no.message.push.delivery.personnel.receiving.order";
                                    String shBody = OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState()));
                                    String shDdId = String.valueOf(orst.getDdId());
                                    AsyncManager.me().execute(new TimerTask() {
                                        @Override
                                        public void run() {
                                            merchantNotificationRouter.sendStoreNotification(orst.getMdId(), orst.getShId(),
                                                    shTitle, shContent, shBody, shDdId);
                                        }
                                    });
                                }
                            }
                        });
                        return success(MessageUtils.message("no.modify.success"), posOrder.getId());
                    } else {
                        return error();
                    }
                } finally {
                    if (releaseInfinally && lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            } else {
                throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new ServiceException(MessageUtils.message("no.operation.interrupted.try.again"));
        }
    }

    /**
     * 更新用户用户账单
     *
     * @param ddId
     * @param userId
     * @param qsId
     */
    private void updateUserBill(String ddId, Long userId, Long qsId) {
        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dd_id", ddId);
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("type", "3");
        UserBilling userBill = userBillingService.getOne(queryWrapper);
        if (userBill != null) {
            userBill.setState("0");
            userBill.setIllustrate("Rider Payment Order");
            userBill.setBalancePay("1");
            userBill.setPaymentId(String.valueOf(qsId));
            userBillingService.saveOrUpdate(userBill);
        }
    }


    //商家接单
    private AjaxResult setOrderState2(PosOrder posOrder, String id) {
        int zsou = userBillingMapper.gettypesum(Long.valueOf(id), 1L);
        int zcz = userBillingMapper.gettypesum(Long.valueOf(id), 2L);
        int xiaof = userBillingMapper.gettypesum(Long.valueOf(id), 3L);
        int yure = zsou - zcz - xiaof;
        PosMargin posMargin = posMarginService.getById(1);
        InfoUser user = infoUserService.getById(id);
        if (user.getUserType().equals("1")) {
            boolean org = posOrderService.saveOrUpdate(posOrder);
            if (org) {
                PosOrder order = posOrderService.getById(posOrder.getId());

                // 平台管理员修改订单状态（商家接单），添加操作日志
                SysUser adminUser = SecurityUtils.getLoginUser().getUser();
                String adminName = adminUser != null ? adminUser.getNickName() : "";
                PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
                String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
                orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                    "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
            } else {
                return error();
            }
        } else {
            if (yure <= (int) Math.round(posMargin.getAmount())) {
                return error(MessageUtils.message("no.insufficient.user.security.deposit"));
            } else {
                boolean org = posOrderService.saveOrUpdate(posOrder);
                if (org) {
                    PosOrder order = posOrderService.getById(posOrder.getId());

                    // 平台管理员修改订单状态（商家接单），添加操作日志
                    SysUser adminUser = SecurityUtils.getLoginUser().getUser();
                    String adminName = adminUser != null ? adminUser.getNickName() : "";
                    PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
                    String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
                    orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                        "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

                    return success(MessageUtils.message("no.modify.success"), posOrder.getId());
                } else {
                    return error();
                }
            }
        }
    }

    //订单完成
    private AjaxResult setOrderState5(PosOrder posOrder) {
        boolean org = posOrderService.saveOrUpdate(posOrder);
        if (org) {
            PosOrder order = posOrderService.getById(posOrder.getId());

            // 平台管理员修改订单状态（订单完成），添加操作日志
            SysUser adminUser = SecurityUtils.getLoginUser().getUser();
            String adminName = adminUser != null ? adminUser.getNickName() : "";
            PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
            String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
            orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
            wrapper.eq("dd_id", order.getDdId());

            UserBilling billing = userBillingService.getOne(wrapper);
            if (billing == null) {
                orderService.setSanghuBilling(order);
                orderService.setQishouBilling(order);
            }
            return success(MessageUtils.message("no.modify.success"), posOrder.getId());
        } else {
            return error();
        }
    }

    //同意退款
    private AjaxResult setOrderState7(PosOrder posOrder) {
        boolean org = posOrderService.saveOrUpdate(posOrder);
        PosOrder order = posOrderService.getById(posOrder.getId());

        // 平台管理员修改订单状态（同意退款），添加操作日志
        SysUser adminUser = SecurityUtils.getLoginUser().getUser();
        String adminName = adminUser != null ? adminUser.getNickName() : "";
        PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
        String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
        orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
            "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

        if (order.getPoints() != null && order.getPoints() > 0) {
            returnPoints(order.getUserId(), Long.valueOf(order.getDdId()), Long.valueOf(order.getPoints()));
        }
        if (org) {
            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
            wrapper.eq("dd_id", posOrder.getId());
            List<UserBilling> billing = userBillingService.list(wrapper);
            if (billing.size() == 0) {
                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
            } else {
                for (int i = 0; i < billing.size(); i++) {
                    UserBilling user = new UserBilling();
                    user.setId(billing.get(i).getId());
                    user.setState("1");
                    userBillingService.saveOrUpdate(user);
                }
                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
            }
        } else {
            return error();
        }
    }

    //更改订单没传订单状态
    private AjaxResult setOrderNoState(PosOrder posOrder, String id) {
        PosOrder ordera = posOrderService.getById(posOrder.getId());
        //订单金额限制100万改为200万
        if (posOrder.getCollectPayment().equals("1") && ordera.getAmount() > 2000000) {
            return error(MessageUtils.message("no.cash_on_delivery_amount.exceed.limit_amount"));
        }

        QueryWrapper<PosOrder> query = new QueryWrapper<>();
        query.eq("user_id", id);
        query.eq("collect_payment", "1");
        query.notIn("state", 5, 10, 11);
        List<PosOrder> posOrders = posOrderService.list(query);
        //到付能存在2单未完成，第3单弹出提示;修改做判断的前提是当前订单不是为到付
        if (posOrders.size() >= 2 && posOrder.getCollectPayment().equals("1") && !"1".equals(ordera.getCollectPayment())) {
            return error(MessageUtils.message("no.exist.cash_on_delivery_order.incomplete"));
        }
        boolean org = posOrderService.saveOrUpdate(posOrder);
        if (org) {
            shOprateController.chuCan(ordera, posOrder);
            PosOrder order = posOrderService.getById(posOrder.getId());

            // 平台管理员修改订单状态（无状态变更），添加操作日志
            SysUser adminUser = SecurityUtils.getLoginUser().getUser();
            String adminName = adminUser != null ? adminUser.getNickName() : "";
            PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
            String logDdId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
            orderLogHelper.log(logDdId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
                "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

            return success(MessageUtils.message("no.modify.success"), posOrder.getId());
        } else {
            return error();
        }
    }



    /**
     * 获取预计送达时间
     *
     * @param posOrder
     * @return
     */
    private String setYjsdTime(PosOrder posOrder) {
        try {
            if (posOrder.getState() == 4) {
                GetArea getArea = new GetArea();
                PosOrder order = posOrderService.getById(posOrder.getId());
                String mdlat = order.getLongitude() + "," + order.getLatitude();
                InfoAddress shDz = infoAddressService.getById(order.getShdzId());

                String shlat = shDz.getLongitude() + "," + shDz.getLatitude();
                double time = getArea.getMotorbikeDuration(mdlat, shlat);
                DateUtil dateUtil = new DateUtil();
                String start = dateUtil.getHourAndMinute((long) time);
                double endTime = time + 600; //加上10分钟
                String end = dateUtil.getHourAndMinute((long) endTime);
                posOrder.setYjsdTime(start + "-" + end);
                return start + "-" + end;
            }
            return "";
        } catch (Exception e) {
            logger.error("获取预计送达时间异常,id:" + posOrder.getId() + "异常信息：", e);
            return "";
        }
    }

    //修改订单
    @Anonymous
    @PostMapping("/testYjsdTime")
    public String testYjsdTime(@RequestBody PosOrder order) {
        return setYjsdTime(order);

    }



    //后台查询详情
    @GetMapping("/getorderhout")
    public AjaxResult getorderhout(@RequestParam String id) {
        PosOrder orlist = posOrderService.getById(id);
        // 自动序列化所有PosOrder字段，新增字段无需手动添加
        JSONObject org = JSON.parseObject(
            JSON.toJSONStringWithDateFormat(orlist, "yyyy-MM-dd HH:mm:ss")
        );
        // 以下为非PosOrder字段或需要特殊处理的字段
        org.put("shanghu", infoUserService.getById(orlist.getShId()));
        org.put("store", posStoreService.getById(orlist.getMdId()));
        org.put("shaddress", orlist.getShAddress() == null ? infoAddressService.getById(orlist.getShdzId()) : JSONObject.parseObject(orlist.getShAddress()));
        org.put("user", infoUserService.getById(orlist.getUserId()));
        org.put("qsuser", infoUserService.getById(orlist.getQsId()));
        QueryWrapper<RiderPosition> query = new QueryWrapper<>();
        query.eq("rider_id", orlist.getQsId());
        org.put("RiderPosition", orlist.getQsId() == null ? null : riderPositionService.getOne(query));
        org.put("food", JSONArray.parseArray(orlist.getFood()));
        // 已支付订单附带支付商交易单号，供平台到支付商后台按单号查询交易详情
        org.put("payTrade", buildPayTrade(orlist));
        return success(org);
    }

    /**
     * 已支付订单的支付商交易单号信息，供平台在支付商后台按单号查询交易详情。
     * OMG 返回 MerchantTradeNo（支付商侧查询键）与网关 TradeNo；
     * LINE Pay 返回 lineOrderId 与 transactionId；其他渠道（到付等）返回 null。
     */
    private JSONObject buildPayTrade(PosOrder order) {
        // 已退款订单同样需要单号到支付商侧核对退款，因此仅排除未支付
        if (order.getPayStatus() == null || order.getPayStatus() == 0L) {
            return null;
        }
        JSONObject trade = new JSONObject();
        if (OrderLifecycleService.isCardWalletPayType(order.getPayType())) {
            OmgPaymentAttempt attempt = omgPaymentAttemptService.selectPaidByDdId(order.getDdId());
            if (attempt == null) {
                return null;
            }
            trade.put("channel", "OMG");
            trade.put("merchantTradeNo", attempt.getMerchantTradeNo());
            trade.put("gatewayTradeNo", attempt.getTradeNo());
        } else if (LinePayService.PAY_TYPE_LINE.equals(order.getPayType())) {
            PosOrderLinePayment paid = linePaymentService.getByDdId(order.getDdId()).stream()
                    .filter(payment -> "PAID".equals(payment.getStatus()))
                    .max(Comparator.comparing(PosOrderLinePayment::getId))
                    .orElse(null);
            if (paid == null) {
                return null;
            }
            trade.put("channel", "LINE Pay");
            trade.put("lineOrderId", paid.getLineOrderId());
            trade.put("transactionId", paid.getTransactionId());
        } else {
            return null;
        }
        return trade;
    }

    /**
     * 通过订单号查询订单详情
     *
     * @param ddid
     * @return
     */
    //查询订单详情
    @Anonymous
    @Auth(session = true)
    @GetMapping("/getorderxq")
    public AjaxResult getorderxq(@RequestHeader String token, @RequestParam String ddid) {
        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dd_id", ddid);
        PosOrder orlist = posOrderService.getOne(queryWrapper);
        requireOrderDetailAccess(orlist);
        // 自动序列化所有PosOrder字段，新增字段无需手动添加
        JSONObject org = JSON.parseObject(
            JSON.toJSONStringWithDateFormat(orlist, "yyyy-MM-dd HH:mm:ss")
        );
        // 以下为非PosOrder字段或需要特殊处理的字段
        org.put("shanghu", infoUserService.getById(orlist.getShId()));
        org.put("store", posStoreService.getById(orlist.getMdId()));
        org.put("shaddress", orlist.getShAddress() == null ? infoAddressService.getById(orlist.getShdzId()) : JSONObject.parseObject(orlist.getShAddress()));
        org.put("user", infoUserService.getById(orlist.getUserId()));
        InfoUser qsUser = infoUserService.getById(orlist.getQsId());
        setQsStar(qsUser);
        org.put("qsuser", orlist.getQsId() == null ? null : qsUser);
        QueryWrapper<RiderPosition> query = new QueryWrapper<>();
        query.eq("rider_id", orlist.getQsId());
        org.put("RiderPosition", orlist.getQsId() == null ? null : riderPositionService.getOne(query));
        org.put("food", JSONArray.parseArray(orlist.getFood()));
        Long count = posOrderRatingService.getBaseMapper().selectCount(new QueryWrapper<PosOrderRating>().eq("dd_id", ddid));
        org.put("isCommented", count > 0);
        // 查询促销快照明细
        List<PosOrderPromotion> promotions = posOrderPromotionMapper.selectByOrderId(orlist.getId());
        org.put("promotions", promotions);
        return success(org);
    }

    private void requireOrderDetailAccess(PosOrder order) {
        Long loginUserId = AuthContext.requireUserId();
        InfoUser actor = infoUserService.getById(loginUserId);
        if (order == null || actor == null) {
            throw new ServiceException(MessageUtils.message("merchant.order.not.found"));
        }
        if ("0".equals(actor.getUserType())) {
            if (!loginUserId.equals(order.getUserId())) {
                throw new ServiceException(MessageUtils.message("merchant.order.not.found"));
            }
            return;
        }
        if ("2".equals(actor.getUserType())) {
            if (!loginUserId.equals(order.getQsId())) {
                throw new ServiceException(MessageUtils.message("merchant.order.not.found"));
            }
            return;
        }
        if ("1".equals(actor.getUserType()) || "5".equals(actor.getUserType())) {
            merchantStoreAccessService.requireOrderAccess(loginUserId, order.getId());
            return;
        }
        linePayOrderGuard.requireMerchantOwnership(order, actor);
    }

    /**
     * 设置骑手星级
     *
     * @param infoUser
     */

    private void setQsStar(InfoUser infoUser) {
        if (infoUser != null) {
            QueryWrapper<PosOrderRating> wrapper = new QueryWrapper<>();
            wrapper.eq("qs_id", infoUser.getUserId()).isNotNull("qs_stars").isNotNull("qs_stars").select("ROUND(AVG(qs_stars), 1) as qs_stars");
            List<Map<String, Object>> map = posOrderRatingService.getBaseMapper().selectMaps(wrapper);
            if (!map.isEmpty() && map.get(0) != null) {
                Object rating = map.get(0).get("qs_stars");
                // 关键：显式检查null值
                if (rating != null) {
                    infoUser.setStar(Double.parseDouble(rating.toString()));
                }

            } else {
                infoUser.setStar(4.5);
            }

        }
    }

    //查询所有的订单
    @Anonymous
    @GetMapping("/getqishouorderlist")
    public AjaxResult getqishouorderlist(@RequestParam Integer page, @RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude, @RequestParam Integer juli, @RequestParam(defaultValue = "") String state) {

        JSONArray arr = new JSONArray();
        List<PosOrder> orlist;
        if (!"".equals(state)) {
            if (state.equals("z02")) {
                orlist = posOrderMapper.getz02(longitude, latitude, (page - 1) * 20, juli);
            } else if (state.equals("z234")) {
                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 2, 4);
            } else if (state.equals("z23")) {
                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 2, 3);
            } else if (state.equals("z34")) {
                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 3, 4);
            } else if (state.equals("z6789")) {
                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 6, 9);
            } else {
                orlist = posOrderMapper.getstate(longitude, latitude, (page - 1) * 20, juli, state);
            }
        } else {
            orlist = posOrderMapper.getqisjvli(longitude, latitude, (page - 1) * 20, juli);
        }
        // 循环外统一查询，避免N+1问题
        Set<Long> allUserIds = orlist.stream().flatMap(o -> Stream.of(o.getShId(), o.getUserId())).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> mdIds = orlist.stream().map(PosOrder::getMdId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> shdzIds = orlist.stream().filter(o -> o.getShAddress() == null && o.getShdzId() != null).map(PosOrder::getShdzId).collect(Collectors.toSet());
        Map<Long, InfoUser> userMap = allUserIds.isEmpty() ? Collections.emptyMap() :
            infoUserService.listByIds(allUserIds).stream().collect(Collectors.toMap(InfoUser::getUserId, u -> u));
        Map<Integer, PosStore> storeMap = mdIds.isEmpty() ? Collections.emptyMap() :
            posStoreService.listByIds(mdIds).stream().collect(Collectors.toMap(PosStore::getId, s -> s));
        Map<Long, InfoAddress> addressMap = shdzIds.isEmpty() ? Collections.emptyMap() :
            infoAddressService.listByIds(shdzIds).stream().collect(Collectors.toMap(InfoAddress::getId, a -> a));

        DecimalFormat jl = new DecimalFormat("#.0");
        for (PosOrder order : orlist) {
            // 自动序列化所有PosOrder字段，新增字段无需手动添加
            JSONObject org = JSON.parseObject(
                JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss")
            );
            // 以下为非PosOrder字段或需要特殊处理的字段
            org.put("shanghu", userMap.get(order.getShId()));
            org.put("store", storeMap.get(order.getMdId().intValue()));
            org.put("shaddress", order.getShAddress() == null ? addressMap.get(order.getShdzId()) : JSONObject.parseObject(order.getShAddress()));
            org.put("user", userMap.get(order.getUserId()));
            org.put("jvli", jl.format(order.getJvli()));
            org.put("juli", jl.format(order.getJuli()));
            org.put("food", JSONArray.parseArray(order.getFood()));
            arr.add(org);
        }
        return success(arr);
    }

    //查询骑手的订单
    @Anonymous
    @Auth
    @GetMapping("/getqsorderlist")
    public AjaxResult getqsorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam(defaultValue = "") String state, @RequestParam(defaultValue = "0") BigDecimal longitude, @RequestParam(defaultValue = "0") BigDecimal latitude) {
        logger.info("骑手token:" + token);
        JwtUtil jwtUtil = new JwtUtil();
        String id = jwtUtil.getusid(token);
        List<PosOrder> orlist = posOrderMapper.getQsOrderList(id, longitude, latitude, (page - 1) * size, size, state);
        // 循环外统一查询，避免N+1问题
        Set<Long> allUserIds = orlist.stream().flatMap(o -> Stream.of(o.getShId(), o.getUserId(), o.getQsId())).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> mdIds = orlist.stream().map(PosOrder::getMdId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> shdzIds = orlist.stream().filter(o -> o.getShAddress() == null && o.getShdzId() != null).map(PosOrder::getShdzId).collect(Collectors.toSet());
        Map<Long, InfoUser> userMap = allUserIds.isEmpty() ? Collections.emptyMap() :
            infoUserService.listByIds(allUserIds).stream().collect(Collectors.toMap(InfoUser::getUserId, u -> u));
        Map<Integer, PosStore> storeMap = mdIds.isEmpty() ? Collections.emptyMap() :
            posStoreService.listByIds(mdIds).stream().collect(Collectors.toMap(PosStore::getId, s -> s));
        Map<Long, InfoAddress> addressMap = shdzIds.isEmpty() ? Collections.emptyMap() :
            infoAddressService.listByIds(shdzIds).stream().collect(Collectors.toMap(InfoAddress::getId, a -> a));

        JSONArray arr = new JSONArray();
        DecimalFormat jl = new DecimalFormat("#.0");
        for (PosOrder order : orlist) {
            // 自动序列化所有PosOrder字段，新增字段无需手动添加
            JSONObject org = JSON.parseObject(
                JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss")
            );
            // 以下为非PosOrder字段或需要特殊处理的字段
            org.put("shanghu", userMap.get(order.getShId()));
            org.put("store", storeMap.get(order.getMdId().intValue()));
            org.put("shaddress", order.getShAddress() == null ? addressMap.get(order.getShdzId()) : JSONObject.parseObject(order.getShAddress()));
            org.put("user", userMap.get(order.getUserId()));
            org.put("qishou", userMap.get(order.getQsId()));
            org.put("jvli", jl.format(order.getJvli()));
            org.put("qsjvli", jl.format(order.getJuli()));
            org.put("food", JSONArray.parseArray(order.getFood()));
            org.put("sqImg", org.remove("qsImg"));
            arr.add(org);
        }
        return success(arr);
    }

    //查询商家的订单
    @Anonymous
    @Auth(session = true)
    @GetMapping("/getstoreorderlist")
    public AjaxResult getstoreorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam String mdId, @RequestParam(defaultValue = "") String state, @RequestParam(defaultValue = "") String diningStatus,@RequestParam(defaultValue = "")String type) {
        Long loginUserId = AuthContext.requireUserId();
        Long requestedStoreId;
        try {
            requestedStoreId = Long.valueOf(mdId);
        } catch (NumberFormatException exception) {
            throw new ServiceException(MessageUtils.message("merchant.store.access.denied"));
        }
        InfoUser actor = infoUserService.getById(loginUserId);
        if (actor == null) {
            throw new ServiceException(MessageUtils.message("merchant.account.unavailable"));
        }
        IPage<PosOrder> palist = new Page<>(page, size);
        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select().orderByDesc("cretim");
        if ("1".equals(actor.getUserType()) || "5".equals(actor.getUserType())) {
            merchantStoreAccessService.requireStoreAccess(loginUserId, requestedStoreId);
            queryWrapper.eq("md_id", requestedStoreId);
        } else if ("3".equals(actor.getUserType())) {
            queryWrapper.eq("sh_id", loginUserId).eq("md_id", requestedStoreId);
        } else if (actor.getStoreId() != null && actor.getStoreId().equals(requestedStoreId)) {
            queryWrapper.eq("md_id", actor.getStoreId());
        } else {
            throw new ServiceException(MessageUtils.message("merchant.store.access.denied"));
        }
        queryWrapper.eq("is_display", true);
        queryWrapper.eq(!StringUtils.isEmpty(type),"type",type);
        if (!"".equals(state)) {
            if (state.equals("z01")) {
                queryWrapper.apply(" ((state = 0 AND (collect_payment = 1 OR type = 1)) OR (state = 1))");
            } else if (state.equals("z234")) {
                queryWrapper.in("state", 2, 3, 4);
            } else if (state.equals("z23")) {
                queryWrapper.in("state", 2, 3);
            } else if (state.equals("z34")) {
                queryWrapper.in("state", 3, 4);
            } else if (state.equals("z678911")) {
                queryWrapper.in("state", 6, 7, 8, 9, 11);
            } else {
                queryWrapper.eq("state", state);
            }
        }
        if (!"".equals(diningStatus)) {
            queryWrapper.eq("dining_status", diningStatus);
        }
        IPage<PosOrder> list = posOrderService.page(palist, queryWrapper);
        List<PosOrder> orlist = list.getRecords();
        // 循环外统一查询，避免N+1问题
        Set<Long> allUserIds = orlist.stream().flatMap(o -> Stream.of(o.getShId(), o.getUserId())).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> mdIds = orlist.stream().map(PosOrder::getMdId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> shdzIds = orlist.stream().filter(o -> o.getShAddress() == null && o.getShdzId() != null).map(PosOrder::getShdzId).collect(Collectors.toSet());
        Map<Long, InfoUser> userMap = allUserIds.isEmpty() ? Collections.emptyMap() :
            infoUserService.listByIds(allUserIds).stream().collect(Collectors.toMap(InfoUser::getUserId, u -> u));
        Map<Integer, PosStore> storeMap = mdIds.isEmpty() ? Collections.emptyMap() :
            posStoreService.listByIds(mdIds).stream().collect(Collectors.toMap(PosStore::getId, s -> s));
        Map<Long, InfoAddress> addressMap = shdzIds.isEmpty() ? Collections.emptyMap() :
            infoAddressService.listByIds(shdzIds).stream().collect(Collectors.toMap(InfoAddress::getId, a -> a));

        JSONArray arr = new JSONArray();
        for (PosOrder order : orlist) {
            // 自动序列化所有PosOrder字段，新增字段无需手动添加
            JSONObject org = JSON.parseObject(
                JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss")
            );
            // 以下为非PosOrder字段或需要特殊处理的字段
            org.put("shanghu", userMap.get(order.getShId()));
            org.put("store", storeMap.get(order.getMdId().intValue()));
            org.put("shaddress", order.getShAddress() == null ? addressMap.get(order.getShdzId()) : JSONObject.parseObject(order.getShAddress()));
            org.put("user", userMap.get(order.getUserId()));
            org.put("food", JSONArray.parseArray(order.getFood()));
            arr.add(org);
        }
        return success(arr);
    }

    //查询用户的订单(用户端)
    @Anonymous
    @Auth
    @GetMapping("/getorderlist")
    public AjaxResult getorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam(defaultValue = "") String state,@RequestParam(defaultValue = "")String type) {
        JwtUtil jwtUtil = new JwtUtil();
        String id = jwtUtil.getusid(token);
        IPage<PosOrder> palist = new Page<>(page, size);
        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select().orderByDesc("cretim");
        queryWrapper.eq("user_id", id);
        queryWrapper.eq(!StringUtils.isEmpty(type),"type",type);
        if (!"".equals(state)) {
            if (state.equals("z23412")) {
                queryWrapper.in("state", 2, 3, 4, 12);
            } else if (state.equals("z23")) {
                queryWrapper.in("state", 2, 3);
            } else if (state.equals("z34")) {
                queryWrapper.in("state", 3, 4);
            } else if (state.equals("z678911")) {
                queryWrapper.in("state", 6, 7, 8, 9, 11);
            } else {
                queryWrapper.eq("state", state);
            }
        }
        // 添加排除条件：state=0且collect_payment=0的数据
        queryWrapper.apply("NOT (state = 0 AND collect_payment = 0)");
        IPage<PosOrder> list = posOrderService.page(palist, queryWrapper);
        List<PosOrder> orlist = list.getRecords();
        List<String> parentDdIds = orlist.stream().map(PosOrder::getParentDdId).collect(Collectors.toList());
        List<OrderParent> orderParents = new ArrayList<>();
        if (!parentDdIds.isEmpty()) {
            orderParents = orderParentService.list(new LambdaQueryWrapper<>(OrderParent.class).in(OrderParent::getDdId, parentDdIds));
        }
        // 循环外统一查询，避免N+1问题
        Set<Long> allUserIds = orlist.stream().flatMap(o -> Stream.of(o.getShId(), o.getUserId())).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> mdIds = orlist.stream().map(PosOrder::getMdId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> shdzIds = orlist.stream().filter(o -> o.getShAddress() == null && o.getShdzId() != null).map(PosOrder::getShdzId).collect(Collectors.toSet());
        Map<Long, InfoUser> userMap = allUserIds.isEmpty() ? Collections.emptyMap() :
            infoUserService.listByIds(allUserIds).stream().collect(Collectors.toMap(InfoUser::getUserId, u -> u));
        Map<Integer, PosStore> storeMap = mdIds.isEmpty() ? Collections.emptyMap() :
            posStoreService.listByIds(mdIds).stream().collect(Collectors.toMap(PosStore::getId, s -> s));
        Map<Long, InfoAddress> addressMap = shdzIds.isEmpty() ? Collections.emptyMap() :
            infoAddressService.listByIds(shdzIds).stream().collect(Collectors.toMap(InfoAddress::getId, a -> a));
        Map<String, OrderParent> orderParentMap = orderParents.stream().collect(Collectors.toMap(OrderParent::getDdId, p -> p));

        JSONArray arr = new JSONArray();
        for (PosOrder order : orlist) {
            // 自动序列化所有PosOrder字段，新增字段无需手动添加
            JSONObject org = JSON.parseObject(
                JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss")
            );
            // 以下为非PosOrder字段或需要特殊处理的字段
            org.put("ddId", order.getDdId() == null ? null : order.getDdId().toString());
            org.put("shanghu", userMap.get(order.getShId()));
            org.put("store", storeMap.get(order.getMdId().intValue()));
            org.put("shaddress", order.getShAddress() == null ? addressMap.get(order.getShdzId()) : JSONObject.parseObject(order.getShAddress()));
            org.put("user", userMap.get(order.getUserId()));
            org.put("food", JSONArray.parseArray(order.getFood()));
            org.put("parentRemarks", "");
            if (StringUtils.isNotEmpty(order.getParentDdId())) {
                OrderParent parent = orderParentMap.get(order.getParentDdId());
                if (parent != null) org.put("parentRemarks", parent.getRemarks());
            }
            arr.add(org);
        }
        return success(arr);
    }

    //    @Anonymous
//    @GetMapping("/sssaaaa")
//    public AjaxResult sssaaaa(@RequestParam String aa,@RequestParam String bb){
//        DateUtil dateUtil = new DateUtil();
//        Boolean sbsj = dateUtil.isLegalTime(aa,bb);
//        return success(sbsj);
//    }
    //添加新订单
    @SneakyThrows
    @Anonymous
    @Auth
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    @PostMapping("/addorder")
    public AjaxResult addorder(@RequestHeader String token, @RequestBody OrderDTO orderDTO) {
        long methodStart = System.currentTimeMillis(); // 记录方法开始时间
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        Integer xiadanjiaoyan = orderDTO.getXiadanjiaoyan();
        if (xiadanjiaoyan == null || !xiadanjiaoyan.equals(2)) {
            return error(MessageUtils.message("no.xiadanyz.message"));
        }

        System.out.println("========== 接收到的orderDTO ==========");
        System.out.println(mapper.writeValueAsString(orderDTO));
        JwtUtil jwtUtil = new JwtUtil();
        DateUtil dateUtil = new DateUtil();
        String id = jwtUtil.getusid(token);
        QueryWrapper<OperatingHours> wrapper = new QueryWrapper<>();
        wrapper.eq("md_id", orderDTO.getMdId());
        List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
        PosStore store = posStoreService.getById(orderDTO.getMdId());

        JSONObject usdizhi = new JSONObject();
        if (orderDTO.getType() != null && orderDTO.getType().equals(0L)) {
            InfoAddress usadd = infoAddressService.getById(orderDTO.getShdzId());
            if (usadd == null) {
                return error(MessageUtils.message("no.address.not.exist"));
            } else {
                usdizhi.put("name", usadd.getName());
                usdizhi.put("phone", usadd.getPhone());
                usdizhi.put("address", usadd.getAddress());
                usdizhi.put("country", usadd.getCountry());
                usdizhi.put("province", usadd.getProvince());
                usdizhi.put("city", usadd.getCity());
                usdizhi.put("area", usadd.getArea());
                usdizhi.put("longitude", String.valueOf(usadd.getLongitude()));
                usdizhi.put("latitude", String.valueOf(usadd.getLatitude()));
            }
        }
        if (hourslist.size() == 0) {
            return error(MessageUtils.message("no.mendian.not.set.business.hours"));
        }
        if (store.getState() == 1) {
            return error(MessageUtils.message("no.mendian.is.closed"));
        }
        //是否在上班时间内（按星期几和是否营业过滤）
        boolean isOperating = OperatingUtil.storeIsOperatingOfDay(hourslist);
        if (!isOperating) {
            return error(MessageUtils.message("no.mendian.is.closed"));
        }
        //订单金额限制100万改为200万
        if (orderDTO.getCollectPayment().equals("1") && orderDTO.getAmount() > 2000000) {
            return error(MessageUtils.message("no.cash_on_delivery_amount.exceed.limit_amount"));
        }
        QueryWrapper<PosOrder> query = new QueryWrapper<>();
        query.eq("user_id", id);
        query.eq("collect_payment", "1");
        query.notIn("state", 5, 10, 11);
        List<PosOrder> posOrders = posOrderService.list(query);
        System.out.println("到付信息：user_id=" + id + " ,到付数量:" + posOrders.size());
        //到付能存在2单未完成，第3单弹出提示
        if (posOrders.size() >= 2 && orderDTO.getCollectPayment().equals("1")) {
            return error(MessageUtils.message("no.exist.cash_on_delivery_order.incomplete"));
        }
        JSONArray jsonArray = orderDTO.getFoodlist();
        Map<Long, Long> map = new HashMap<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            Long foodid = jsonArray.getJSONObject(i).getLong("id");
            PosFood food = posFoodService.getById(foodid);
            if (food == null) {
                return error(jsonArray.getJSONObject(i).getString("name") + MessageUtils.message("no.goods.not.exist"));
            } else {
                if (food.getStackingUp().equals("1")) {
                    return error(food.getName() + MessageUtils.message("no.goods.is.off.shelf"));
                }
            }
            Long num = jsonArray.getJSONObject(i).getLong("number");
            map.put(foodid, num);
        }
        VipUserQuanyi yh = null;
        VipUserQuanyi mdYh = null;
        if (ObjectUtil.isNotNull(orderDTO.getYhId()) && ObjectUtil.notEqual(orderDTO.getYhId(), 0L)) {
            LambdaQueryWrapper<VipUserQuanyi> yhQuery = new LambdaQueryWrapper<>();
            yhQuery.eq(VipUserQuanyi::getId, orderDTO.getYhId());
            yh = userQuanyiService.getOne(yhQuery);
            if (yh == null) {
                throw new ServiceException("no.userquanyi.not.exist");
            }
            if (yh.getState().equals("1")) {
                throw new ServiceException("userquanyi.isUsed");
            }
        }
        if (ObjectUtil.isNotNull(orderDTO.getMdYhId()) && ObjectUtil.notEqual(orderDTO.getMdYhId(), 0L)) {
            LambdaQueryWrapper<VipUserQuanyi> mdYhquery = new LambdaQueryWrapper<>();
            mdYhquery.eq(VipUserQuanyi::getId, orderDTO.getMdYhId());
            mdYh = userQuanyiService.getOne(mdYhquery);
            if (mdYh == null) {
                throw new ServiceException("no.userquanyi.not.exist");
            }
            if (mdYh.getState().equals("1")) {
                throw new ServiceException("userquanyi.isUsed");
            }
        }
        SalesPromotion activity = null;
        SalesPromotion mdActivity = null;
        if (ObjectUtil.isNotNull(orderDTO.getActivity()) && ObjectUtil.notEqual(orderDTO.getActivity(), 0L)) {
            LambdaQueryWrapper<SalesPromotion> saleQuery = new LambdaQueryWrapper<>();
            saleQuery.eq(SalesPromotion::getId, orderDTO.getActivity());
            activity = salesPromotionService.getOne(saleQuery);
            if (activity == null) {
                throw new ServiceException("no.activity.not.exist");
            }
//            if (yh.getState().equals("1")) {
//                throw new ServiceException("userquanyi.isUsed");
//            }
        }
        if (ObjectUtil.isNotNull(orderDTO.getMdActivity()) && ObjectUtil.notEqual(orderDTO.getMdActivity(), 0L)) {
            LambdaQueryWrapper<SalesPromotion> saleQuery = new LambdaQueryWrapper<>();
            saleQuery.eq(SalesPromotion::getId, orderDTO.getMdActivity());
            mdActivity = salesPromotionService.getOne(saleQuery);

            if (mdActivity == null) {
                throw new ServiceException("no.activity.not.exist");
            }

        }
        PosOrder posOrder = new PosOrder();
        AjaxResult posOrderResult = redeePoints(orderDTO, Long.valueOf(id));
        if (!posOrderResult.get("code").equals(200)) {
            return posOrderResult;
        } else {
            posOrder.setPoints(orderDTO.getPoints());
            posOrder.setPointsReduction(orderDTO.getPointsReduction());
        }
        posOrder.setDdId(orderDTO.getDdId());
        posOrder.setShId(orderDTO.getShId());
        posOrder.setMdId(orderDTO.getMdId());
        posOrder.setShdzId(orderDTO.getShdzId());
        posOrder.setShAddress(JSON.toJSONString(usdizhi));
        posOrder.setUserId(Long.valueOf(id));
        posOrder.setAmount(orderDTO.getAmount());
        posOrder.setRemarks(orderDTO.getRemarks());
        posOrder.setType(orderDTO.getType());
        posOrder.setDelryTime(orderDTO.getDelryTime());
        posOrder.setFood(jsonArray.toString());
        posOrder.setState(0L);

        posOrder.setJvli(orderDTO.getJvli());
        posOrder.setFreight(orderDTO.getFreight());
        posOrder.setLongitude(orderDTO.getLongitude());
        posOrder.setLatitude(orderDTO.getLatitude());
        posOrder.setDiningStatus(orderDTO.getDiningStatus());
        posOrder.setQsId(orderDTO.getQsId());
        posOrder.setJuli(orderDTO.getJuli());
        posOrder.setPayUrl(orderDTO.getPayUrl());
        posOrder.setCollectPayment(orderDTO.getCollectPayment());
        posOrder.setAfterSaleStatus(0L);
        posOrder.setDeliveryStatus(Long.valueOf(0L).equals(orderDTO.getType()) ? 0L : null);
        posOrder.setPayStatus(Long.valueOf(0L).equals(orderDTO.getType())
                && "1".equals(orderDTO.getCollectPayment()) ? 1L : 0L);

        // posOrder.setCretim(dateUtil.getDatetim(orderDTO.getCretim()));
        //创建时间改成后端生成
        posOrder.setCretim(new Date());

        if (yh != null) {
            posOrder.setYhName(yh.getName());
            posOrder.setYhId(orderDTO.getYhId());
            posOrder.setDiscountAmount(orderDTO.getDiscountAmount());
        }

        if (mdYh != null) {
            posOrder.setMdYhId(orderDTO.getMdYhId());
            posOrder.setMdYhName(mdYh.getName());
            posOrder.setMdDiscountAmount(orderDTO.getMdDiscountAmount());
        }

        if (mdActivity != null) {
            posOrder.setMdActivity(orderDTO.getMdActivity());
            posOrder.setMdSalesName(mdActivity.getSalesName());
            posOrder.setMdSalesReduction(orderDTO.getMdSalesReduction());
        }
        if (activity != null) {
            posOrder.setActivity(orderDTO.getActivity());
            posOrder.setSalesName(activity.getSalesName());
            posOrder.setSalesReduction(orderDTO.getSalesReduction());
        }
        //设置支付类型为货到付款
        if ("1".equals(posOrder.getCollectPayment())) {
            posOrder.setPayType("1");
        }
        Boolean org = posOrderService.saveOrUpdate(posOrder);
        foodStatistics(map);
        if (org) {
            QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", id);
            queryWrapper.eq("dd_id", posOrder.getDdId());
            UserBilling billing = userBillingService.getOne(queryWrapper);
            if (billing == null) {
                UserBilling usb = new UserBilling();
                usb.setUserId(Long.valueOf(id));
                usb.setDdId(String.valueOf(posOrder.getDdId()));
                usb.setMdId(posOrder.getMdId());
                usb.setState("3");
                usb.setType("3");
                userBillingService.saveOrUpdate(usb);
            }
            QueryWrapper<UserFootprint> Wrapper = new QueryWrapper<>();
            Wrapper.eq("user_id", id);
            Wrapper.eq("md_id", posOrder.getMdId());
            UserFootprint foot = userFootprintService.getOne(Wrapper);
            DateUtil dateString = new DateUtil();
            if (foot == null) {
                UserFootprint usf = new UserFootprint();
                usf.setUserId(Long.valueOf(id));
                usf.setMdId(posOrder.getMdId());
                usf.setCretim(dateString.GetDate());
                userFootprintService.saveOrUpdate(usf);
            } else {
                foot.setCretim(dateString.GetDate());
                userFootprintService.saveOrUpdate(foot);
            }
            QueryWrapper<PosOrder> querywra = new QueryWrapper<>();
            querywra.eq("dd_id", posOrder.getDdId());
            PosOrder order = posOrderService.getOne(querywra);
            //货到付款、类型外卖，推送给骑手有新订单了
            if (order.getCollectPayment().equals("1") && order.getType() == 0) {
                sendHdfkMessage(order);
            }

            //存在使用优惠券的话，核销优惠券
            redeemCoupons(yh, mdYh, order.getDdId());
            System.out.println("========== 输出的order ==========");
            System.out.println(mapper.writeValueAsString(order));
            long methodEnd = System.currentTimeMillis(); // 方法结束时间
            System.out.println("addorder 方法总执行耗时: " + (methodEnd - methodStart) + " ms");
            return success(MessageUtils.message("no.order.submit.success"), order);
        } else {
            long methodEnd = System.currentTimeMillis(); // 方法结束时间
            System.out.println("addorder 方法总执行耗时: " + (methodEnd - methodStart) + " ms");
            return error();
        }
    }




    //统计美食销售量
    private void foodStatistics(Map<Long, Long> map) {
        for (Map.Entry<Long, Long> entry : map.entrySet()) {
            Long key = entry.getKey();
            Long value = entry.getValue();
            // 使用数据库原子UPSERT，避免并发下的竞态问题
            foodStatisticsService.increaseNumber(key, value);
        }
    }

    /**
     * 货到付款发送推送
     *
     * @param order
     */
    private void sendHdfkMessage(PosOrder order) {
        deliveryOrderNotificationService.notifyOrderAvailable(order);
    }

    //核销积分
    private AjaxResult redeePoints(OrderDTO orderDTO, Long userId) {
        if (ObjectUtil.isNotNull(orderDTO.getPoints()) && ObjectUtil.notEqual(orderDTO.getPoints(), 0) && ObjectUtil.isNotNull(orderDTO.getPointsReduction()) && ObjectUtil.notEqual(orderDTO.getPointsReduction(), 0)) {
            SysPointControl control = pointControlService.getById(1L);
            if (!control.getOrderUseEnable().equals(1L)) {
                throw new ServiceException(MessageUtils.message("no.points.use.enable"));
            }
            LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
            walletQuery.eq(UserWallet::getUserId, userId);
            walletQuery.isNull(UserWallet::getStoreId);
            UserWallet userWallet = userWalletService.getOne(walletQuery);
            if (ObjectUtil.isNotNull(userWallet)) {
                if (userWallet.getPointsWallet().compareTo(Long.valueOf(orderDTO.getPoints())) >= 0) {
                    walletQuery.eq(UserWallet::getVersion, userWallet.getVersion());
                    userWallet.setPointsWallet(userWallet.getPointsWallet() - orderDTO.getPoints());
                    userWallet.setVersion(userWallet.getVersion() + 1);
                    boolean update = userWalletService.update(userWallet, walletQuery);
                    createPointTransaction(userId, Long.valueOf(orderDTO.getPoints()), userWallet.getPointsWallet(), orderDTO.getDdId().toString(), "1");
                    if (!update) {
                        throw new ServiceException(MessageUtils.message("no.points.update.fail"));
                    }
                } else {
                    throw new ServiceException(MessageUtils.message("no.points.insufficient"));
                }
            } else {
                throw new ServiceException(MessageUtils.message("no.points.not.exist"));
            }
        }
        return success();
    }

    /**
     * 创建积分流水
     */
    private void createPointTransaction(Long userid, Long pointsChange, Long currentPoints, String ddId, String type) {
        PointsTransaction pointsTransaction = new PointsTransaction();
        pointsTransaction.setUserId(userid);
        if (type.equals("1")) {
            pointsTransaction.setPointsChange("-" + pointsChange);
            pointsTransaction.setType("1");
        }
        if (type.equals("2")) {
            pointsTransaction.setPointsChange("+" + pointsChange);
            pointsTransaction.setType("2");
        }
        pointsTransaction.setCurrentPoints(currentPoints.toString());
        pointsTransaction.setDdId(ddId);
        pointsTransaction.setCreateTime(new Date());
        pointsTransactionService.save(pointsTransaction);
    }


    /**
     * 核销优惠券
     *
     * @param orderId
     */
    private void redeemCoupons(VipUserQuanyi yh, VipUserQuanyi mdYh, Long orderId) {
        if (ObjectUtil.isNotNull(yh)) {
            yh.setState("1");
            yh.setOrderId(String.valueOf(orderId));
            yh.setUpdateTime(new Date());
            userQuanyiService.saveOrUpdate(yh);
        }
        if (ObjectUtil.isNotNull(mdYh)) {
            mdYh.setState("1");
            mdYh.setOrderId(String.valueOf(orderId));
            mdYh.setUpdateTime(new Date());
            userQuanyiService.saveOrUpdate(mdYh);
        }
    }


    /**
     * 核销优惠券
     *
     * @param orderId
     */
    private void redeemCoupons(VipUserQuanyi yh, VipUserQuanyi mdYh, String orderId) {
        if (ObjectUtil.isNotNull(yh)) {
            yh.setState("1");
            yh.setOrderId(orderId);
            yh.setUpdateTime(new Date());
            userQuanyiService.saveOrUpdate(yh);
        }
        if (ObjectUtil.isNotNull(mdYh)) {
            mdYh.setState("1");
            mdYh.setOrderId(orderId);
            mdYh.setUpdateTime(new Date());
            userQuanyiService.saveOrUpdate(mdYh);
        }
    }

    /**
     * 查询posorder列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:list')")
    @GetMapping("/list")
    public TableDataInfo list(PosOrder posOrder) {
        startPage();
        String[] dr = posOrder.getDateRange();
        if (dr != null && dr.length == 2) {
            posOrder.setCretimStart(dr[0]);
            posOrder.setCretimEnd(dr[1]);
        }
        List<PosOrder> list = posOrderService.selectPosOrderList(posOrder);
        if (list != null && list.size() > 0) {
            for (PosOrder od : list) {
                JSONArray foodArr = JSONArray.parseArray(od.getFood());
                long priceAll = 0L;
                for (int i = 0; i < foodArr.size(); i++) {
                    JSONObject obj = foodArr.getJSONObject(i);
                    BigDecimal price = obj.getBigDecimal("price");
                    if (price == null) continue;
                    Integer priceDb = price.intValue();
                    BigDecimal otherprice = obj.getBigDecimal("otherPrice");
                    if (otherprice != null && otherprice.doubleValue() > 0) {
                        priceDb += otherprice.intValue();
                    }
                    Long num = obj.getLong("number");
                    if (num == null) continue;
                    priceAll += (priceDb * num.longValue());
                }
                od.setPriceAll(priceAll + "");
                Long atv = od.getActivity();
                if (atv != null && atv.longValue() > 0) {
                    SalesPromotion salesPromotion = salesPromotionService.getById(atv);
                    if (salesPromotion != null) {
                        od.setSalesName(salesPromotion.getSalesName());
//                        od.setSalesReduction(""+salesPromotion.getSalesReduction());
                    }
                }
            }
        }
        return getDataTable(list);
    }

    /**
     * 查询sh posorder列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:shlist1')")
    @GetMapping("/shlist1")
    public TableDataInfo shlist1(PosOrder posOrder) {
        startPage();
        String[] dr = posOrder.getDateRange();
        if (dr != null && dr.length == 2) {
            posOrder.setCretimStart(dr[0]);
            posOrder.setCretimEnd(dr[1]);
        }
        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
        if (list != null && list.size() > 0) {
            for (PosOrder od : list) {
                //查询用户留言
                PosAppeal posAppeal = new PosAppeal();
                posAppeal.setDdId(od.getDdId());
                posAppeal.setUserType("0");
                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
                int s = 0;
                if (aplist != null) s = aplist.size();
                od.setAppealCount(s + "");
            }
        }
        return getDataTable(list);
    }

    /**
     * 查询sh posorder列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:shlist2')")
    @GetMapping("/shlist2")
    public TableDataInfo shlist2(PosOrder posOrder) {
        startPage();
        String[] dr = posOrder.getDateRange();
        if (dr != null && dr.length == 2) {
            posOrder.setCretimStart(dr[0]);
            posOrder.setCretimEnd(dr[1]);
        }
        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
        if (list != null && list.size() > 0) {
            for (PosOrder od : list) {
                //查询用户留言
                PosAppeal posAppeal = new PosAppeal();
                posAppeal.setDdId(od.getDdId());
                posAppeal.setUserType("1");
                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
                int s = 0;
                if (aplist != null) s = aplist.size();
                od.setAppealCount(s + "");
            }
        }
        return getDataTable(list);
    }

    /**
     * 查询sh posorder列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:shlist3')")
    @GetMapping("/shlist3")
    public TableDataInfo shlist3(PosOrder posOrder) {
        startPage();
        String[] dr = posOrder.getDateRange();
        if (dr != null && dr.length == 2) {
            posOrder.setCretimStart(dr[0]);
            posOrder.setCretimEnd(dr[1]);
        }
        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
        if (list != null && list.size() > 0) {
            for (PosOrder od : list) {
                //查询用户留言
                PosAppeal posAppeal = new PosAppeal();
                posAppeal.setDdId(od.getDdId());
                posAppeal.setUserType("2");
                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
                int s = 0;
                if (aplist != null) s = aplist.size();
                od.setAppealCount(s + "");
            }
        }
        return getDataTable(list);
    }

    /**
     * 导出posorder列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:export')")
    @Log(title = "posorder", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, PosOrder posOrder) {
        List<PosOrder> list = posOrderService.selectPosOrderList(posOrder);
        if (list != null && list.size() > 0) {
            for (PosOrder od : list) {
                JSONArray foodArr = JSONArray.parseArray(od.getFood());
                long priceAll = 0L;
                for (int i = 0; i < foodArr.size(); i++) {
                    JSONObject obj = foodArr.getJSONObject(i);
                    BigDecimal price = obj.getBigDecimal("price");
                    if (price == null) continue;
                    Integer priceDb = price.intValue();
                    //商品规格价格
                    BigDecimal otherprice = obj.getBigDecimal("otherPrice");
                    if (otherprice != null && otherprice.doubleValue() > 0) {
                        priceDb += otherprice.intValue();
                    }
                    Long num = obj.getLong("number");
                    if (num == null) continue;
                    priceAll += (priceDb * num.longValue());
                }
                od.setPriceAll(priceAll + "");
                Long atv = od.getActivity();
                if (atv != null && atv.longValue() > 0) {
                    SalesPromotion salesPromotion = salesPromotionService.getById(atv);
                    if (salesPromotion != null) {
                        od.setSalesName(salesPromotion.getSalesName());
//                        od.setSalesReduction(""+salesPromotion.getSalesReduction());
                    }
                }
            }
        }
        ExcelUtil<PosOrder> util = new ExcelUtil<PosOrder>(PosOrder.class);
        util.exportExcel(response, list, MessageUtils.message("no.export.excel.posorder"));
    }

    /**
     * 获取posorder详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:order:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(posOrderService.selectPosOrderById(id));
    }

    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @GetMapping("/{id}/status-context")
    public AjaxResult getStatusContext(@PathVariable Long id) {
        return success(orderLifecycleService.getStatusContext(id));
    }

    @PreAuthorize("@ss.hasPermi('system:order:linePaymentReconcile')")
    @RepeatSubmit(interval = 2000, message = "查询过于频繁")
    @PostMapping("/{id}/line-payment/reconcile")
    public AjaxResult adminReconcileLinePayment(@PathVariable Long id) {
        AdminOrderStatusContext context = orderLifecycleService.getStatusContext(id);
        if (context.getLinePaymentId() == null) {
            throw new ServiceException("LINE Pay 流水不存在");
        }
        String status = linePayService.reconcilePayment(context.getLinePaymentId(), "ADMIN");
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("status", status);
        data.put("context", orderLifecycleService.getStatusContext(id));
        return success("LINE Pay 状态查询完成", data);
    }

    @PreAuthorize("@ss.hasPermi('system:order:lineRefund')")
    @RepeatSubmit(interval = 2000, message = "请求过于频繁")
    @PostMapping("/{id}/line-refund")
    public AjaxResult adminRefundLinePayment(@PathVariable Long id) {
        Long paymentId = orderLifecycleService.reserveLineRefund(id, "ADMIN");
        String status = linePayRefundService.requestFullRefund(paymentId, "ADMIN");
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("status", status);
        data.put("context", orderLifecycleService.getStatusContext(id));
        return success("LINE Pay 退款处理完成", data);
    }

    private String lineMessage(String key, String fallback) {
        try {
            return MessageUtils.message(key);
        } catch (RuntimeException ignored) {
            return fallback;
        }
    }

    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @PutMapping("/{id}/status")
    public AjaxResult adminUpdateStatus(@PathVariable Long id,
                                        @Valid @RequestBody AdminOrderStatusUpdateRequest request) {
        SysUser operator = currentAdmin();
        return success("修改成功", orderLifecycleService.updateStatus(id, request,
                operator == null ? null : operator.getUserId(), operatorName(operator)));
    }

    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @PostMapping("/{id}/offline-payment/confirm")
    public AjaxResult adminConfirmOfflinePayment(@PathVariable Long id,
                                                 @Valid @RequestBody AdminOrderActionRequest request) {
        SysUser operator = currentAdmin();
        return success("已确认线下收款", orderLifecycleService.confirmOfflinePayment(id, request,
                operator == null ? null : operator.getUserId(), operatorName(operator)));
    }

    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @PostMapping("/{id}/offline-refund/confirm")
    public AjaxResult adminConfirmOfflineRefund(@PathVariable Long id,
                                                @Valid @RequestBody AdminOrderActionRequest request) {
        SysUser operator = currentAdmin();
        return success("已确认线下退款", orderLifecycleService.confirmOfflineRefund(id, request,
                operator == null ? null : operator.getUserId(), operatorName(operator)));
    }

    /**
     * 新增posorder
     */
    @PreAuthorize("@ss.hasPermi('system:order:add')")
    @Log(title = "posorder", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody PosOrder posOrder) {
        return toAjax(posOrderService.insertPosOrder(posOrder));
    }

    /**
     * 修改posorder
     */
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @Log(title = "posorder", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody PosOrder posOrder) {
        if (posOrder == null || posOrder.getId() == null) {
            return error("订单ID不能为空");
        }
        if (posOrder.getState() != null || posOrder.getDeliveryStatus() != null
                || posOrder.getPayStatus() != null || posOrder.getAfterSaleStatus() != null
                || posOrder.getSdTime() != null) {
            return error("订单状态请使用状态专用操作");
        }
        return toAjax(posOrderService.updatePosOrder(posOrder));
    }

    private SysUser currentAdmin() {
        return SecurityUtils.getLoginUser() == null ? null : SecurityUtils.getLoginUser().getUser();
    }

    private String operatorName(SysUser operator) {
        return operator == null || operator.getNickName() == null ? "" : operator.getNickName();
    }

    /**
     * 订单取消、退款成功返回积分
     *
     * @param userId
     * @param ddId
     * @param points
     */
    public void returnPoints(Long userId, Long ddId, Long points) {
        LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
        walletQuery.eq(UserWallet::getUserId, userId);
        walletQuery.isNull(UserWallet::getStoreId);
        UserWallet userWallet = userWalletService.getOne(walletQuery);
        PointsTransaction transaction = pointsTransactionService.getOne(new LambdaQueryWrapper<PointsTransaction>().eq(PointsTransaction::getDdId, ddId.toString()).eq(PointsTransaction::getType, "2"));
        //该订单不存在退回的积分记录
        if (ObjectUtil.isNotNull(userWallet) && transaction == null) {
            walletQuery.eq(UserWallet::getVersion, userWallet.getVersion());
            userWallet.setPointsWallet(userWallet.getPointsWallet() + points);
            userWallet.setVersion(userWallet.getVersion() + 1);
            boolean update = userWalletService.update(userWallet, walletQuery);
            createPointTransaction(userId, Long.valueOf(points), userWallet.getPointsWallet(), ddId.toString(), "2");
            if (!update) {
                throw new ServiceException(MessageUtils.message("no.points.update.fail"));
            }
        } else {
            throw new ServiceException(MessageUtils.message("no.points.insufficient"));
        }
    }


    /**
     * 删除posorder
     */
    @PreAuthorize("@ss.hasPermi('system:order:remove')")
    @Log(title = "posorder", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(posOrderService.deletePosOrderByIds(ids));
    }

    /**
     * 测试推送消息
     *
     * @param cid
     * @return
     */

    @Anonymous
    @RequestMapping(value = "/testPushMessage", method = {RequestMethod.GET})
    public AjaxResult testPushMessage(String cid, String title, String content, String body) {
        PayPush push = new PayPush();
        push.qspush(cid, title, content, body);
        return AjaxResult.success();
    }


    /**
     * 获取配送中的订单位置信息
     */
    @Anonymous
    @Auth
    @GetMapping("/getPsOrdersPosition")
    public AjaxResult getPsOrdersPosition(@RequestHeader String token) {
        JwtUtil jwtUtil = new JwtUtil();
        String id = jwtUtil.getusid(token);
        List<OrderPositionInfo> result = new ArrayList<>();
        QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();

        wrapper.eq("user_id", id).apply("(pay_type!=1 and (state = 1 or state = 2 or state = 3 or state = 4) or (pay_type=1 and (state = 0 or state = 1 or state = 2 or state = 3 or state = 4)))").orderByDesc("cretim");
        List<PosOrder> list = posOrderService.list(wrapper);
        if (!list.isEmpty()) {
            List<Long> qsIds = list.stream().map(PosOrder::getQsId).collect(Collectors.toList());
            List<InfoUser> users = new ArrayList<>();
            if (!qsIds.isEmpty()) {
                LambdaQueryWrapper<InfoUser> userWrapper = new LambdaQueryWrapper<>();
                userWrapper.in(InfoUser::getUserId, qsIds);
                users = infoUserService.list(userWrapper);
            }
            List<Long> mdIds = list.stream().map(PosOrder::getMdId).collect(Collectors.toList());
            LambdaQueryWrapper<PosStore> mdWrapper = new LambdaQueryWrapper<PosStore>().in(PosStore::getId, mdIds);
            List<PosStore> stores = posStoreService.list(mdWrapper);
            List<RiderPosition> riderPositions = new ArrayList<>();
            if (!qsIds.isEmpty()) {
                riderPositions = riderPositionService.list(new LambdaQueryWrapper<RiderPosition>().in(RiderPosition::getRiderId, qsIds));
            }
            for (PosOrder posOrder : list) {
                OrderPositionInfo orderPositionInfo = new OrderPositionInfo();
                orderPositionInfo.setDdId(posOrder.getDdId());
                orderPositionInfo.setOrderState(posOrder.getState());
                orderPositionInfo.setDelryTime(posOrder.getDelryTime());
                orderPositionInfo.setYjsdTime(posOrder.getYjsdTime());
                orderPositionInfo.setDiningStatus(posOrder.getDiningStatus());
                orderPositionInfo.setPayType(posOrder.getPayType());

                if (posOrder.getQsId() != null) {
                    QsDto qsDto = new QsDto();
                    users.stream().filter(infoUser -> infoUser.getUserId().equals(posOrder.getQsId())).findFirst().ifPresent(user -> {
                        qsDto.setUserName(user.getUserName());
                        qsDto.setNickName(user.getNickName());
                    });
                    qsDto.setDelryTime(posOrder.getDelryTime());
                    orderPositionInfo.setQsInfo(qsDto);

                    PositionDto qsPosition = new PositionDto();
                    riderPositions.stream().filter(riderPosition -> riderPosition.getRiderId().equals(posOrder.getQsId())).findFirst().ifPresent(rPosition -> {
                        qsPosition.setLat(rPosition.getLatitude().toString());
                        qsPosition.setLng(rPosition.getLongitude().toString());
                    });
                    orderPositionInfo.setQsPosition(qsPosition);
                }
                PositionDto mdPosition = new PositionDto();
                stores.stream().filter(posStore -> posStore.getId().equals(Integer.valueOf(posOrder.getMdId().toString()))).findFirst().ifPresent(p -> {
                    mdPosition.setLat(p.getLatitude().toString());
                    mdPosition.setLng(p.getLongitude().toString());
                });
                orderPositionInfo.setMdPosition(mdPosition);

                Map map = JSON.parseObject(posOrder.getShAddress(), Map.class);
                PositionDto userPosition = new PositionDto();
                userPosition.setLat(map.get("latitude").toString());
                userPosition.setLng(map.get("longitude").toString());
                orderPositionInfo.setUserPosition(userPosition);

                result.add(orderPositionInfo);
            }
        }

        return AjaxResult.success(result);
    }


}
