package com.gxwebsoft.shop.task;

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.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.entity.ShopDealerReferee;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.service.ShopDealerOrderService;
import com.gxwebsoft.shop.service.ShopDealerRefereeService;
import com.gxwebsoft.shop.service.ShopDealerUserService;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.util.UpstreamUserFinder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
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.format.DateTimeFormatter;
import java.util.*;

/**
 * 租户10584：分销订单结算任务
 * <p>
 * 每20秒执行一次，查询“已付款且未结算”的订单，按指定规则发放佣金并将订单置为已结算。
 */
@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_03 = new BigDecimal("0.03");
    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 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 ShopGoodsService shopGoodsService;

    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;

    @Resource
    private UserMapper userMapper;

    /**
     * 每30秒执行一次。
     */
    @Scheduled(cron = "0/20 * * * * ?")
    @IgnoreTenant("该定时任务仅处理租户10584，但需要显式按tenantId过滤，避免定时任务线程无租户上下文导致查询异常")
    public void settleTenant10584Orders() {
        try {
            List<ShopOrder> orders = findUnsettledPaidOrders();
            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<>();

            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())) {
                            return;
                        }
                        settleOneOrder(order, level1ParentCache, shopRoleCache);
                    });
                } catch (Exception e) {
                    log.error("订单结算失败，将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
                }
            }
        } catch (Exception e) {
            log.error("租户{}分销订单结算任务执行失败", TENANT_ID, e);
        }
    }

    private List<ShopOrder> findUnsettledPaidOrders() {
        return shopOrderService.list(
            new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getTenantId, TENANT_ID)
                .eq(ShopOrder::getDeleted, 0)
                .eq(ShopOrder::getPayStatus, true)
                .eq(ShopOrder::getIsSettled, 0)
                .orderByAsc(ShopOrder::getOrderId)
                .last("limit " + MAX_ORDERS_PER_RUN)
        );
    }

    private boolean claimOrderToSettle(Integer orderId) {
        return shopOrderService.update(
            new LambdaUpdateWrapper<ShopOrder>()
                .eq(ShopOrder::getOrderId, orderId)
                .eq(ShopOrder::getTenantId, TENANT_ID)
                .eq(ShopOrder::getIsSettled, 0)
                .set(ShopOrder::getIsSettled, 1)
        );
    }

    private void settleOneOrder(ShopOrder order, Map<Integer, Integer> level1ParentCache, Map<Integer, Boolean> shopRoleCache) {
        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);

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

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

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

    private DealerRefereeCommission settleDealerRefereeCommission(ShopOrder order, BigDecimal baseAmount, int goodsQty, CommissionConfig commissionConfig) {
        // 兼容两种数据形态：
        // 1) 同一 userId 下有 level=1/2 的多级关系（直接按 level 取）；
        // 2) 仅维护 level=1（用“查两次”回退获取上级）。
        Integer directDealerId = getDealerRefereeId(order.getUserId(), 1);
        Integer simpleDealerId = getDealerRefereeId(order.getUserId(), 2);
        if (simpleDealerId == null && directDealerId != null) {
            simpleDealerId = getDealerRefereeId(directDealerId, 1);
        }
        Integer 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%)：对方=直推分销商（便于在资金明细中看出“来自哪个下级分销商/团队订单”）
        creditDealerCommission(
            directDealerId,
            directMoney,
            order,
            order.getUserId(),
            buildCommissionComment("直推佣金", commissionConfig.commissionType, commissionConfig.dealerDirectValue, goodsQty)
        );
        creditDealerCommission(
            simpleDealerId,
            simpleMoney,
            order,
            directDealerId,
            buildCommissionComment("推荐奖", commissionConfig.commissionType, commissionConfig.dealerSimpleValue, goodsQty)
        );
        creditDealerCommission(
            thirdDealerId,
            thirdMoney,
            order,
            simpleDealerId,
            buildCommissionComment("第3级佣金", commissionConfig.commissionType, commissionConfig.dealerThirdValue, goodsQty)
        );

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

    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);
    }

    /**
     * 门店分红规则：
     * - 门店角色为 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);

        // 先累加佣金到分销商账户（避免并发下丢失更新，用SQL自增）
        boolean updated = shopDealerUserService.update(
            new LambdaUpdateWrapper<ShopDealerUser>()
                .eq(ShopDealerUser::getTenantId, TENANT_ID)
                .eq(ShopDealerUser::getUserId, dealerUserId)
                .setSql("money = IFNULL(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 {
                    User sysUser = userMapper.selectByIdIgnoreTenant(dealerUserId);
                    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("money = IFNULL(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
    ) {
        // 幂等：同一订单只写一条（依赖 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));

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

    private String buildCommissionTraceComment(DealerRefereeCommission dealerRefereeCommission, ShopRoleCommission shopRoleCommission) {
        // 轻量“过程”留痕，方便排查；详细分佣以 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;
    }

    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 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;
        }
    }
}
