package com.liquidnet.service.goblin.service.impl;

import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.request.CouponRefundRequest;
import com.liquidnet.common.third.sqb.param.response.data.CouponQueryData;
import com.liquidnet.common.third.sqb.param.response.data.CouponRefundData;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinSqbOrder;
import com.liquidnet.service.goblin.mapper.GoblinSqbOrderMapper;
import com.liquidnet.service.goblin.service.IGoblinSqbService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 收钱吧订单服务实现
 */
@Slf4j
@Service
public class GoblinSqbServiceImpl implements IGoblinSqbService {

    @Autowired
    private GoblinSqbRedisUtils goblinSqbRedisUtils;

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;

    @Autowired
    private GoblinMongoUtils goblinMongoUtils;

    @Autowired
    private QueueUtils queueUtils;

    @Autowired
    private SqbBiz sqbBiz;
    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /** 与下单结算 CheckoutItem.type 一致：1=自定义商品（按实付单价下单时） */
    private static final byte SQB_LINE_ITEM_TYPE_CUSTOM = 1;

    @Autowired
    private GoblinSqbOrderMapper goblinSqbOrderMapper;


    // ================================ 获取券码 ================================

    @Override
    public ResponseDto<GoblinSqbCouponVo> queryCoupon(String userId, String orderId) {
        log.info("[收钱吧券码] 开始获取 userId={}, orderId={}", userId, orderId);

        // 支付态以商城订单为准（收钱吧扩展状态仅用于核销等业务态）
        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) return ResponseDto.failure("订单不存在");
        if (!userId.equals(storeOrderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
        if (!(storeOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()
                || storeOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_4.getValue())) {
            return ResponseDto.failure("订单未支付，无法获取券码");
        }

        GoblinSqbOrderVo orderVo = getSqbOrderVoOrLoadFromDb(orderId);
        if (orderVo == null) {
            return ResponseDto.failure("订单不存在");
        }
        // 兜底：以商城订单的 userId 为准，这里仅防御脏数据
        if (orderVo.getUserId() != null && !userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");

        // 幂等：已存在则直接返回
        if (orderVo.getCouponQrCode() != null && !orderVo.getCouponQrCode().isEmpty()) {
            GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
            couponVo.setCouponSn(orderVo.getCouponSn());
            couponVo.setCouponQrCode(orderVo.getCouponQrCode());
            couponVo.setCouponExpireTime(orderVo.getCouponExpireTime());
            return ResponseDto.success(couponVo);
        }

        // 调用收钱吧查询券码
        List<CouponQueryData> couponList = sqbBiz.queryCoupon(orderVo.getSqbOrderSn(), orderVo.getSqbOrderSignature());
        if (CollectionUtils.isEmpty(couponList)) return ResponseDto.failure("暂无可用券码");
        CouponQueryData couponData = couponList.get(0);

        // 更新订单 coupon 字段
        String now = LocalDateTime.now().format(DTF);
        orderVo.setCouponSn(couponData.getVoucherNo());
        orderVo.setCouponQrCode(couponData.getUrl());
        orderVo.setCouponExpireTime(couponData.getOperationTime());
        orderVo.setUpdatedAt(now);
        goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
        // 券码信息保存在 Redis，MySQL和MongoDB商城基础模型无此字段，无需同步

        GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
        couponVo.setCouponSn(couponData.getVoucherNo());
        couponVo.setCouponQrCode(couponData.getUrl());
        couponVo.setCouponExpireTime(couponData.getOperationTime());

        log.info("[收钱吧券码] 获取成功，orderId={}", orderId);
        return ResponseDto.success(couponVo);
    }

    // ================================ 申请退款 ================================

    @Override
    public ResponseDto<Boolean> refund(String userId, String orderId, String reason) {
        log.info("[收钱吧-退款] 开始 userId={}, orderId={}", userId, orderId);

        // 与详情接口一致：先主单 store + 商品，再收钱吧扩展；避免扩展单缺失却提示「订单不存在」
        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        }
        if (!userId.equals(storeOrderVo.getUserId())) {
            return ResponseDto.failure("无权限访问该订单");
        }
        Integer storeSt = storeOrderVo.getStatus();
        if (Integer.valueOf(GoblinStatusConst.Status.ORDER_STATUS_4.getValue()).equals(storeSt)) {
            return ResponseDto.failure("订单已完成（含券已核销），不可退款");
        }
        if (Integer.valueOf(GoblinStatusConst.Status.ORDER_STATUS_6.getValue()).equals(storeSt)) {
            return ResponseDto.failure("订单已退款，不可重复退款");
        }
        boolean isRetry = Integer.valueOf(GoblinStatusConst.Status.ORDER_STATUS_61.getValue()).equals(storeSt);
        if (!isRetry && !Integer.valueOf(GoblinStatusConst.Status.ORDER_STATUS_2.getValue()).equals(storeSt)) {
            return ResponseDto.failure("订单状态不可退款");
        }
        List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
        if (CollectionUtils.isEmpty(orderSkuVoIds)) {
            return ResponseDto.failure("订单数据异常");
        }
        GoblinOrderSkuVo firstSkuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
        if (firstSkuVo == null) {
            return ResponseDto.failure("订单商品数据异常");
        }
        if (!Integer.valueOf(33).equals(firstSkuVo.getSkuType())) {
            return ResponseDto.failure("该订单非收钱吧订单");
        }

        GoblinSqbOrderVo orderVo = getSqbOrderVoOrLoadFromDb(orderId);
        if (orderVo == null) {
            return ResponseDto.failure("收钱吧扩展订单未找到，无法退款");
        }
        if (!userId.equals(orderVo.getUserId())) {
            return ResponseDto.failure("无权限访问该订单");
        }
        if (Integer.valueOf(1).equals(orderVo.getCouponUsedStatus())) {
            return ResponseDto.failure("券码已核销，不可退款");
        }

        // 首次申请：置退款中；卡单重试(已是61)：不改主单状态，避免刷新 updated_at
        if (!isRetry) {
            String now = LocalDateTime.now().format(DTF);
            orderVo.setUpdatedAt(now);
            goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
            syncOrderStatus(orderId, 4);
        }

        List<GoblinOrderSkuVo> orderSkuVos = new ArrayList<>();
        for (String skuVoId : storeOrderVo.getOrderSkuVoIds()) {
            GoblinOrderSkuVo goblinOrderSkuVo = goblinRedisUtils.getGoblinOrderSkuVo(skuVoId);
            if (null != goblinOrderSkuVo) {
                orderSkuVos.add(goblinOrderSkuVo);
            }
        }

        try {
            CouponRefundData refundData = sqbBiz.refundCoupon(orderVo.getSqbOrderSn(),
                    orderVo.getSqbOrderSignature(),
                    orderVo.getAmount(),
                    (byte) 2, // 2-按金额退款
                    buildRefundItem(orderSkuVos), // 需要构建退款商品
                    reason,
                    buildRequestId(IDGenerator.nextSnowId())
            );
            log.info("[收钱吧-退款] 收钱吧退款响应: {}, orderId: {}, isRetry={}.", JsonUtils.toJson(refundData), orderId, isRetry);
            if (refundData == null) {
                if (!isRetry) {
                    // 首次申请失败：回滚为已支付
                    orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
                    goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
                    syncOrderStatus(orderId, 1);
                } else {
                    log.warn("[收钱吧-退款] 卡单重试失败，保持退款中，orderId={}", orderId);
                }
                return ResponseDto.failure("退款失败，请稍后重试");
            }

            // 调收钱吧成功：写退款号；库存只在退款回调 targetState=20 时回（避免申请成功+回调各回一次）
            orderVo.setRefundSn(refundData.getTicketsSn());
            orderVo.setRefundSignature(refundData.getTicketSignature());
            orderVo.setRefundReason(reason);
            orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
            goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);

//            syncOrderStatus(orderId, 3);
            log.info("[收钱吧-退款] 调用收钱吧退款成功，orderId={}, isRetry={}", orderId, isRetry);
            return ResponseDto.success(Boolean.TRUE);

        } catch (Exception e) {
            if (!isRetry) {
                log.error("[收钱吧退款] 退款异常，orderId={}，回滚主单为已支付", orderId, e);
                orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
                goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
                syncOrderStatus(orderId, 1);
            } else {
                log.error("[收钱吧退款] 卡单重试异常，保持退款中，orderId={}", orderId, e);
            }
            return ResponseDto.failure("退款失败：" + e.getMessage());
        }
    }

