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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import com.liquidnet.service.goblin.entity.GoblinGoods;
import com.liquidnet.service.goblin.entity.GoblinGoodsSku;
import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt;
import com.liquidnet.service.goblin.entity.GoblinSqbPerformanceGoods;
import com.liquidnet.service.goblin.mapper.GoblinGoodsMapper;
import com.liquidnet.service.goblin.mapper.GoblinGoodsSkuMapper;
import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper;
import com.liquidnet.service.goblin.mapper.GoblinSqbPerformanceGoodsMapper;
import com.liquidnet.service.goblin.param.shouqianba.request.CommonRequest;
import com.liquidnet.service.goblin.param.shouqianba.request.MallListQueryRequest;
import com.liquidnet.service.goblin.param.shouqianba.request.MallProductsQueryRequest;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallListQueryData;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.IGoblinSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 收钱吧商品同步服务实现
 */
@Slf4j
@Service
public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {

    // TODO: 后期移入配置文件
    private static final String SQB_APPID            = "test_appid";
    private static final String SQB_MERCHANT_ID       = "todo_merchant_id";
    private static final String SQB_MERCHANT_USER_ID  = "todo_merchant_user_id";
    private static final String SQB_ROLE              = "super_admin";
    private static final String SQB_STORE_ID         = "0"; // 平台级商品 store_id=0

    @Autowired
    private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;

    @Autowired
    private IGoblinShouQianBaService goblinShouQianBaService;

    @Autowired
    private GoblinSqbPerformanceGoodsMapper goblinSqbPerformanceGoodsMapper;

    @Autowired
    private GoblinGoodsMapper goblinGoodsMapper;

    @Autowired
    private GoblinGoodsSkuMapper goblinGoodsSkuMapper;

    @Autowired
    private GoblinSqbRedisUtils goblinSqbRedisUtils;

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;

    @Autowired
    private GoblinMongoUtils goblinMongoUtils;

    @Autowired
    private QueueUtils queueUtils;

    // ================================ 获取所有商城商品 ================================

    /**
     * 获取所有商城及商品列表
     * 自动拉取所有商城，循环获取每个商城的商品列表，聚合返回
     */
    @Override
    public ResponseDto<List<GoblinSqbPerfGoodsVo>> getAllMallProducts() {
        List<GoblinSqbPerfGoodsVo> result = new ArrayList<>();

        try {
            // 1. 调用收钱吧获取商城列表
            MallListQueryRequest mallListRequest = new MallListQueryRequest();
            mallListRequest.setAppid(SQB_APPID);
            // 过滤条件：只查已上线的商城
            MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter();
            CommonRequest.Seller seller = buildSeller();
            filter.setSeller(seller);
            filter.setState((byte) 1); // 1=已上线
            mallListRequest.setFilter(filter);
            // 分页：每次取 100 个
            MallListQueryRequest.Cursor cursor = new MallListQueryRequest.Cursor();
            cursor.setCount(100);
            mallListRequest.setCursor(cursor);

            List<MallListQueryData> mallList = goblinShouQianBaService.queryMallList(mallListRequest);
            if (CollectionUtils.isEmpty(mallList)) {
                log.warn("[收钱吧] 未查询到任何商城信息");
                return ResponseDto.success(result);
            }

            // 2. 循环每个商城获取商品列表
            for (MallListQueryData mall : mallList) {
                String mallSn = mall.getMallSn();
                if (StringUtils.isEmpty(mallSn)) continue;

                try {
                    MallProductsQueryRequest productsRequest = new MallProductsQueryRequest();
                    productsRequest.setAppid(SQB_APPID);
                    productsRequest.setSeller(seller);

                    CommonRequest.Mall mallId = new CommonRequest.Mall();
                    mallId.setMallSn(mallSn);
                    mallId.setSignature(mall.getSignature());
                    productsRequest.setMallID(mallId);

                    List<MallProductsQueryData> productsDataList = goblinShouQianBaService.queryMallProducts(productsRequest);
                    if (CollectionUtils.isEmpty(productsDataList)) {
                        log.warn("[收钱吧商品同步] 商城 {} 获取商品列表为空", mallSn);
                        continue;
                    }

                    // 3. 将商品数据转换为 VO
                    for (MallProductsQueryData productsData : productsDataList) {
                        if (productsData == null || CollectionUtils.isEmpty(productsData.getSkuModels())) continue;
                        
                        String coverPic = null;
                        if (!CollectionUtils.isEmpty(productsData.getConverImages())) {
                            coverPic = productsData.getConverImages().get(0);
                        }
                        for (MallProductsQueryData.Sku sku : productsData.getSkuModels()) {
                            GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
                            vo.setSpuId(productsData.getSpuId());
                            vo.setSpuName(productsData.getTitle());
                            vo.setSkuId(sku.getSkuId());
                            String skuName = sku.getSkuName() != null ? sku.getSkuName() : sku.getSkuTitle();
                            vo.setSkuName(skuName);
                            vo.setPrice(sku.getPrice());
                            vo.setCoverPic(coverPic);
                            result.add(vo);
                        }
                    }
                } catch (Exception e) {
                    log.error("[收钱吧商品同步] 获取商城 {} 商品列表异常", mallSn, e);
                }
            }
        } catch (Exception e) {
            log.error("[收钱吧商品同步] getAllMallProducts 异常", e);
            return ResponseDto.failure("获取商城商品列表失败：" + e.getMessage());
        }

        log.info("[收钱吧商品同步] getAllMallProducts 完成，共 {} 个 SKU", result.size());
        return ResponseDto.success(result);
    }

    // ================================ 批量同步商品到 goblin 系统 ================================

    /**
     * 批量同步商品到 goblin 系统
     * <p>
     * 流程：对每个 sqbProductId，调用收钱吧查询商品详情，
     * 写入 goblin_goods + goblin_goods_sku + goblin_sqb_goods_ext
     * </p>
     *
     * @param items 待同步商品列表：每项包含 mallSn、sqbProductId、sqbProductSn（来自收钱吧）
     * @return 同步结果摘要
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> syncGoods(List<Map<String, String>> items) {
        if (CollectionUtils.isEmpty(items)) {
            return ResponseDto.failure("同步商品列表不能为空");
        }

        int newCount    = 0;
        int existCount  = 0;
        int failCount   = 0;
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        for (Map<String, String> item : items) {
            String sqbProductId  = item.get("sqbProductId");
            String sqbProductSn  = item.get("sqbProductSn");
            String mallSn        = item.get("mallSn");
            String mallSignature = item.get("mallSignature"); // 商城签名，用于查商品

            if (StringUtils.isEmpty(sqbProductId)) {
                log.warn("[收钱吧商品同步] sqbProductId 为空，跳过: {}", item);
                failCount++;
                continue;
            }

            try {
                // Step 1: 幂等检查 —— 已存在则跳过
                LambdaQueryWrapper<GoblinSqbGoodsExt> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(GoblinSqbGoodsExt::getSqbProductId, sqbProductId);
                GoblinSqbGoodsExt existing = goblinSqbGoodsExtMapper.selectOne(queryWrapper);

                if (existing != null) {
                    log.info("[收钱吧商品同步] 商品已存在，sqbProductId={}, spuId={}, skuId={}",
                            sqbProductId, existing.getSpuId(), existing.getSkuId());
                    existCount++;
                    continue;
                }

                // Step 2: 查询收钱吧商品详情（通过 queryMallProducts）
                MallProductsQueryData productsData = null;
                if (!StringUtils.isEmpty(mallSn)) {
                    MallProductsQueryRequest productsRequest = new MallProductsQueryRequest();
                    productsRequest.setAppid(SQB_APPID);
                    productsRequest.setSeller(buildSeller());
                    CommonRequest.Mall mallId = new CommonRequest.Mall();
                    mallId.setMallSn(mallSn);
                    mallId.setSignature(mallSignature);
                    productsRequest.setMallID(mallId);
                    List<MallProductsQueryData> productsDataList = goblinShouQianBaService.queryMallProducts(productsRequest);
                    if (!CollectionUtils.isEmpty(productsDataList)) {
                        for (MallProductsQueryData data : productsDataList) {
                            if (sqbProductId.equals(data.getSpuId())) {
                                productsData = data;
                                break;
                            }
                        }
                    }
                }

                // Step 3: 生成本地 spuId
                String spuId = IDGenerator.nextSnowId();

                // Step 4: 构建 GoblinGoodsInfoVo
                GoblinGoodsInfoVo goodsInfoVo = buildGoblinGoodsInfoVo(spuId, productsData, now);
                log.info("[收钱吧商品同步] 准备写入商品，spuId={}", spuId);

                // Step 5: 遍历 SKU，构建 GoblinGoodsSkuInfoVo 及写 EXT 表
                List<MallProductsQueryData.Sku> sqbSkus = productsData != null && !CollectionUtils.isEmpty(productsData.getSkuModels())
                        ? productsData.getSkuModels() : Collections.emptyList();
                List<GoblinGoodsSkuInfoVo> skuInfoVos = new ArrayList<>();
                List<String> skuIdList = new ArrayList<>();

                if (CollectionUtils.isEmpty(sqbSkus)) {
                    // 没有 SKU 数据时，创建一个占位 SKU
                    String skuId = IDGenerator.nextSnowId();
                    GoblinGoodsSkuInfoVo skuVo = buildGoblinGoodsSkuInfoVo(skuId, spuId, null, productsData, now);
                    skuInfoVos.add(skuVo);
                    skuIdList.add(skuId);

                    GoblinSqbGoodsExt ext = buildExt(spuId, skuId, mallSn, sqbProductId, sqbProductSn, null, now);
                    goblinSqbGoodsExtMapper.insert(ext);
                    log.info("[收钱吧商品同步] 写入占位 SKU，skuId={}", skuId);
                } else {
                    for (MallProductsQueryData.Sku sqbSku : sqbSkus) {
                        String skuId = IDGenerator.nextSnowId();
                        GoblinGoodsSkuInfoVo skuVo = buildGoblinGoodsSkuInfoVo(skuId, spuId, sqbSku, productsData, now);
                        skuInfoVos.add(skuVo);
                        skuIdList.add(skuId);

                        GoblinSqbGoodsExt ext = buildExt(spuId, skuId, mallSn, sqbProductId, sqbProductSn, sqbSku.getSkuId(), now);
                        goblinSqbGoodsExtMapper.insert(ext);
                        log.info("[收钱吧商品同步] 写入 SKU，skuId={}, sqbSkuId={}", skuId, sqbSku.getSkuId());
                    }
                }
                goodsInfoVo.setSkuIdList(skuIdList);

                // Step 6: 组装价格区间
                if (!CollectionUtils.isEmpty(skuInfoVos)) {
                    long minPrice = skuInfoVos.stream().mapToLong(s -> s.getPrice() != null ? s.getPrice().multiply(BigDecimal.valueOf(100)).longValue() : 0L).min().orElse(0L);
                    long maxPrice = skuInfoVos.stream().mapToLong(s -> s.getPrice() != null ? s.getPrice().multiply(BigDecimal.valueOf(100)).longValue() : 0L).max().orElse(0L);
                    goodsInfoVo.setPriceGe(BigDecimal.valueOf(minPrice).divide(BigDecimal.valueOf(100)));
                    goodsInfoVo.setPriceLe(BigDecimal.valueOf(maxPrice).divide(BigDecimal.valueOf(100)));
                    goodsInfoVo.setSellPrice(BigDecimal.valueOf(minPrice).divide(BigDecimal.valueOf(100)));
                }

                // Step 7: 写 MongoDB
                goblinMongoUtils.setGoodsInfoVo(goodsInfoVo);
                goblinMongoUtils.setGoodsSkuInfoVos(skuInfoVos);

                // Step 8: 发队列通知及 Redis 库存写入
                LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
                LinkedList<Object[]> initGoodsObjs = CollectionUtil.linkedListObjectArr();
                LinkedList<Object[]> initGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
                LinkedList<Object[]> initGoodsImageObjs = CollectionUtil.linkedListObjectArr();
                
                toMqSqls.add(SqlMapping.get("goblin_goods.insert"));
                initGoodsObjs.add(new Object[]{
                        spuId, goodsInfoVo.getSpuNo(), goodsInfoVo.getSpuBarCode(), goodsInfoVo.getSpuErpCode(), goodsInfoVo.getErpType(),
                        goodsInfoVo.getName(), goodsInfoVo.getSubtitle(), goodsInfoVo.getSellPrice(), goodsInfoVo.getPriceGe(), goodsInfoVo.getPriceLe(),
                        goodsInfoVo.getIntro(), goodsInfoVo.getDetails(), goodsInfoVo.getCoverPic(), goodsInfoVo.getVideo(), goodsInfoVo.getSpecMode(),
                        goodsInfoVo.getStoreId(), goodsInfoVo.getCateFid(), goodsInfoVo.getCateSid(), goodsInfoVo.getCateTid(), goodsInfoVo.getStoreCateFid(),
                        goodsInfoVo.getStoreCateSid(), goodsInfoVo.getStoreCateTid(), goodsInfoVo.getBrandId(), goodsInfoVo.getShelvesHandle(), goodsInfoVo.getShelvesTime(),
                        goodsInfoVo.getSpuValidity(), goodsInfoVo.getVirtualFlg(), goodsInfoVo.getStatus(), goodsInfoVo.getShelvesStatus(), goodsInfoVo.getSpuAppear(),
                        goodsInfoVo.getShelvesAt(), goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(), goodsInfoVo.getLogisticsTemplate()
                });

                toMqSqls.add(SqlMapping.get("goblin_goods_sku.insert"));
                for (GoblinGoodsSkuInfoVo skuInfoVo : skuInfoVos) {
                    // 写 Redis 库存
                    goblinRedisUtils.setSkuStock(null, skuInfoVo.getSkuId(), skuInfoVo.getStock());
                    
                    initGoodsSkuObjs.add(new Object[]{
                            skuInfoVo.getSkuId(), skuInfoVo.getSpuId(), skuInfoVo.getSkuNo(), skuInfoVo.getSkuBarCode(), skuInfoVo.getSkuErpCode(),
                            skuInfoVo.getErpType(), skuInfoVo.getErpHosting(), skuInfoVo.getErpWarehouseNo(), skuInfoVo.getSkuType(), skuInfoVo.getName(),
                            skuInfoVo.getSubtitle(), skuInfoVo.getSellPrice(), skuInfoVo.getSkuPic(), skuInfoVo.getSkuIsbn(), skuInfoVo.getStock(),
                            skuInfoVo.getSkuStock(), skuInfoVo.getWarningStock(), skuInfoVo.getPrice(), skuInfoVo.getPriceMember(), skuInfoVo.getWeight(),
                            skuInfoVo.getBuyFactor(), skuInfoVo.getBuyRoster(), skuInfoVo.getBuyLimit(), skuInfoVo.getStoreId(), skuInfoVo.getSkuValidity(),
                            skuInfoVo.getVirtualFlg(), skuInfoVo.getStatus(), skuInfoVo.getShelvesStatus(), skuInfoVo.getSkuAppear(), skuInfoVo.getShelvesAt(),
                            goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(), skuInfoVo.getLogisticsTemplate()
                    });
                }
                
                toMqSqls.add(SqlMapping.get("goblin_goods_image.insert_byreplace"));
                if (!CollectionUtils.isEmpty(goodsInfoVo.getImageList())) {
                    goodsInfoVo.getImageList().forEach(imageUrl -> initGoodsImageObjs.add(new Object[]{spuId, imageUrl}));
                }

                queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(),
                        SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsSkuObjs, initGoodsImageObjs));
                
                log.info("[收钱吧商品同步] Redis及MongoDB写入、MQ消息发送成功，sqbProductId={}", sqbProductId);

                newCount++;
            } catch (Exception e) {
                log.error("[收钱吧商品同步] 处理商品异常，sqbProductId={}", sqbProductId, e);
                failCount++;
            }
        }

        String summary = String.format("同步完成：新增 %d 条，已存在 %d 条，失败 %d 条", newCount, existCount, failCount);
        log.info("[收钱吧商品同步] {}", summary);
        return ResponseDto.success(summary);
    }

    // ================================ 查询演出关联商品 ================================

    /**
     * 查询演出关联商品列表
     * 先查 Redis 缓存（TTL 5min），未命中则查 MySQL 并写入缓存
     */
    @Override
    public ResponseDto<List<GoblinSqbPerfGoodsVo>> getPerfGoods(String performancesId) {
        // 1. 先查 Redis 缓存
        List<GoblinSqbPerfGoodsVo> cached = goblinSqbRedisUtils.getPerfGoods(performancesId);
        if (cached != null) {
            return ResponseDto.success(cached);
        }

        // 2. 缓存未命中，查 MySQL
        try {
            LambdaQueryWrapper<GoblinSqbPerformanceGoods> query = new LambdaQueryWrapper<>();
            query.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId)
                    .eq(GoblinSqbPerformanceGoods::getStatus, 1)
                    .orderByAsc(GoblinSqbPerformanceGoods::getSort);
            List<GoblinSqbPerformanceGoods> relations = goblinSqbPerformanceGoodsMapper.selectList(query);

            if (CollectionUtils.isEmpty(relations)) {
                List<GoblinSqbPerfGoodsVo> empty = new ArrayList<>();
                goblinSqbRedisUtils.setPerfGoods(performancesId, empty);
                return ResponseDto.success(empty);
            }

            // 收集 skuId 和 spuId
            List<String> skuIds = relations.stream()
                    .map(GoblinSqbPerformanceGoods::getSkuId)
                    .collect(Collectors.toList());
            List<String> spuIds = relations.stream()
                    .map(GoblinSqbPerformanceGoods::getSpuId)
                    .distinct()
                    .collect(Collectors.toList());

            // 批量查询 SKU 信息
            LambdaQueryWrapper<GoblinGoodsSku> skuQuery = new LambdaQueryWrapper<>();
            skuQuery.in(GoblinGoodsSku::getSkuId, skuIds);
            List<GoblinGoodsSku> skuList = goblinGoodsSkuMapper.selectList(skuQuery);
            Map<String, GoblinGoodsSku> skuMap = skuList.stream()
                    .collect(Collectors.toMap(GoblinGoodsSku::getSkuId, Function.identity(), (a, b) -> a));

            // 批量查询 SPU 信息
            LambdaQueryWrapper<GoblinGoods> spuQuery = new LambdaQueryWrapper<>();
            spuQuery.in(GoblinGoods::getSpuId, spuIds);
            List<GoblinGoods> spuList = goblinGoodsMapper.selectList(spuQuery);
            Map<String, GoblinGoods> spuMap = spuList.stream()
                    .collect(Collectors.toMap(GoblinGoods::getSpuId, Function.identity(), (a, b) -> a));

            // 组装 VO
            List<GoblinSqbPerfGoodsVo> result = new ArrayList<>();
            for (GoblinSqbPerformanceGoods rel : relations) {
                GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
                vo.setSkuId(rel.getSkuId());
                vo.setSpuId(rel.getSpuId());
                vo.setSort(rel.getSort());

                GoblinGoodsSku sku = skuMap.get(rel.getSkuId());
                if (sku != null) {
                    vo.setSkuName(sku.getName());
                    vo.setPrice(sku.getPrice() != null ? sku.getPrice().longValue() : null);
                }

                GoblinGoods spu = spuMap.get(rel.getSpuId());
                if (spu != null) {
                    vo.setSpuName(spu.getName());
                    vo.setCoverPic(spu.getCoverPic());
                }

                result.add(vo);
            }

            // 3. 写入 Redis 缓存（TTL 5min）
            goblinSqbRedisUtils.setPerfGoods(performancesId, result);

            return ResponseDto.success(result);
        } catch (Exception e) {
            log.error("[收钱吧] getPerfGoods 异常，performancesId={}", performancesId, e);
            return ResponseDto.failure("查询演出关联商品失败：" + e.getMessage());
        }
    }

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

    private CommonRequest.Seller buildSeller() {
        CommonRequest.Seller seller = new CommonRequest.Seller();
        seller.setMerchantId(SQB_MERCHANT_ID);
        seller.setMerchantUserId(SQB_MERCHANT_USER_ID);
        seller.setRole(SQB_ROLE);
        return seller;
    }

    /**
     * 构建 GoblinGoodsInfoVo（收钱吧商品固定字段）
     */
    private GoblinGoodsInfoVo buildGoblinGoodsInfoVo(String spuId, MallProductsQueryData productsData, String now) {
        GoblinGoodsInfoVo goods = new GoblinGoodsInfoVo();
        goods.setSpuId(spuId);
        goods.setSpuNo(spuId);
        goods.setSpuType(33);       // 33 = 收钱吧商品
        goods.setVirtualFlg("1");   // 虚拟商品
        goods.setStatus("3");       // 3 = 审核通过（收钱吧商品无需审核）
        goods.setShelvesHandle("2"); // 2 = 直接上架售卖
        goods.setShelvesStatus("3"); // 3 = 上架
        goods.setSpuAppear("0");    // 默认展示
        goods.setDelFlg("0");       // 未删除
        goods.setStoreId(SQB_STORE_ID);
        goods.setCreatedBy("system");
        goods.setCreatedAt(LocalDateTime.now());
        goods.setUpdatedBy("system");
        goods.setUpdatedAt(LocalDateTime.now());
        goods.setImageList(new ArrayList<>());
        
        if (productsData != null) {
            goods.setName(productsData.getTitle());
            goods.setIntro(productsData.getProductIntroduction());
            if (!CollectionUtils.isEmpty(productsData.getConverImages())) {
                goods.setCoverPic(productsData.getConverImages().get(0));
                goods.setImageList(new ArrayList<>(productsData.getConverImages()));
            }
        } else {
            goods.setName("收钱吧商品-" + spuId);
        }
        goods.setSkuIdList(new ArrayList<>());
        return goods;
    }

    /**
     * 构建 GoblinGoodsSkuInfoVo 实体
     */
    private GoblinGoodsSkuInfoVo buildGoblinGoodsSkuInfoVo(String skuId, String spuId,
                                                           MallProductsQueryData.Sku sqbSku,
                                                           MallProductsQueryData productsData,
                                                           String now) {
        GoblinGoodsSkuInfoVo sku = new GoblinGoodsSkuInfoVo();
        sku.setSkuId(skuId);
        sku.setSpuId(spuId);
        sku.setSkuNo(skuId);
        sku.setSkuType(33);         // 33 = 收钱吧商品
        sku.setVirtualFlg("1");     // 虚拟商品
        sku.setStatus("3");         // 审核通过
        sku.setShelvesHandle("2");  // 直接上架
        sku.setShelvesStatus("3");  // 上架
        sku.setSkuAppear("0");
        sku.setBuyFactor("0");      // 全部用户可买
        sku.setBuyLimit(0);         // 不限购
        sku.setDelFlg("0");
        sku.setStoreId(SQB_STORE_ID);
        sku.setCreatedBy("system");
        sku.setCreatedAt(LocalDateTime.now());
        sku.setUpdatedBy("system");
        sku.setUpdatedAt(LocalDateTime.now());

        if (sqbSku != null) {
            // SKU 名称
            String skuName = sqbSku.getSkuName() != null ? sqbSku.getSkuName() : sqbSku.getSkuTitle();
            sku.setName(skuName != null ? skuName : (productsData != null ? productsData.getTitle() : "规格"));
            // 收钱吧价格单位为分，转元
            if (sqbSku.getPrice() != null) {
                BigDecimal priceYuan = BigDecimal.valueOf(sqbSku.getPrice()).divide(BigDecimal.valueOf(100));
                sku.setPrice(priceYuan);
                sku.setSellPrice(priceYuan);
            }
            // 库存：优先取 quantity，若为 null 则默认 9999
            int stock = sqbSku.getQuantity() != null ? sqbSku.getQuantity().intValue() : 9999;
            sku.setStock(stock);
            sku.setSkuStock(stock);

            if (productsData != null && !CollectionUtils.isEmpty(productsData.getConverImages())) {
                sku.setSkuPic(productsData.getConverImages().get(0));
            }
        } else {
            sku.setName(productsData != null ? productsData.getTitle() : "规格");
            sku.setPrice(BigDecimal.ZERO);
            sku.setSellPrice(BigDecimal.ZERO);
            sku.setStock(0);
            sku.setSkuStock(0);
        }
        return sku;
    }

    /**
     * 构建 GoblinSqbGoodsExt 实体
     */
    private GoblinSqbGoodsExt buildExt(String spuId, String skuId, String mallSn,
                                         String sqbProductId, String sqbProductSn,
                                         String sqbSkuId, String now) {
        GoblinSqbGoodsExt ext = new GoblinSqbGoodsExt();
        ext.setSpuId(spuId);
        ext.setSkuId(skuId);
        ext.setMallSn(mallSn);
        ext.setSqbProductId(sqbProductId);
        ext.setSqbProductSn(sqbProductSn);
        ext.setSqbSkuId(sqbSkuId);
        ext.setCreatedAt(now);
        ext.setUpdatedAt(now);
        return ext;
    }
}
