package com.gxwebsoft.glt.task;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.annotation.IgnoreTenant;
import com.gxwebsoft.common.core.enums.ShopDealerCapitalUpdateEnum;
import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.glt.entity.GltTicketTemplate;
import com.gxwebsoft.glt.service.GltTicketTemplateService;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper;
import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.util.UpstreamUserFinder;
import com.gxwebsoft.shop.vo.ShopDealerRefereeVO;
import com.gxwebsoft.shop.vo.ShopOrderGoodsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 租户10584：分销订单结算任务
 * <p>
 * 每10秒执行一次，查询“已付款且未结算”的订单，按指定规则计算佣金并先计入分销商冻结金额（freezeMoney），并将订单置为已结算。
 */
@Slf4j
@Component
public class DealerOrderSettlement10584Task {

    private static final Integer TENANT_ID = 10584;

    private static final BigDecimal RATE_0_10 = new BigDecimal("0.10");
    private static final BigDecimal RATE_0_05 = new BigDecimal("0.05");
    private static final BigDecimal RATE_0_02 = new BigDecimal("0.02");
    private static final BigDecimal RATE_0_01 = new BigDecimal("0.01");
    private static final BigDecimal TOTAL_DEALER_DIVIDEND_RATE = RATE_0_01;

    private static final int MAX_ORDERS_PER_RUN = 50;
    private static final int MAX_REFEREE_CHAIN_DEPTH = 20;
    private static final int DIVIDEND_SCALE = 3;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private ShopOrderService shopOrderService;

    @Resource
    private ShopDealerRefereeService shopDealerRefereeService;

    @Resource
    private ShopDealerUserService shopDealerUserService;

    @Resource
    private ShopDealerCapitalService shopDealerCapitalService;

    @Resource
    private ShopDealerOrderService shopDealerOrderService;

    @Resource
    private ShopDealerSettingService shopDealerSettingService;

    @Resource
    private ShopGoodsService shopGoodsService;

    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private GltTicketTemplateService gltTicketTemplateService;

    @Resource
    private ShopOrderMapper shopOrderMapper;

    @Resource
    private ShopDealerRefereeMapper shopDealerRefereeMapper;

    /**
     * 每10秒执行一次。
     */
//    @Scheduled(cron = "0/10 * * * * ?")
    @IgnoreTenant("该定时任务仅处理租户10584，但需要显式按tenantId过滤，避免定时任务线程无租户上下文导致查询异常")
    public void settleTenant10584Orders() {
        try {
            //获取水票模板对应的商品信息列表
            Set<Integer> waterFormIds = loadWaterFormIds();

            //查询商品列表存在已支付未核销订单数据
            List<ShopOrder> orders = findUnsettledPaidOrders(waterFormIds);
            if (orders.isEmpty()) {
                return;
            }

            // Per-run caches to reduce DB chatter across orders.
            Map<Integer, Integer> level1ParentCache = new HashMap<>();
            Map<Integer, Boolean> shopRoleCache = new HashMap<>();

            //获取系统设置分销等级
            DealerBasicSetting dealerBasicSetting = findDealerBasicSetting();

            //获取分销员type=2第一个分销人作为平台总分红人
            ShopDealerUser totalDealerUser = findTotalDealerUser();
            if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
                log.warn("未找到分红账号，订单仍可结算但不会发放分红 - tenantId={}", TENANT_ID);
            }
            log.debug("租户{}分销设置 - level={}", TENANT_ID, dealerBasicSetting.level);

            log.info("租户{}待结算订单数: {}, orderNos(sample)={}",
                TENANT_ID,
                orders.size(),
                orders.stream().limit(10).map(ShopOrder::getOrderNo).toList());

            for (ShopOrder order : orders) {
                try {
                    transactionTemplate.executeWithoutResult(status -> {
                        // 先“认领”订单：并发/多实例下避免重复结算（update=0 表示被其他线程/实例处理）
                        //更新商品订单为已结算状态
                        if (!claimOrderToSettle(order.getOrderId(), waterFormIds)) {
                            return;
                        }
                        settleOneOrder(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
                    });
                } catch (Exception e) {
                    log.error("订单结算失败，将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
                }
            }
        } catch (Exception e) {
            log.error("租户{}分销订单结算任务执行失败", TENANT_ID, e);
        }
    }

    /**
     * 每10分钟执行一次。
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    @IgnoreTenant("该定时任务仅处理租户10584，但需要显式按tenantId过滤，避免定时任务线程无租户上下文导致查询异常")
    public void settleTenant10584OrdersV2() {
        try {
            //获取水票模板对应的商品信息列表
            Set<Integer> waterFormIds = loadWaterFormIds();

            //查询商品列表存在已支付未核销订单数据【isSettled = 0， payStatus= 1， orderStatus 不在列表（2, 3, 4, 5, 6, 7）】
            List<ShopOrder> orders = findUnsettledPaidOrders(waterFormIds);
            if (orders.isEmpty()) {
                return;
            }

            // Per-run caches to reduce DB chatter across orders.
            Map<Integer, Integer> level1ParentCache = new HashMap<>();
            Map<Integer, Boolean> shopRoleCache = new HashMap<>();

            //获取系统设置分销等级
            DealerBasicSetting dealerBasicSetting = findDealerBasicSetting();

            //获取分销员type=2第一个分销人作为平台总分红人
            ShopDealerUser totalDealerUser = findTotalDealerUser();
            if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
                log.warn("未找到分红账号，订单仍可结算但不会发放分红 - tenantId={}", TENANT_ID);
            }
            log.debug("租户{}分销设置 - level={}", TENANT_ID, dealerBasicSetting.level);

            log.info("租户{}待结算订单数: {}, orderNos(sample)={}",
                    TENANT_ID,
                    orders.size(),
                    orders.stream().limit(10).map(ShopOrder::getOrderNo).toList());

            for (ShopOrder order : orders) {
                try {
                    transactionTemplate.executeWithoutResult(status -> {
                        // 先“认领”订单：并发/多实例下避免重复结算（update=0 表示被其他线程/实例处理）
                        //更新商品订单为已结算状态
                        if (!claimOrderToSettle(order.getOrderId(), waterFormIds)) {
                            return;
                        }
                        settleOneOrderV2(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
                    });
                } catch (Exception e) {
                    log.error("订单结算失败，将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
                }
            }
        } catch (Exception e) {
            log.error("租户{}分销订单结算任务执行失败", TENANT_ID, e);
        }
    }

    /**
     * 订单分销金、分润金结算
     */
    @Transactional
    public void orderSettlement(String orderNo){
        LambdaQueryWrapper<ShopOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper<ShopOrder>().eq(ShopOrder::getOrderNo, orderNo).eq(ShopOrder::getIsSettled, 0).eq(ShopOrder::getPayStatus, 1);
        ShopOrder order = shopOrderService.getOne(orderLambdaQueryWrapper);
        if(order != null){
            //获取系统设置分销等级
            DealerBasicSetting dealerBasicSetting = findDealerBasicSetting();

            //获取分销员type=2第一个分销人作为平台总分红人
            ShopDealerUser totalDealerUser = findTotalDealerUser();

            Map<Integer, Integer> level1ParentCache = new HashMap<>();
            Map<Integer, Boolean> shopRoleCache = new HashMap<>();

            transactionTemplate.executeWithoutResult(status -> {
                // 先“认领”订单：并发/多实例下避免重复结算（update=0 表示被其他线程/实例处理）
                //更新商品订单为已结算状态
                if (!claimOrderToSettleV2(order.getOrderId())) {
                    return;
                }
                settleOneOrderV2(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
            });
        }
    }

    private List<ShopOrder> findUnsettledPaidOrders(Set<Integer> waterFormIds) {
        // 租户10584约定：
        // - 普通订单：以发货为准（deliveryStatus=20）才结算；
        // - 绑定水票模板的订单：支付成功即可体现分润（无需等发货状态变更）。
        LambdaQueryWrapper<ShopOrder> qw = new LambdaQueryWrapper<ShopOrder>()
            .eq(ShopOrder::getTenantId, TENANT_ID)
            .eq(ShopOrder::getDeleted, 0)
            .eq(ShopOrder::getPayStatus, true)
            .eq(ShopOrder::getIsSettled, 0)
            // 退款/取消订单不结算，避免“退款后仍发放分红/分润/佣金”
            .and(w -> w.notIn(ShopOrder::getOrderStatus, 2, 3, 4, 5, 6, 7).or().isNull(ShopOrder::getOrderStatus));

        if (waterFormIds != null && !waterFormIds.isEmpty()) {
            qw.and(w -> w.eq(ShopOrder::getDeliveryStatus, 20).or().in(ShopOrder::getFormId, waterFormIds));
        } else {
            qw.eq(ShopOrder::getDeliveryStatus, 20);
        }

        qw.orderByAsc(ShopOrder::getOrderId).last("limit " + MAX_ORDERS_PER_RUN);
        return shopOrderService.list(qw);
    }

    private boolean claimOrderToSettle(Integer orderId, Set<Integer> waterFormIds) {
        LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>()
            .eq(ShopOrder::getOrderId, orderId)
            .eq(ShopOrder::getTenantId, TENANT_ID)
            .eq(ShopOrder::getIsSettled, 0)
            // 二次防御：退款/取消订单不允许被“认领结算”
            .and(w -> w.notIn(ShopOrder::getOrderStatus, 2, 4, 5, 6, 7).or().isNull(ShopOrder::getOrderStatus));

        if (waterFormIds != null && !waterFormIds.isEmpty()) {
            uw.and(w -> w.eq(ShopOrder::getDeliveryStatus, 20).or().in(ShopOrder::getFormId, waterFormIds));
        } else {
            uw.eq(ShopOrder::getDeliveryStatus, 20);
        }

        uw.set(ShopOrder::getIsSettled, 1);
        return shopOrderService.update(uw);
    }

    private boolean claimOrderToSettleV2(Integer orderId) {
        LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>()
                .eq(ShopOrder::getOrderId, orderId)
                .eq(ShopOrder::getTenantId, TENANT_ID)
                .eq(ShopOrder::getIsSettled, 0)
                // 二次防御：退款/取消订单不允许被“认领结算”
                .and(w -> w.notIn(ShopOrder::getOrderStatus, 2, 3, 4, 5, 6, 7).or().isNull(ShopOrder::getOrderStatus));
        uw.set(ShopOrder::getIsSettled, 1);
        return shopOrderService.update(uw);
    }

    private Set<Integer> loadWaterFormIds() {
        try {
            return gltTicketTemplateService.list(
                new LambdaQueryWrapper<GltTicketTemplate>()
                    .eq(GltTicketTemplate::getTenantId, TENANT_ID)
                    .eq(GltTicketTemplate::getDeleted, 0)
                    .isNotNull(GltTicketTemplate::getGoodsId)
            ).stream()
                .map(GltTicketTemplate::getGoodsId)
                .filter(Objects::nonNull)
                .collect(java.util.stream.Collectors.toSet());
        } catch (Exception e) {
            log.warn("读取水票模板goodsId失败，将按普通订单规则结算 - tenantId={}", TENANT_ID, e);
            return Collections.emptySet();
        }
    }

    private void settleOneOrder(
        ShopOrder order,
        Map<Integer, Integer> level1ParentCache,
        Map<Integer, Boolean> shopRoleCache,
        ShopDealerUser totalDealerUser,
        int dealerLevel
    ) {
        if (order.getUserId() == null || order.getOrderNo() == null) {
            throw new IllegalStateException("订单关键信息缺失，无法结算 - orderId=" + order.getOrderId());
        }

        BigDecimal baseAmount = getOrderBaseAmount(order);
        if (baseAmount == null || baseAmount.signum() <= 0) {
            throw new IllegalStateException("订单金额为空或<=0，无法结算 - orderId=" + order.getOrderId() + ", orderNo=" + order.getOrderNo());
        }

        OrderGoodsInfo goodsInfo = findOrderSingleGoodsInfo(order);
        ShopGoods goods = goodsInfo.goods;
        int goodsQty = goodsInfo.quantity;

        if (goods != null && goods.getIsOpenCommission() != null && goods.getIsOpenCommission() != 1) {
            log.info("商品未开启分销，跳过订单结算 - orderId={}, orderNo={}, buyerUserId={}, goodsId={}, isOpenCommission={}",
                order.getOrderId(), order.getOrderNo(), order.getUserId(), goods.getGoodsId(), goods.getIsOpenCommission());
            return;
        }

        CommissionConfig commissionConfig = resolveCommissionConfig(goods);

        log.info("开始结算订单 - orderId={}, orderNo={}, buyerUserId={}, payPrice={}, goodsId={}, goodsQty={}, commissionType={}, cfg[dealer1={}, dealer2={}, dealer3={}, div1={}, div2={}]",
            order.getOrderId(),
            order.getOrderNo(),
            order.getUserId(),
            baseAmount,
            goods != null ? goods.getGoodsId() : null,
            goodsQty,
            commissionConfig.commissionType,
            commissionConfig.dealerDirectValue,
            commissionConfig.dealerSimpleValue,
            commissionConfig.dealerThirdValue,
            commissionConfig.storeDirectValue,
            commissionConfig.storeSimpleValue);

        // 1) 直推/间推（shop_dealer_referee）
        DealerRefereeCommission dealerRefereeCommission = settleDealerRefereeCommission(order, baseAmount, goodsQty, commissionConfig, dealerLevel);

        // 2) 门店分润上级：从下单用户开始逐级向上找，命中 ShopDealerUser.type=1 的最近两级（直推门店/间推门店）。
        ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommission(order, baseAmount, goodsQty, commissionConfig, level1ParentCache, shopRoleCache);

        // 3) 分红：固定比率，每个订单都分。
        TotalDealerCommission totalDealerCommission = settleTotalDealerCommission(order, baseAmount, goodsQty, totalDealerUser);

        // 4) 写入分销订单记录（用于排查/统计；详细分佣以 ShopDealerCapital 为准）
        createDealerOrderRecord(order, baseAmount, dealerRefereeCommission, shopRoleCommission, totalDealerCommission);

        log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), baseAmount);
    }