    private List<CouponRefundRequest.RefundItem> buildRefundItem(List<GoblinOrderSkuVo> orderSkuVos) {
        List<CouponRefundRequest.RefundItem> refundItems = new ArrayList<>();
        for (GoblinOrderSkuVo orderSkuVo : orderSkuVos) {

            GoblinSqbGoodsExtVo sqbGoodsExt = goblinSqbRedisUtils.getSqbGoodsExt(orderSkuVo.getSpuId(), orderSkuVo.getSkuId());
            if (sqbGoodsExt == null) {
                log.error("[buildRefundItem] 收钱吧扩展参数为空, spuId: {}, skuId: {}", orderSkuVo.getSpuId(), orderSkuVo.getSkuId());
                continue;
            }

            CouponRefundRequest.RefundItem item = new CouponRefundRequest.RefundItem();
            item.setSpuId(sqbGoodsExt.getSqbSpuId());
            item.setSkuId(sqbGoodsExt.getSqbSkuId());
            item.setTitle(orderSkuVo.getSkuName());
            item.setImg(orderSkuVo.getSkuImage());
            item.setQuantity(String.valueOf(orderSkuVo.getNum()));
            item.setType(SQB_LINE_ITEM_TYPE_CUSTOM);
            refundItems.add(item);
        }
        return refundItems;
    }

    // ================================ 同步核销状态 ================================

    @Override
    public ResponseDto<Boolean> syncCouponStatus(String userId, String orderId) {
        log.info("[收钱吧核销同步] 开始 userId={}, orderId={}", userId, orderId);

        GoblinSqbOrderVo orderVo = getSqbOrderVoOrLoadFromDb(orderId);
        if (orderVo == null) {
            return ResponseDto.failure("收钱吧扩展订单未找到");
        }
        if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");

        boolean couponUsed = sqbBiz.syncCouponStatus(sqbBiz.getSqbConfig().getMerchantId(),
                Collections.singletonList(orderVo.getCouponSn()),
                buildRequestId(IDGenerator.nextSnowId()),
                "terminal_001",
                (byte) 1);
        if (couponUsed) {
            String now = LocalDateTime.now().format(DTF);
            orderVo.setCouponUsedStatus(1);
            orderVo.setUpdatedAt(now);
            goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
            syncOrderStatus(orderId, 2);
            log.info("[收钱吧核销同步] 核销成功，orderId={}", orderId);
        }
        return ResponseDto.success(couponUsed);
    }

    // ================================ 自动退款（定时任务） ================================

    @Override
    public ResponseDto<String> autoRefundByPerformance(String performancesId) {
        String pid = performancesId == null ? null : performancesId.trim();
        if (pid != null && pid.isEmpty()) {
            pid = null;
        }
        if (pid == null) {
            log.warn("[收钱吧自动退款] performancesId 为空，将处理库内所有符合条件候选单（演出结束已支付 / 退款中超8小时）");
        } else {
            log.info("[收钱吧自动退款] 开始 performancesId={}", pid);
        }

        List<GoblinSqbOrder> orders = goblinSqbOrderMapper.selectAutoRefundCandidates(pid);
        if (CollectionUtils.isEmpty(orders)) {
            String scope = pid != null ? ("演出 " + pid) : "全库";
            String summary = scope + " 无待自动退款的收钱吧扩展单";
            log.info("[收钱吧自动退款] {}", summary);
            return ResponseDto.success(summary);
        }

        int successCount = 0;
        int failCount = 0;

        for (GoblinSqbOrder order : orders) {
            String orderId = order.getOrderId();
            String userId = order.getUserId();
            if (orderId == null || orderId.trim().isEmpty() || userId == null || userId.trim().isEmpty()) {
                log.warn("[收钱吧自动退款] 扩展单缺少 orderId/userId，跳过 mid={}", order.getMid());
                failCount++;
                continue;
            }
            try {
                ResponseDto<Boolean> result = refund(userId, orderId, "演出结束自动退款");
                if (result != null && result.isSuccess() && Boolean.TRUE.equals(result.getData())) {
                    successCount++;
                } else {
                    log.warn("[收钱吧自动退款] 退款失败 orderId={}, msg={}", orderId,
                            result != null ? result.getMessage() : "null");
                    failCount++;
                }
            } catch (Exception e) {
                log.error("[收钱吧自动退款] 订单退款异常 orderId={}", orderId, e);
                failCount++;
            }
        }

        String scopeLabel = pid != null ? ("演出 " + pid) : "全库";
        String summary = String.format("%s 自动退款完成：成功 %d 笔，失败 %d 笔", scopeLabel, successCount, failCount);
        log.info("[收钱吧自动退款] {}", summary);
        return ResponseDto.success(summary);
    }