    private void settleOneOrderV2(ShopOrder order, Map<Integer, Integer> level1ParentCache, Map<Integer, Boolean> shopRoleCache,
                                  ShopDealerUser totalDealerUser, int dealerLevel) {
        if (order.getUserId() == null || order.getOrderNo() == null) {
            throw new IllegalStateException("订单关键信息缺失，无法结算 - orderId=" + order.getOrderId());
        }

        BigDecimal totalPrice = order.getTotalPrice();
        BigDecimal payPrice = order.getPayPrice();
        BigDecimal rate = payPrice.divide(totalPrice, 2, RoundingMode.HALF_UP);

        if(payPrice.compareTo(BigDecimal.ZERO) <= 0){
            log.info("订单号：{}，实付金额为0，无需执行分销逻辑" + order.getOrderNo());
            return;
        }

        //查询订单号订单所有已开启分销的商品分润信息
        List<ShopOrderGoodsVO> orderGoodsVOList = shopOrderMapper.getOrderGoodsInfo(order.getOrderNo());
        if(CollectionUtils.isNotEmpty(orderGoodsVOList)){
            // 1) 直推/间推（直接增加冻结账户余额）
            DealerRefereeCommissionV2 dealerRefereeCommission = settleDealerRefereeCommissionV2(order, rate, orderGoodsVOList, dealerLevel);

            // 2) 门店分润上级：从下单用户开始逐级向上找，命中 ShopDealerUser.type=1 的最近两级（直推门店/间推门店）【只统计数据，不对分销账户进行处理，
            // 已日结形式，统计分销记录表：shop_dealer_order 做对应一级二级管理津贴结算】
            ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommissionV2(order, rate, orderGoodsVOList, level1ParentCache, shopRoleCache);

            // 3) 分红：固定比率，每个订单都分 TODO 总分红未开发，还按原逻辑走
            int goodsQty = orderGoodsVOList.stream().mapToInt(ShopOrderGoodsVO::getTotalNum).sum();
            TotalDealerCommission totalDealerCommission = settleTotalDealerCommissionV2(order, goodsQty, totalDealerUser);

            // 4) 写入分销订单记录（用于排查/统计；详细分佣以 ShopDealerCapital 为准）
            createDealerOrderRecordV2(order, dealerRefereeCommission, shopRoleCommission, totalDealerCommission);

            log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), payPrice);
        }else {
           log.error("订单号：{}，未找到下单分销商品数据！", order.getOrderNo());
           return;
        }
    }

    private DealerRefereeCommission settleDealerRefereeCommission(
        ShopOrder order,
        BigDecimal baseAmount,
        int goodsQty,
        CommissionConfig commissionConfig,
        int dealerLevel
    ) {
        // 兼容两种数据形态：
        // 1) 同一 userId 下有 level=1/2/3 的多级关系（直接按 level 取）；
        // 2) 仅维护 level=1（用“查两次”回退获取上级）。
        //
        // 严格按“分销设置 level”决定发放到第几级，避免 level=2 时仍触发第3级发放逻辑。
        int normalizedLevel = normalizeDealerLevel(dealerLevel);

        Integer directDealerId = null;
        Integer simpleDealerId = null;
        Integer thirdDealerId = null;

        if (normalizedLevel >= 1) {
            directDealerId = getDealerRefereeId(order.getUserId(), 1);
        }
        if (normalizedLevel >= 2) {
            simpleDealerId = getDealerRefereeId(order.getUserId(), 2);
            if (simpleDealerId == null && directDealerId != null) {
                simpleDealerId = getDealerRefereeId(directDealerId, 1);
            }
        }
        if (normalizedLevel >= 3) {
            thirdDealerId = getDealerRefereeId(order.getUserId(), 3);
            if (thirdDealerId == null && simpleDealerId != null) {
                thirdDealerId = getDealerRefereeId(simpleDealerId, 1);
            }
        }

        BigDecimal directMoney =
            directDealerId != null ? calcMoneyByCommissionType(baseAmount, commissionConfig.dealerDirectValue, goodsQty, 2, commissionConfig.commissionType) : BigDecimal.ZERO;
        // 允许同一条线内同一个人同时拿到“直推 + 间推”（即使 directDealerId == simpleDealerId 也照常发放两笔）
        BigDecimal simpleMoney =
            simpleDealerId != null ? calcMoneyByCommissionType(baseAmount, commissionConfig.dealerSimpleValue, goodsQty, 2, commissionConfig.commissionType) : BigDecimal.ZERO;
        BigDecimal thirdMoney =
            thirdDealerId != null ? calcMoneyByCommissionType(baseAmount, commissionConfig.dealerThirdValue, goodsQty, 2, commissionConfig.commissionType) : BigDecimal.ZERO;

        log.info("分销直推/间推/第3级查询结果 - orderNo={}, buyerUserId={}, directDealerId={}, directMoney={}, simpleDealerId={}, simpleMoney={}, thirdDealerId={}, thirdMoney={}",
            order.getOrderNo(), order.getUserId(), directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);

        // 直推：对方=买家；推荐奖(5%)：对方=直推分销商（便于在资金明细中看出“来自哪个下级分销商/团队订单”）
        if (normalizedLevel >= 1) {
            creditDealerCommission(
                directDealerId,
                directMoney,
                order,
                order.getUserId(),
                buildCommissionComment("分佣", commissionConfig.commissionType, commissionConfig.dealerDirectValue, goodsQty)
            );
        }
        if (normalizedLevel >= 2) {
            creditDealerCommission(
                simpleDealerId,
                simpleMoney,
                order,
                directDealerId,
                buildCommissionComment("推荐奖", commissionConfig.commissionType, commissionConfig.dealerSimpleValue, goodsQty)
            );
        }
        if (normalizedLevel >= 3) {
            creditDealerCommission(
                thirdDealerId,
                thirdMoney,
                order,
                simpleDealerId,
                buildCommissionComment("分润收入", commissionConfig.commissionType, commissionConfig.dealerThirdValue, goodsQty)
            );
        }

        return new DealerRefereeCommission(directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);
    }

    /**
     * 获取分销员分销霍金数据
     * @param order
     * @param orderGoodsVOList
     * @param dealerLevel
     * @return
     */
    private DealerRefereeCommissionV2 settleDealerRefereeCommissionV2(ShopOrder order, BigDecimal rate, List<ShopOrderGoodsVO> orderGoodsVOList, int dealerLevel) {
        Integer directDealerId = null;
        Integer simpleDealerId = null;
        AtomicReference<BigDecimal> directMoney = new AtomicReference<>(BigDecimal.ZERO);
        AtomicReference<BigDecimal> simpleMoney = new AtomicReference<>(BigDecimal.ZERO);


        ShopDealerRefereeVO dealerRefereeVO = shopDealerRefereeMapper.getDealerIdByUserId(order.getUserId());
        if (dealerLevel == 1) {
            Integer directUserId = dealerRefereeVO.getDirectUserId();
            Integer directUserType = dealerRefereeVO.getDirectUserType();
            if(directUserId != null && directUserType != null && directUserType == 0){
                directDealerId = dealerRefereeVO.getDirectUserId();
            }
        }else {
            Integer directUserId = dealerRefereeVO.getDirectUserId();
            Integer directUserType = dealerRefereeVO.getDirectUserType();
            Integer simpleUserId = dealerRefereeVO.getSimpleUserId();
            Integer simpleUserType = dealerRefereeVO.getSimpleUserType();
            if(directUserId != null && directUserType != null && directUserType == 0){
                directDealerId = directUserId;
            }
            if(simpleUserId != null && simpleUserType != null && simpleUserType == 0){
                simpleDealerId = simpleUserId;
            }
        }

        if(directDealerId != null || simpleDealerId != null){
            Integer finalDirectDealerId = directDealerId;
            Integer finalSimpleDealerId = simpleDealerId;
            orderGoodsVOList.forEach(orderGoodsVO -> {
                //获取商品分润比例/金额
                BigDecimal firstMoney = orderGoodsVO.getFirstMoney();
                BigDecimal secondMoney = orderGoodsVO.getSecondMoney();

                //按实付比例计算单项应参与分润金额
                BigDecimal itemRatePrice = orderGoodsVO.getPrice().multiply(BigDecimal.valueOf(orderGoodsVO.getTotalNum())).multiply(rate);

                //一级分销员存在(type = 0)且单项实付金额大于0及商品设置了一级分销比例/金额
                if(finalDirectDealerId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0 && firstMoney.compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
                    directMoney.accumulateAndGet(one, BigDecimal::add);
                }

                //一级分销员存在(type = 0)且单项实付金额大于0及商品设置了一级分销比例/金额
                if(finalSimpleDealerId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0 && secondMoney.compareTo(BigDecimal.ZERO) > 0 ){
                    BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
                    simpleMoney.accumulateAndGet(two, BigDecimal::add);
                }
            });

            //一级分销员账户增加冻结金额
            if (directDealerId != null && directMoney.get().compareTo(BigDecimal.ZERO) > 0) {
                ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
                reduceDto.setTypeEnum(ShopDealerTypeEnum.FREEZE_ACCOUNT);
                reduceDto.setUserId(directDealerId);
                reduceDto.setOrderUserId(order.getUserId());
                reduceDto.setOrderNo(order.getOrderNo());
                reduceDto.setPrice(directMoney.get());
                reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DISTRIBUTION_INCOME);
                shopDealerUserService.reduceBalance(reduceDto);
            }

            //二级分销员账户增加冻结金额
            if (simpleDealerId != null && simpleMoney.get().compareTo(BigDecimal.ZERO) > 0) {
                ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
                reduceDto.setTypeEnum(ShopDealerTypeEnum.FREEZE_ACCOUNT);
                reduceDto.setUserId(simpleDealerId);
                reduceDto.setOrderUserId(order.getUserId());
                reduceDto.setOrderNo(order.getOrderNo());
                reduceDto.setPrice(simpleMoney.get());
                reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DISTRIBUTION_INCOME);
                shopDealerUserService.reduceBalance(reduceDto);
            }
            return new DealerRefereeCommissionV2(directDealerId, directMoney.get(), simpleDealerId, simpleMoney.get());
        }
        return null;
    }

    private Integer getDealerRefereeId(Integer userId) {
        return getDealerRefereeId(userId, 1);
    }

    private Integer getDealerRefereeId(Integer userId, int level) {
        if (userId == null) {
            return null;
        }
        ShopDealerReferee rel = shopDealerRefereeService.getOne(
            new LambdaQueryWrapper<ShopDealerReferee>()
                .eq(ShopDealerReferee::getTenantId, TENANT_ID)
                .eq(ShopDealerReferee::getUserId, userId)
                .eq(ShopDealerReferee::getLevel, level)
                .orderByDesc(ShopDealerReferee::getId)
                .last("limit 1")
        );
        log.debug("shop_dealer_referee(level={}) 查询 - tenantId={}, userId={}, dealerId={}",
            level, TENANT_ID, userId, rel != null ? rel.getDealerId() : null);
        return rel != null ? rel.getDealerId() : null;
    }

    private ShopRoleCommission settleShopRoleRefereeCommission(
        ShopOrder order,
        BigDecimal baseAmount,
        int goodsQty,
        CommissionConfig commissionConfig,
        Map<Integer, Integer> level1ParentCache,
        Map<Integer, Boolean> shopRoleCache
    ) {
        List<Integer> shopRoleReferees = findFirstTwoShopRoleReferees(order.getUserId(), level1ParentCache, shopRoleCache);
        log.info("门店分润命中结果(type=1门店角色取前两级) - orderNo={}, buyerUserId={}, shopRoleReferees={}",
            order.getOrderNo(), order.getUserId(), shopRoleReferees);
        if (shopRoleReferees.isEmpty()) {
            return ShopRoleCommission.empty();
        }

        if (shopRoleReferees.size() == 1) {
            // 仅找到一个门店：按(直推+间推)汇总发放
            BigDecimal singleStoreValue = safeValue(commissionConfig.storeDirectValue).add(safeValue(commissionConfig.storeSimpleValue));
            BigDecimal money = calcMoneyByCommissionType(baseAmount, singleStoreValue, goodsQty, DIVIDEND_SCALE, commissionConfig.commissionType);
            log.info("分润发放(仅1门店) - orderNo={}, firstDividendUserId={}, commissionType={}, value={}, money={}",
                order.getOrderNo(), shopRoleReferees.get(0), commissionConfig.commissionType, singleStoreValue, money);
            creditDealerCommission(
                shopRoleReferees.get(0),
                money,
                order,
                order.getUserId(),
                buildCommissionComment("门店直推分润(仅1门店)", commissionConfig.commissionType, singleStoreValue, goodsQty)
            );
            return new ShopRoleCommission(shopRoleReferees.get(0), money, null, BigDecimal.ZERO);
        }

        // 两个或以上：按配置分别发放
        BigDecimal storeDirectMoney =
            calcMoneyByCommissionType(baseAmount, commissionConfig.storeDirectValue, goodsQty, DIVIDEND_SCALE, commissionConfig.commissionType);
        BigDecimal storeSimpleMoney =
            calcMoneyByCommissionType(baseAmount, commissionConfig.storeSimpleValue, goodsQty, DIVIDEND_SCALE, commissionConfig.commissionType);
        log.info("分润发放(2人) - orderNo={}, firstDividendUserId={}, commissionType={}, firstValue={}, firstMoney={}, secondDividendUserId={}, secondValue={}, secondMoney={}",
            order.getOrderNo(),
            shopRoleReferees.get(0),
            commissionConfig.commissionType,
            commissionConfig.storeDirectValue,
            storeDirectMoney,
            shopRoleReferees.get(1),
            commissionConfig.storeSimpleValue,
            storeSimpleMoney);
        creditDealerCommission(
            shopRoleReferees.get(0),
            storeDirectMoney,
            order,
            order.getUserId(),
            buildCommissionComment("门店直推分润", commissionConfig.commissionType, commissionConfig.storeDirectValue, goodsQty)
        );
        creditDealerCommission(
            shopRoleReferees.get(1),
            storeSimpleMoney,
            order,
            order.getUserId(),
            buildCommissionComment("门店间推分润", commissionConfig.commissionType, commissionConfig.storeSimpleValue, goodsQty)
        );
        return new ShopRoleCommission(shopRoleReferees.get(0), storeDirectMoney, shopRoleReferees.get(1), storeSimpleMoney);
    }

    private ShopRoleCommission settleShopRoleRefereeCommissionV2(ShopOrder order, BigDecimal rate, List<ShopOrderGoodsVO> orderGoodsVOList, Map<Integer, Integer> level1ParentCache, Map<Integer, Boolean> shopRoleCache) {
        List<Integer> shopRoleReferees = findFirstTwoShopRoleReferees(order.getUserId(), level1ParentCache, shopRoleCache);
        log.info("门店分润命中结果(type=1门店角色取前两级) - orderNo={}, buyerUserId={}, shopRoleReferees={}",
                order.getOrderNo(), order.getUserId(), shopRoleReferees);
        if (shopRoleReferees.isEmpty()) {
            return ShopRoleCommission.empty();
        }

        if(CollectionUtils.isNotEmpty(shopRoleReferees)){
            Integer storeDirectUserId;
            Integer storeSimpleUserId = null;
            AtomicReference<BigDecimal> storeDirectMoney = new AtomicReference<>(BigDecimal.ZERO);
            AtomicReference<BigDecimal> storeSimpleMoney = new AtomicReference<>(BigDecimal.ZERO);

            if(shopRoleReferees.size() == 1){
                storeDirectUserId = shopRoleReferees.get(0);
            }else {
                storeDirectUserId = shopRoleReferees.get(0);
                storeSimpleUserId = shopRoleReferees.get(1);
            }


            Integer finalStoreDirectUserId = storeDirectUserId;
            Integer finalStoreSimpleUserId = storeSimpleUserId;
            orderGoodsVOList.forEach(orderGoodsVO ->{
                //获取商品对应服务商管理费分润比例/金额
                BigDecimal firstMoney = orderGoodsVO.getFirstDividend();
                BigDecimal secondMoney = orderGoodsVO.getSecondDividend();

                //按实付比例计算单项应参与分润金额
                BigDecimal itemRatePrice = orderGoodsVO.getPrice().multiply(BigDecimal.valueOf(orderGoodsVO.getTotalNum())).multiply(rate);

                if(finalStoreDirectUserId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
                    storeDirectMoney.accumulateAndGet(one, BigDecimal::add);
                }

                if(finalStoreSimpleUserId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
                    storeSimpleMoney.accumulateAndGet(two, BigDecimal::add);
                }
            });
            return new ShopRoleCommission(storeDirectUserId, storeDirectMoney.get(), storeSimpleUserId, storeSimpleMoney.get());
        }else {
            return null;
        }
    }

    private TotalDealerCommission settleTotalDealerCommission(
        ShopOrder order,
        BigDecimal baseAmount,
        int goodsQty,
        ShopDealerUser totalDealerUser
    ) {
        if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
            return TotalDealerCommission.empty();
        }
        BigDecimal rate = safePositive(totalDealerUser.getRate());
        if (rate.signum() <= 0) {
            rate = TOTAL_DEALER_DIVIDEND_RATE;
        }
        BigDecimal money = calcMoneyByCommissionType(baseAmount, rate, goodsQty, DIVIDEND_SCALE, 20);
        log.info("分红发放 - orderNo={}, totalDealerUserId={}, rate={}, money={}",
            order.getOrderNo(), totalDealerUser.getUserId(), rate, money);
        creditDealerCommission(
            totalDealerUser.getUserId(),
            money,
            order,
            order.getUserId(),
            buildCommissionComment("分红", 20, rate, goodsQty)
        );
        return new TotalDealerCommission(totalDealerUser.getUserId(), money);
    }

    private TotalDealerCommission settleTotalDealerCommissionV2(ShopOrder order, int goodsQty, ShopDealerUser totalDealerUser) {
        if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
            return TotalDealerCommission.empty();
        }
        BigDecimal rate = safePositive(totalDealerUser.getRate());
        if (rate.signum() <= 0) {
            rate = TOTAL_DEALER_DIVIDEND_RATE;
        }
        BigDecimal money = calcMoneyByCommissionType(order.getPayPrice(), rate, goodsQty, DIVIDEND_SCALE, 20);

        //一级分销员账户增加冻结金额
        if (money.compareTo(BigDecimal.ZERO) > 0) {
            ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
            reduceDto.setTypeEnum(ShopDealerTypeEnum.FREEZE_ACCOUNT);
            reduceDto.setUserId(totalDealerUser.getUserId());
            reduceDto.setOrderUserId(order.getUserId());
            reduceDto.setOrderNo(order.getOrderNo());
            reduceDto.setPrice(money);
            reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DIVIDEND_INCOME);
            shopDealerUserService.reduceBalance(reduceDto);

            return new TotalDealerCommission(totalDealerUser.getUserId(), money);
        }
        return TotalDealerCommission.empty();
    }

    private ShopDealerUser findTotalDealerUser() {
        return shopDealerUserService.getOne(
            new LambdaQueryWrapper<ShopDealerUser>()
                .eq(ShopDealerUser::getTenantId, TENANT_ID)
                .eq(ShopDealerUser::getType, 2)
                .and(w -> w.eq(ShopDealerUser::getIsDelete, 0).or().isNull(ShopDealerUser::getIsDelete))
                .orderByAsc(ShopDealerUser::getId)
                .last("limit 1")
        );
    }

    private DealerBasicSetting findDealerBasicSetting() {
        int level = 2;
        ShopDealerSetting setting = shopDealerSettingService.getOne(
            new LambdaQueryWrapper<ShopDealerSetting>()
                .eq(ShopDealerSetting::getTenantId, TENANT_ID)
                .eq(ShopDealerSetting::getKey, "basic")
                .last("limit 1")
        );
        if (setting != null && setting.getValues() != null && !setting.getValues().isBlank()) {
            try {
                JSONObject json = JSONObject.parseObject(setting.getValues());
                Integer levelVal = json.getInteger("level");
                if (levelVal != null && levelVal > 0) {
                    level = Math.min(levelVal, 3);
                }
            } catch (Exception e) {
                log.warn("解析分销设置失败，将使用默认等级 - tenantId={}, values={}", TENANT_ID, setting.getValues(), e);
            }
        }
        return new DealerBasicSetting(level);
    }

    private int normalizeDealerLevel(int dealerLevel) {
        if (dealerLevel <= 0) {
            return 2;
        }
        return Math.min(dealerLevel, 3);
    }

    /**
     * shop_dealer_setting(key=basic) 的关键配置（仅取结算任务需要的字段）。
     */
    private static class DealerBasicSetting {
        private final int level;

        private DealerBasicSetting(int level) {
            this.level = level;
        }
    }

    /**
     * 门店分润规则：
     * - 门店角色为 ShopDealerUser.type=1；
     * - 从下单用户开始，沿 shop_dealer_referee(level=1) 链路逐级向上找；
     * - 遇到第一个 type=1 用户命中为“直推门店用户”，继续向上找到第二个 type=1 用户命中为“间推门店用户”。
     */
    private List<Integer> findFirstTwoShopRoleReferees(
        Integer buyerUserId,
        Map<Integer, Integer> level1ParentCache,
        Map<Integer, Boolean> shopRoleCache
    ) {
        if (buyerUserId == null) {
            return Collections.emptyList();
        }

        return UpstreamUserFinder.findFirstNMatchingUpstreamUsers(
            buyerUserId,
            2,
            MAX_REFEREE_CHAIN_DEPTH,
            childId -> getLevel1ParentCached(childId, level1ParentCache),
            userId -> isShopRoleUserCached(userId, shopRoleCache)
        );
    }

    private Integer getLevel1ParentCached(Integer userId, Map<Integer, Integer> cache) {
        if (userId == null) {
            return null;
        }
        if (cache != null) {
            if (cache.containsKey(userId)) {
                return cache.get(userId);
            }
            Integer parent = getDealerRefereeId(userId, 1);
            cache.put(userId, parent);
            return parent;
        }
        return getDealerRefereeId(userId, 1);
    }

    private boolean isShopRoleUserCached(Integer userId, Map<Integer, Boolean> cache) {
        if (userId == null) {
            return false;
        }
        if (cache != null) {
            Boolean cached = cache.get(userId);
            if (cached != null) {
                return cached;
            }
            if (cache.containsKey(userId)) {
                return false;
            }
            boolean val = isShopRoleUser(userId);
            cache.put(userId, val);
            return val;
        }
        return isShopRoleUser(userId);
    }

    private boolean isShopRoleUser(Integer userId) {
        return shopDealerUserService.count(
            new LambdaQueryWrapper<ShopDealerUser>()
                .eq(ShopDealerUser::getTenantId, TENANT_ID)
                .eq(ShopDealerUser::getUserId, userId)
                .eq(ShopDealerUser::getType, 1)
                .and(w -> w.eq(ShopDealerUser::getIsDelete, 0).or().isNull(ShopDealerUser::getIsDelete))
        ) > 0;
    }

    private void creditDealerCommission(Integer dealerUserId, BigDecimal money, ShopOrder order, Integer toUserId, String comments) {
        if (dealerUserId == null || money == null || money.signum() <= 0) {
            return;
        }

        // 幂等：同一订单同一类型佣金，避免重复发放（用于任务重跑/补发场景）
        LambdaQueryWrapper<ShopDealerCapital> idempotentQw = new LambdaQueryWrapper<ShopDealerCapital>()
            .eq(ShopDealerCapital::getTenantId, TENANT_ID)
            .eq(ShopDealerCapital::getOrderNo, order.getOrderNo())
            .eq(ShopDealerCapital::getUserId, dealerUserId);
        if (comments != null) {
            // 以“佣金类型前缀”做幂等键，避免 comments 细节文案调整导致重复发放。
            String commentPrefix = comments;
            int idx = comments.indexOf('(');
            if (idx > 0) {
                commentPrefix = comments.substring(0, idx) + "(";
            }
            idempotentQw.likeRight(ShopDealerCapital::getComments, commentPrefix);
        } else {
            idempotentQw.isNull(ShopDealerCapital::getComments);
        }
        boolean alreadyCredited = shopDealerCapitalService.count(idempotentQw) > 0;
        if (alreadyCredited) {
            log.info("佣金已处理(已入冻结/已落明细)，跳过 - orderNo={}, toDealerUserId={}, money={}, comments={}", order.getOrderNo(), dealerUserId, money, comments);
            return;
        }

        log.info("佣金入冻结 - orderNo={}, toDealerUserId={}, money={}, comments={}", order.getOrderNo(), dealerUserId, money, comments);

        // 订单付款成功：佣金先进入冻结金额（freeze_money），避免后续退款/撤销时已可提现导致对账困难。
        // 并发下避免丢失更新，用SQL自增。
        boolean updated = shopDealerUserService.update(
            new LambdaUpdateWrapper<ShopDealerUser>()
                .eq(ShopDealerUser::getTenantId, TENANT_ID)
                .eq(ShopDealerUser::getUserId, dealerUserId)
                .setSql("freeze_money = IFNULL(freeze_money,0) + " + money.toPlainString())
                .setSql("total_money = IFNULL(total_money,0) + " + money.toPlainString())
        );

        if (!updated) {
            // 门店角色用户可能未开通分销账户：此时门店直推/间推会“找到了人但入不了账”，收益与明细都不会写入。
            // 这里补偿创建账户后再尝试入账一次。
            ShopDealerUser existed = shopDealerUserService.getOne(
                new LambdaQueryWrapper<ShopDealerUser>()
                    .eq(ShopDealerUser::getTenantId, TENANT_ID)
                    .eq(ShopDealerUser::getUserId, dealerUserId)
                    .last("limit 1")
            );
            if (existed == null) {
                ShopDealerUser newDealerUser = new ShopDealerUser();
                newDealerUser.setTenantId(TENANT_ID);
                newDealerUser.setUserId(dealerUserId);
                newDealerUser.setType(0);
                newDealerUser.setIsDelete(0);
                newDealerUser.setSortNumber(0);
                newDealerUser.setFirstNum(0);
                newDealerUser.setSecondNum(0);
                newDealerUser.setThirdNum(0);
                newDealerUser.setMoney(BigDecimal.ZERO);
                newDealerUser.setFreezeMoney(BigDecimal.ZERO);
                newDealerUser.setTotalMoney(BigDecimal.ZERO);
                // 尽量补齐基础信息，避免表字段 NOT NULL 导致插入失败（插入失败会让门店分佣“找到了人但入不了账”）。
                try {
                    List<User> sysUsers = userMapper.selectByIdIgnoreTenant(dealerUserId);
                    User sysUser = (sysUsers != null && !sysUsers.isEmpty()) ? sysUsers.get(0) : null;
                    if (sysUser != null) {
                        newDealerUser.setRealName(sysUser.getRealName() != null ? sysUser.getRealName() : sysUser.getNickname());
                        newDealerUser.setMobile(sysUser.getPhone());
                    }
                } catch (Exception e) {
                    // 拉取基础信息失败不应阻断结算；后续 update 若失败会有 warn 日志。
                    log.warn("创建分销商账户时读取sys_user失败 - tenantId={}, dealerUserId={}", TENANT_ID, dealerUserId, e);
                }
                newDealerUser.setCreateTime(java.time.LocalDateTime.now());
                newDealerUser.setUpdateTime(java.time.LocalDateTime.now());
                try {
                    shopDealerUserService.save(newDealerUser);
                } catch (Exception e) {
                    // 并发下可能已被其他线程/实例创建；也可能是字段约束导致插入失败。
                    // 继续重试 update，若仍失败会输出 warn，便于定位原因。
                    log.warn("创建分销商账户失败 - tenantId={}, dealerUserId={}, orderNo={}", TENANT_ID, dealerUserId, order.getOrderNo(), e);
                }
            }

            updated = shopDealerUserService.update(
                new LambdaUpdateWrapper<ShopDealerUser>()
                    .eq(ShopDealerUser::getTenantId, TENANT_ID)
                    .eq(ShopDealerUser::getUserId, dealerUserId)
                    .setSql("freeze_money = IFNULL(freeze_money,0) + " + money.toPlainString())
                    .setSql("total_money = IFNULL(total_money,0) + " + money.toPlainString())
            );
            if (!updated) {
                log.warn("发放佣金失败：未找到/创建分销商账户 - tenantId={}, dealerUserId={}, orderNo={}", TENANT_ID, dealerUserId, order.getOrderNo());
                return;
            }
        }

        ShopDealerCapital cap = new ShopDealerCapital();
        cap.setUserId(dealerUserId);
        cap.setOrderNo(order.getOrderNo());
        cap.setFlowType(10);
        cap.setMoney(money);
        cap.setComments(comments);
        cap.setToUserId(toUserId);
        cap.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
        cap.setTenantId(TENANT_ID);
        shopDealerCapitalService.save(cap);
    }

    private void createDealerOrderRecord(
        ShopOrder order,
        BigDecimal baseAmount,
        DealerRefereeCommission dealerRefereeCommission,
        ShopRoleCommission shopRoleCommission,
        TotalDealerCommission totalDealerCommission
    ) {
        // 幂等：同一订单只写一条（依赖 order_no + tenant_id 作为业务唯一）
        ShopDealerOrder existed = shopDealerOrderService.getOne(
            new LambdaQueryWrapper<ShopDealerOrder>()
                .eq(ShopDealerOrder::getTenantId, TENANT_ID)
                .eq(ShopDealerOrder::getOrderNo, order.getOrderNo())
                .last("limit 1")
        );
        if (existed != null) {
            // 允许“补发”门店分润时回填分润字段，避免订单已结算但分润字段一直为空，影响排查/对账。
            LambdaUpdateWrapper<ShopDealerOrder> uw = new LambdaUpdateWrapper<ShopDealerOrder>()
                .eq(ShopDealerOrder::getTenantId, TENANT_ID)
                .eq(ShopDealerOrder::getOrderNo, order.getOrderNo());
            boolean needUpdate = false;
            if (shopRoleCommission.storeDirectUserId != null) {
                Integer existedUser = existed.getFirstDividendUser();
                boolean needSetUser = existedUser == null;
                boolean needSetMoney = existed.getFirstDividend() == null || existed.getFirstDividend().signum() == 0;
                if (needSetUser) {
                    uw.set(ShopDealerOrder::getFirstDividendUser, shopRoleCommission.storeDirectUserId);
                    needUpdate = true;
                }
                boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeDirectUserId);
                if (sameUser && needSetMoney && shopRoleCommission.storeDirectMoney != null && shopRoleCommission.storeDirectMoney.signum() > 0) {
                    uw.set(ShopDealerOrder::getFirstDividend, shopRoleCommission.storeDirectMoney);
                    needUpdate = true;
                }
            }
            if (shopRoleCommission.storeSimpleUserId != null) {
                Integer existedUser = existed.getSecondDividendUser();
                boolean needSetUser = existedUser == null;
                boolean needSetMoney = existed.getSecondDividend() == null || existed.getSecondDividend().signum() == 0;
                if (needSetUser) {
                    uw.set(ShopDealerOrder::getSecondDividendUser, shopRoleCommission.storeSimpleUserId);
                    needUpdate = true;
                }
                boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeSimpleUserId);
                if (sameUser && needSetMoney && shopRoleCommission.storeSimpleMoney != null && shopRoleCommission.storeSimpleMoney.signum() > 0) {
                    uw.set(ShopDealerOrder::getSecondDividend, shopRoleCommission.storeSimpleMoney);
                    needUpdate = true;
                }
            }
            if (needUpdate) {
                shopDealerOrderService.update(uw);
                log.info("ShopDealerOrder已存在，回填门店分润字段 - orderNo={}, firstDividendUser={}, secondDividendUser={}",
                    order.getOrderNo(), shopRoleCommission.storeDirectUserId, shopRoleCommission.storeSimpleUserId);
            } else {
                log.info("ShopDealerOrder已存在，跳过写入 - orderNo={}", order.getOrderNo());
            }
            return;
        }

        ShopDealerOrder dealerOrder = new ShopDealerOrder();
        dealerOrder.setUserId(order.getUserId()); // 买家用户ID
        dealerOrder.setOrderNo(order.getOrderNo());
        dealerOrder.setOrderPrice(baseAmount);
        dealerOrder.setPayPrice(baseAmount);

        dealerOrder.setFirstUserId(dealerRefereeCommission.directDealerId);
        dealerOrder.setFirstMoney(dealerRefereeCommission.directMoney);
        dealerOrder.setSecondUserId(dealerRefereeCommission.simpleDealerId);
        dealerOrder.setSecondMoney(dealerRefereeCommission.simpleMoney);
        dealerOrder.setThirdUserId(dealerRefereeCommission.thirdDealerId);
        dealerOrder.setThirdMoney(dealerRefereeCommission.thirdMoney);

        // 门店(角色shop)两级分润单独落字段（详细以 ShopDealerCapital 为准）
        dealerOrder.setFirstDividendUser(shopRoleCommission.storeDirectUserId);
        dealerOrder.setFirstDividend(shopRoleCommission.storeDirectMoney);
        dealerOrder.setSecondDividendUser(shopRoleCommission.storeSimpleUserId);
        dealerOrder.setSecondDividend(shopRoleCommission.storeSimpleMoney);

        dealerOrder.setIsSettled(1);
        dealerOrder.setSettleTime(java.time.LocalDateTime.now());
        // ShopDealerCapital 关联查询会拿 shop_dealer_order.month（覆盖 a.month），这里需要同步填充。
        dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
        dealerOrder.setTenantId(TENANT_ID);

        dealerOrder.setComments(buildCommissionTraceComment(dealerRefereeCommission, shopRoleCommission, totalDealerCommission));

        shopDealerOrderService.save(dealerOrder);
        log.info("写入ShopDealerOrder完成 - orderNo={}, firstUserId={}, secondUserId={}, firstDividendUser={}, secondDividendUser={}",
            order.getOrderNo(), dealerOrder.getFirstUserId(), dealerOrder.getSecondUserId(), dealerOrder.getFirstDividendUser(), dealerOrder.getSecondDividendUser());
    }

    /**
     * 记录订单分销业务
     * @param order 商品订单
     * @param dealerRefereeCommission   一级、二级分销员分销数据
     * @param shopRoleCommission        门店/服务商一级、二级管理津贴数据
     */
    private void createDealerOrderRecordV2(ShopOrder order, DealerRefereeCommissionV2 dealerRefereeCommission, ShopRoleCommission shopRoleCommission, TotalDealerCommission totalDealerCommission) {
        // 幂等：同一订单只写一条（依赖 order_no + tenant_id 作为业务唯一）
        ShopDealerOrder existed = shopDealerOrderService.getOne(
                new LambdaQueryWrapper<ShopDealerOrder>()
                        .eq(ShopDealerOrder::getTenantId, TENANT_ID)
                        .eq(ShopDealerOrder::getOrderNo, order.getOrderNo())
                        .last("limit 1")
        );
        if (existed != null) {
            // 允许“补发”门店分润时回填分润字段，避免订单已结算但分润字段一直为空，影响排查/对账。
            LambdaUpdateWrapper<ShopDealerOrder> uw = new LambdaUpdateWrapper<ShopDealerOrder>()
                    .eq(ShopDealerOrder::getTenantId, TENANT_ID)
                    .eq(ShopDealerOrder::getOrderNo, order.getOrderNo());
            boolean needUpdate = false;
            if (shopRoleCommission != null && shopRoleCommission.storeDirectUserId != null) {
                Integer existedUser = existed.getFirstDividendUser();
                boolean needSetUser = existedUser == null;
                boolean needSetMoney = existed.getFirstDividend() == null || existed.getFirstDividend().signum() == 0;
                if (needSetUser) {
                    uw.set(ShopDealerOrder::getFirstDividendUser, shopRoleCommission.storeDirectUserId);
                    needUpdate = true;
                }
                boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeDirectUserId);
                if (sameUser && needSetMoney && shopRoleCommission.storeDirectMoney != null && shopRoleCommission.storeDirectMoney.signum() > 0) {
                    uw.set(ShopDealerOrder::getFirstDividend, shopRoleCommission.storeDirectMoney);
                    needUpdate = true;
                }
            }
            if (shopRoleCommission != null && shopRoleCommission.storeSimpleUserId != null) {
                Integer existedUser = existed.getSecondDividendUser();
                boolean needSetUser = existedUser == null;
                boolean needSetMoney = existed.getSecondDividend() == null || existed.getSecondDividend().signum() == 0;
                if (needSetUser) {
                    uw.set(ShopDealerOrder::getSecondDividendUser, shopRoleCommission.storeSimpleUserId);
                    needUpdate = true;
                }
                boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeSimpleUserId);
                if (sameUser && needSetMoney && shopRoleCommission.storeSimpleMoney != null && shopRoleCommission.storeSimpleMoney.signum() > 0) {
                    uw.set(ShopDealerOrder::getSecondDividend, shopRoleCommission.storeSimpleMoney);
                    needUpdate = true;
                }
            }
            if (needUpdate) {
                shopDealerOrderService.update(uw);
                log.info("ShopDealerOrder已存在，回填门店分润字段 - orderNo={}, firstDividendUser={}, secondDividendUser={}",
                        order.getOrderNo(), shopRoleCommission.storeDirectUserId, shopRoleCommission.storeSimpleUserId);
            } else {
                log.info("ShopDealerOrder已存在，跳过写入 - orderNo={}", order.getOrderNo());
            }
            return;
        }else {

            ShopDealerOrder dealerOrder = new ShopDealerOrder();
            dealerOrder.setUserId(order.getUserId()); // 买家用户ID
            dealerOrder.setOrderNo(order.getOrderNo());
            dealerOrder.setOrderPrice(order.getTotalPrice());
            dealerOrder.setPayPrice(order.getPayPrice());

            //一级、二级分销员分销佣金统计
            dealerOrder.setFirstUserId(dealerRefereeCommission != null ? dealerRefereeCommission.directDealerId : null);
            dealerOrder.setFirstMoney(dealerRefereeCommission != null ? dealerRefereeCommission.directMoney : BigDecimal.ZERO);
            dealerOrder.setSecondUserId(dealerRefereeCommission != null ? dealerRefereeCommission.simpleDealerId : null);
            dealerOrder.setSecondMoney(dealerRefereeCommission != null ? dealerRefereeCommission.simpleMoney : BigDecimal.ZERO);

            //门店(角色shop)两级分润单独落字段（详细以 ShopDealerCapital 为准）
            dealerOrder.setFirstDividendUser(shopRoleCommission != null ? shopRoleCommission.storeDirectUserId : null);
            dealerOrder.setFirstDividend(shopRoleCommission != null ? shopRoleCommission.storeDirectMoney : BigDecimal.ZERO);
            dealerOrder.setSecondDividendUser(shopRoleCommission != null ? shopRoleCommission.storeSimpleUserId : null);
            dealerOrder.setSecondDividend(shopRoleCommission != null ? shopRoleCommission.storeSimpleMoney : BigDecimal.ZERO);

            dealerOrder.setIsSettled(1);
            dealerOrder.setSettleTime(LocalDateTime.now());
            dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
            dealerOrder.setTenantId(TENANT_ID);
            dealerOrder.setComments(buildCommissionTraceCommentV2(dealerRefereeCommission, shopRoleCommission, totalDealerCommission));

            shopDealerOrderService.save(dealerOrder);
        }
    }

    private String buildCommissionTraceComment(
        DealerRefereeCommission dealerRefereeCommission,
        ShopRoleCommission shopRoleCommission,
        TotalDealerCommission totalDealerCommission
    ) {
        // 轻量“过程”留痕，方便排查；详细分佣以 ShopDealerCapital 为准。
        return "direct=" + dealerRefereeCommission.directDealerId + ":" + dealerRefereeCommission.directMoney
            + ",simple=" + dealerRefereeCommission.simpleDealerId + ":" + dealerRefereeCommission.simpleMoney
            + ",third=" + dealerRefereeCommission.thirdDealerId + ":" + dealerRefereeCommission.thirdMoney
            + ",dividend1=" + shopRoleCommission.storeDirectUserId + ":" + shopRoleCommission.storeDirectMoney
            + ",dividend2=" + shopRoleCommission.storeSimpleUserId + ":" + shopRoleCommission.storeSimpleMoney
            + ",totalDealer=" + totalDealerCommission.userId + ":" + totalDealerCommission.money;
    }

    private String buildCommissionTraceCommentV2(
            DealerRefereeCommissionV2 dealerRefereeCommission,
            ShopRoleCommission shopRoleCommission,
            TotalDealerCommission totalDealerCommission
    ) {
        // 轻量“过程”留痕，方便排查；详细分佣以 ShopDealerCapital 为准。
        Integer direct = dealerRefereeCommission != null ? dealerRefereeCommission.directDealerId : null;
        BigDecimal directMoney = dealerRefereeCommission != null ? dealerRefereeCommission.directMoney : BigDecimal.ZERO;
        Integer simpleDealerId = dealerRefereeCommission != null ? dealerRefereeCommission.simpleDealerId : null;
        BigDecimal simpleMoney = dealerRefereeCommission != null ? dealerRefereeCommission.simpleMoney : BigDecimal.ZERO;
        Integer storeDirectUserId = shopRoleCommission != null ? shopRoleCommission.storeDirectUserId : null;
        BigDecimal storeDirectMoney = shopRoleCommission != null ? shopRoleCommission.storeDirectMoney : BigDecimal.ZERO;
        Integer storeSimpleUserId = shopRoleCommission != null ? shopRoleCommission.storeSimpleUserId : null;
        BigDecimal storeSimpleMoney = shopRoleCommission != null ? shopRoleCommission.storeSimpleMoney : BigDecimal.ZERO;
        Integer userId = totalDealerCommission != null ? totalDealerCommission.userId : null;
        BigDecimal money = totalDealerCommission != null ? totalDealerCommission.money : BigDecimal.ZERO;

        return "direct=" + direct + ":" + directMoney
                + ",simple=" + simpleDealerId + ":" + simpleMoney
                + ",dividend1=" + storeDirectUserId + ":" + storeDirectMoney
                + ",dividend2=" + storeSimpleUserId + ":" + storeSimpleMoney
                + ",totalDealer=" + userId + ":" + money;
    }

    private BigDecimal getOrderBaseAmount(ShopOrder order) {
        if (order == null) {
            return null;
        }
        return order.getPayPrice();
    }

    private BigDecimal calcMoneyByCommissionType(BigDecimal baseAmount, BigDecimal value, int goodsQty, int scale, Integer commissionType) {
        if (value == null || value.signum() <= 0) {
            return BigDecimal.ZERO;
        }
        int qty = Math.max(1, goodsQty);

        // 10: 固定金额(按件)；20: 百分比(按订单金额)
        if (commissionType != null && commissionType == 10) {
            return value.multiply(BigDecimal.valueOf(qty)).setScale(scale, RoundingMode.HALF_UP);
        }
        return baseAmount != null ? baseAmount.multiply(value).setScale(scale, RoundingMode.HALF_UP) : BigDecimal.ZERO;
    }

    private String buildCommissionComment(String label, Integer commissionType, BigDecimal value, int goodsQty) {
        if (commissionType != null && commissionType == 10) {
            return label + "(type=amount,amount=" + value + ",qty=" + Math.max(1, goodsQty) + ")";
        }
        return label + "(type=rate,rate=" + value + ")";
    }

    private OrderGoodsInfo findOrderSingleGoodsInfo(ShopOrder order) {
        if (order == null) {
            return new OrderGoodsInfo(null, 1);
        }

        Integer goodsId = order.getFormId();
        Integer totalNum = order.getTotalNum();

        if (goodsId == null) {
            ShopOrderGoods orderGoods = shopOrderGoodsService.getOne(
                new LambdaQueryWrapper<ShopOrderGoods>()
                    .eq(ShopOrderGoods::getTenantId, TENANT_ID)
                    .eq(ShopOrderGoods::getOrderId, order.getOrderId())
                    .orderByDesc(ShopOrderGoods::getId)
                    .last("limit 1")
            );
            goodsId = orderGoods != null ? orderGoods.getGoodsId() : null;
            if (totalNum == null && orderGoods != null) {
                totalNum = orderGoods.getTotalNum();
            }
        }

        int qty = totalNum != null && totalNum > 0 ? totalNum : 1;
        if (goodsId == null) {
            return new OrderGoodsInfo(null, qty);
        }

        ShopGoods goods = shopGoodsService.getOne(
            new LambdaQueryWrapper<ShopGoods>()
                .eq(ShopGoods::getTenantId, TENANT_ID)
                .eq(ShopGoods::getGoodsId, goodsId)
                .last("limit 1")
        );
        return new OrderGoodsInfo(goods, qty);
    }

    private CommissionConfig resolveCommissionConfig(ShopGoods goods) {
        // commissionType：10固定金额；20百分比（默认/兼容历史）
        Integer commissionType = goods != null && goods.getCommissionType() != null ? goods.getCommissionType() : 20;
        if (commissionType != 10 && commissionType != 20) {
            commissionType = 20;
        }

        if (goods == null) {
            // 无商品信息：回退旧逻辑（按比率）
            return CommissionConfig.defaultRate();
        }

        if (commissionType == 10) {
            // 固定金额模式：字段值>0按金额结算(按件)，未配置则视为0。
            return new CommissionConfig(
                commissionType,
                safePositive(goods.getFirstMoney()),
                safePositive(goods.getSecondMoney()),
                safePositive(goods.getThirdMoney()),
                safePositive(goods.getFirstDividend()),
                safePositive(goods.getSecondDividend())
            );
        }

        // 比率模式：默认用旧规则；商品字段值>0则覆盖默认比率。
        BigDecimal dealerDirectValue = RATE_0_10;
        BigDecimal dealerSimpleValue = RATE_0_05;
        BigDecimal dealerThirdValue = BigDecimal.ZERO;
        BigDecimal storeDirectValue = RATE_0_02;
        BigDecimal storeSimpleValue = RATE_0_01;

        if (safePositive(goods.getFirstMoney()).signum() > 0) {
            dealerDirectValue = goods.getFirstMoney();
        }
        if (safePositive(goods.getSecondMoney()).signum() > 0) {
            dealerSimpleValue = goods.getSecondMoney();
        }
        if (safePositive(goods.getThirdMoney()).signum() > 0) {
            dealerThirdValue = goods.getThirdMoney();
        }
        if (safePositive(goods.getFirstDividend()).signum() > 0) {
            storeDirectValue = goods.getFirstDividend();
        }
        if (safePositive(goods.getSecondDividend()).signum() > 0) {
            storeSimpleValue = goods.getSecondDividend();
        }

        return new CommissionConfig(
            commissionType,
            dealerDirectValue,
            dealerSimpleValue,
            dealerThirdValue,
            storeDirectValue,
            storeSimpleValue
        );
    }

    private BigDecimal safeValue(BigDecimal v) {
        return v != null ? v : BigDecimal.ZERO;
    }

    private BigDecimal safePositive(BigDecimal v) {
        return v != null && v.signum() > 0 ? v : BigDecimal.ZERO;
    }

    private static class OrderGoodsInfo {
        private final ShopGoods goods;
        private final int quantity;

        private OrderGoodsInfo(ShopGoods goods, int quantity) {
            this.goods = goods;
            this.quantity = Math.max(1, quantity);
        }
    }

    private static class CommissionConfig {
        private final Integer commissionType;
        private final BigDecimal dealerDirectValue;
        private final BigDecimal dealerSimpleValue;
        private final BigDecimal dealerThirdValue;
        private final BigDecimal storeDirectValue;
        private final BigDecimal storeSimpleValue;

        private static CommissionConfig defaultRate() {
            return new CommissionConfig(20, RATE_0_10, RATE_0_05, BigDecimal.ZERO, RATE_0_02, RATE_0_01);
        }

        private CommissionConfig(
            Integer commissionType,
            BigDecimal dealerDirectValue,
            BigDecimal dealerSimpleValue,
            BigDecimal dealerThirdValue,
            BigDecimal storeDirectValue,
            BigDecimal storeSimpleValue
        ) {
            this.commissionType = commissionType != null ? commissionType : 20;
            this.dealerDirectValue = dealerDirectValue != null ? dealerDirectValue : BigDecimal.ZERO;
            this.dealerSimpleValue = dealerSimpleValue != null ? dealerSimpleValue : BigDecimal.ZERO;
            this.dealerThirdValue = dealerThirdValue != null ? dealerThirdValue : BigDecimal.ZERO;
            this.storeDirectValue = storeDirectValue != null ? storeDirectValue : BigDecimal.ZERO;
            this.storeSimpleValue = storeSimpleValue != null ? storeSimpleValue : BigDecimal.ZERO;
        }
    }

    private static class DealerRefereeCommission {
        private final Integer directDealerId;
        private final BigDecimal directMoney;
        private final Integer simpleDealerId;
        private final BigDecimal simpleMoney;
        private final Integer thirdDealerId;
        private final BigDecimal thirdMoney;

        private DealerRefereeCommission(
            Integer directDealerId,
            BigDecimal directMoney,
            Integer simpleDealerId,
            BigDecimal simpleMoney,
            Integer thirdDealerId,
            BigDecimal thirdMoney
        ) {
            this.directDealerId = directDealerId;
            this.directMoney = directMoney != null ? directMoney : BigDecimal.ZERO;
            this.simpleDealerId = simpleDealerId;
            this.simpleMoney = simpleMoney != null ? simpleMoney : BigDecimal.ZERO;
            this.thirdDealerId = thirdDealerId;
            this.thirdMoney = thirdMoney != null ? thirdMoney : BigDecimal.ZERO;
        }
    }

    private static class DealerRefereeCommissionV2 {
        private final Integer directDealerId;
        private final BigDecimal directMoney;
        private final Integer simpleDealerId;
        private final BigDecimal simpleMoney;

        private DealerRefereeCommissionV2(
                Integer directDealerId,
                BigDecimal directMoney,
                Integer simpleDealerId,
                BigDecimal simpleMoney
        ) {
            this.directDealerId = directDealerId;
            this.directMoney = directMoney != null ? directMoney : BigDecimal.ZERO;
            this.simpleDealerId = simpleDealerId;
            this.simpleMoney = simpleMoney != null ? simpleMoney : BigDecimal.ZERO;
        }
    }

    private static class ShopRoleCommission {
        private final Integer storeDirectUserId;
        private final BigDecimal storeDirectMoney;
        private final Integer storeSimpleUserId;
        private final BigDecimal storeSimpleMoney;

        private static ShopRoleCommission empty() {
            return new ShopRoleCommission(null, BigDecimal.ZERO, null, BigDecimal.ZERO);
        }

        private ShopRoleCommission(Integer storeDirectUserId, BigDecimal storeDirectMoney, Integer storeSimpleUserId, BigDecimal storeSimpleMoney) {
            this.storeDirectUserId = storeDirectUserId;
            this.storeDirectMoney = storeDirectMoney != null ? storeDirectMoney : BigDecimal.ZERO;
            this.storeSimpleUserId = storeSimpleUserId;
            this.storeSimpleMoney = storeSimpleMoney != null ? storeSimpleMoney : BigDecimal.ZERO;
        }
    }

    private static class TotalDealerCommission {
        private final Integer userId;
        private final BigDecimal money;

        private static TotalDealerCommission empty() {
            return new TotalDealerCommission(null, BigDecimal.ZERO);
        }

        private TotalDealerCommission(Integer userId, BigDecimal money) {
            this.userId = userId;
            this.money = money != null ? money : BigDecimal.ZERO;
        }
    }
}