    // ================================ 订单列表 ================================

    @Override
    public ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList(String userId) {
        log.info("[收钱吧订单列表] userId={}", userId);

        List<String> orderIds = goblinSqbRedisUtils.getSqbOrderList(userId);
        if (CollectionUtils.isEmpty(orderIds)) {
            return ResponseDto.success(Collections.emptyList());
        }

        List<GoblinSqbOrderDetailVo> result = new ArrayList<>();
        for (String orderId : orderIds) {
            GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
            if (storeOrderVo == null) continue;

            // 取第一个 orderSkuId 判断 skuType
            List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
            if (CollectionUtils.isEmpty(orderSkuVoIds)) continue;
            GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
            if (skuVo == null) continue;

            // 过滤：只处理 skuType=33 的收钱吧订单
            if (!Integer.valueOf(33).equals(skuVo.getSkuType())) continue;

            GoblinSqbOrderVo sqbOrderVo = getSqbOrderVoOrLoadFromDb(orderId);
            result.add(buildDetailVo(storeOrderVo, skuVo, sqbOrderVo));
        }

        // 按创建时间倒序排列
        result.sort((a, b) -> {
            if (a.getCreatedAt() == null) return 1;
            if (b.getCreatedAt() == null) return -1;
            return b.getCreatedAt().compareTo(a.getCreatedAt());
        });

        log.info("[收钱吧订单列表] userId={}, 共 {} 条", userId, result.size());
        return ResponseDto.success(result);
    }

    // ================================ 订单详情 ================================

    @Override
    public ResponseDto<GoblinSqbOrderDetailVo> getOrderDetail(String userId, String orderId) {
        log.info("[收钱吧订单详情] userId={}, orderId={}", userId, orderId);

        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) return ResponseDto.failure("订单不存在");
        if (!userId.equals(storeOrderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");

        List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
        if (CollectionUtils.isEmpty(orderSkuVoIds)) return ResponseDto.failure("订单数据异常");
        GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
        if (skuVo == null) return ResponseDto.failure("订单商品数据异常");

        // 校验是收钱吧订单
        if (!Integer.valueOf(33).equals(skuVo.getSkuType())) {
            return ResponseDto.failure("该订单非收钱吧订单");
        }

        GoblinSqbOrderVo sqbOrderVo = getSqbOrderVoOrLoadFromDb(orderId);
        GoblinSqbOrderDetailVo detailVo = buildDetailVo(storeOrderVo, skuVo, sqbOrderVo);

        log.info("[收钱吧订单详情] 查询成功，orderId={}", orderId);
        return ResponseDto.success(detailVo);
    }


    // ================================ 私有辅助方法 ================================


    private GoblinSqbOrderDetailVo buildDetailVo(GoblinStoreOrderVo storeOrderVo,
                                                 GoblinOrderSkuVo skuVo,
                                                 GoblinSqbOrderVo sqbOrderVo) {
        GoblinSqbOrderDetailVo detailVo = new GoblinSqbOrderDetailVo();
        // 来自 GoblinStoreOrderVo
        detailVo.setOrderId(storeOrderVo.getOrderId());
        detailVo.setOrderCode(storeOrderVo.getOrderCode());
        detailVo.setStatus(storeOrderVo.getStatus());
        detailVo.setPriceActual(storeOrderVo.getPriceActual());
        detailVo.setCreatedAt(storeOrderVo.getCreatedAt());
        detailVo.setPayTime(storeOrderVo.getPayTime());
        // 来自 GoblinOrderSkuVo
        detailVo.setSpuId(skuVo.getSpuId());
        detailVo.setSpuName(skuVo.getSpuName());
        detailVo.setSkuId(skuVo.getSkuId());
        detailVo.setSkuName(skuVo.getSkuName());
        detailVo.setSkuImage(skuVo.getSkuImage());
        detailVo.setQuantity(skuVo.getNum());
        detailVo.setUpdateTime(sqbOrderVo.getUpdatedAt());
        // 来自 GoblinSqbOrderVo（Redis 或 DB；无扩展数据时券标记默认 0）
        if (sqbOrderVo != null) {
            detailVo.setPerformancesId(sqbOrderVo.getPerformancesId());
            detailVo.setSqbAcquiringSn(sqbOrderVo.getSqbAcquiringSn());
            detailVo.setCouponSn(sqbOrderVo.getCouponSn());
            detailVo.setCouponQrCode(sqbOrderVo.getCouponQrCode());
            detailVo.setCouponExpireTime(getPerformanceEndTime(sqbOrderVo.getPerformancesId())); // 取演出结束时间
            detailVo.setCouponUsedStatus(sqbOrderVo.getCouponUsedStatus() != null ? sqbOrderVo.getCouponUsedStatus() : 0);
        } else {
            detailVo.setCouponUsedStatus(0);
        }
        return detailVo;
    }

    private String getPerformanceEndTime(String performancesId) {
        KylinPerformanceVo kylinPerformanceVo = goblinMongoUtils.getKylinPerformanceVo(performancesId);
        if (null != kylinPerformanceVo) {
            return kylinPerformanceVo.getTimeEnd();
        }
        return "";
    }

    /**
     * 与列表/详情/查券码一致：Redis 无扩展单时从库加载并回写，避免仅因缓存未命中误判「订单不存在」。
     */
    private GoblinSqbOrderVo getSqbOrderVoOrLoadFromDb(String orderId) {
        GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
        if (orderVo == null) {
            orderVo = loadSqbOrderVoFromDb(orderId);
            if (orderVo != null) {
                goblinSqbRedisUtils.setSqbOrderForever(orderId, orderVo);
            }
        }
        return orderVo;
    }

    private GoblinSqbOrderVo loadSqbOrderVoFromDb(String orderId) {
        if (orderId == null || orderId.trim().isEmpty()) {
            return null;
        }
        try {
            LambdaQueryWrapper<GoblinSqbOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(GoblinSqbOrder::getOrderId, orderId).last("LIMIT 1");
            GoblinSqbOrder dbOrder = goblinSqbOrderMapper.selectOne(wrapper);
            if (dbOrder == null) {
                return null;
            }

            GoblinSqbOrderVo vo = new GoblinSqbOrderVo();
            vo.setOrderId(dbOrder.getOrderId());
            vo.setUserId(dbOrder.getUserId());
            vo.setPerformancesId(dbOrder.getPerformancesId());
            vo.setSpuId(dbOrder.getSpuId());
            vo.setSkuId(dbOrder.getSkuId());
            vo.setQuantity(dbOrder.getQuantity());
            vo.setAmount(dbOrder.getAmount());
            vo.setSqbOrderSn(dbOrder.getSqbOrderSn());
            vo.setSqbOrderSignature(dbOrder.getSqbOrderSignature());
            vo.setSqbAcquiringSn(dbOrder.getSqbAcquiringSn());
            vo.setSqbAcquiringSign(dbOrder.getSqbAcquiringSign());
            vo.setSqbCheckoutItemsId(dbOrder.getSqbCheckoutItemsId());
            vo.setCouponSn(dbOrder.getCouponSn());
            vo.setCouponQrCode(dbOrder.getCouponQrCode());
            vo.setCouponExpireTime(dbOrder.getCouponExpireTime());
            vo.setCouponUsedStatus(dbOrder.getCouponUsedStatus() != null ? dbOrder.getCouponUsedStatus() : 0);
            vo.setRefundReason(dbOrder.getRefundReason());
            vo.setRefundSn(dbOrder.getSqbRefundSn());
            vo.setRefundSignature(dbOrder.getSqbRefundSignature());
            vo.setCreatedAt(dbOrder.getCreatedAt());
            vo.setUpdatedAt(dbOrder.getUpdatedAt());
            return vo;
        } catch (Exception e) {
            log.warn("[收钱吧订单详情] sqbOrderVo 降级回源失败 orderId={}", orderId, e);
            return null;
        }
    }

    /**
     * 构建收钱吧请求唯一ID，规则：AppCode（4位）+ id，总长不超过40位。
     *
     * @param id 业务唯一标识（如雪花ID）
     * @return 不超过40位的请求ID字符串
     */
    private String buildRequestId(String id) {
        String appCode = sqbBiz.getSqbConfig().getAppCode();
        if (appCode == null) appCode = "";
        String raw = appCode + id;
        return raw.length() > 40 ? raw.substring(0, 40) : raw;
    }


    /**
     * 同步正在商品订单状态
     *
     * @param orderId
     * @param status
     */
    private void syncOrderStatus(String orderId, int status) {

        final int zhengzaiStatus = sqbOrderStatusConvert(status);

        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) return;

        String now = LocalDateTime.now().format(DTF);
        storeOrderVo.setStatus(zhengzaiStatus);
        if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) { // 支付成功
            storeOrderVo.setPayTime(now);
        }

        // 1. 同步 Redis
        goblinRedisUtils.setGoblinOrder(orderId, storeOrderVo);

        // 2. 同步 MongoDB
        goblinMongoUtils.updateGoblinStoreOrderVo(orderId, storeOrderVo);

        // 3. 同步 MySQL (复用下单 MQ 发送 Update 语句)
        String sql;
        Object[] data;
        if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
            sql = "UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ?";
            data = new Object[]{zhengzaiStatus, storeOrderVo.getPayTime(), now, orderId};
        } else {
            sql = "UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ?";
            data = new Object[]{zhengzaiStatus, now, orderId};
        }

        java.util.LinkedList<String> sqls = new java.util.LinkedList<>();
        sqls.add(sql);
        java.util.LinkedList<Object[]> sqlData = new java.util.LinkedList<>();
        sqlData.add(data);

        if (queueUtils != null) {
            queueUtils.sendMsgByRedis(com.liquidnet.service.base.constant.MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
                    com.liquidnet.service.base.SqlMapping.gets(sqls, sqlData));
        }
    }

    /**
     * 收钱吧业务事件码 → 商城主单 goblin_store_order.status
     *
     * @param sqbOrderStatus 0待支付 1已支付 2已核销(主单完成) 3已退款 4退款中 5取消 9失败
     */
    private int sqbOrderStatusConvert(Integer sqbOrderStatus) {
        if (null == sqbOrderStatus) {
            return -1;
        }
        switch (sqbOrderStatus) {
            case 0:
                // 0-待支付 -> 对应枚举 ORDER_STATUS_0
                return GoblinStatusConst.Status.ORDER_STATUS_0.getValue();

            case 1:
                // 1-已支付 -> 对应枚举 ORDER_STATUS_2 (代发货)
                return GoblinStatusConst.Status.ORDER_STATUS_2.getValue();

            case 2:
                // 2-已核销 -> 对应枚举 ORDER_STATUS_4 (已完成)
                return GoblinStatusConst.Status.ORDER_STATUS_4.getValue();

            case 3:
                // 3-已退款 -> 对应枚举 ORDER_STATUS_6 (退款通过)
                return GoblinStatusConst.Status.ORDER_STATUS_6.getValue();

            case 4:
                // 4-退款中 -> 对应枚举 ORDER_STATUS_61 (发起-退款)
                return GoblinStatusConst.Status.ORDER_STATUS_61.getValue();

            case 5:
                // 5-已取消 -> 对应枚举 ORDER_STATUS_5
                return GoblinStatusConst.Status.ORDER_STATUS_5.getValue();

            case 9:
                // 9-失败 -> 这里归类为 ORDER_STATUS_5 (取消/终态)，如有特殊需求可调整
                return sqbOrderStatus;
            default:
                return sqbOrderStatus;
        }
    }
}
