package cn.qihangerp.service.external.pdd;

import cn.qihangerp.model.entity.OGoods;
import cn.qihangerp.model.entity.OGoodsSku;
import cn.qihangerp.model.request.ExternalGoodsUpsertRequest;
import cn.qihangerp.model.request.ExternalPddGoodsDetailRequest;
import cn.qihangerp.model.vo.ExternalGoodsUpsertResultVo;
import cn.qihangerp.model.vo.ExternalPddGoodsDetailResultVo;
import cn.qihangerp.module.service.OGoodsService;
import cn.qihangerp.module.service.OGoodsSkuService;
import cn.qihangerp.service.external.ExternalPddGoodsDetailAppService;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <p><b>平台商品映射由 ERP-Open 落库</b>：中台仅调用 {@code /external/goods/upsert}、改库存等 HTTP，不持久化拼多多/京东等平台侧 ID。
 * 各渠道在 {@code o_goods}/{@code o_goods_sku}.{@code canonicalExt} 使用<strong>独立键名</strong>（拼多多为 {@value #CANONICAL_PDD_GOODS_ID}、{@value #CANONICAL_PDD_SKU_ID}），
 * 未来京东/天猫可并行增加 {@code jdSkuId} 等，改库存接口按平台从本库解析后再调 POP。</p>
 *
 * <p>拼多多：{@code pdd.goods.add} 响应可解析 SKU 映射；{@code pdd.goods.information.update} 往往不带 {@code sku_list}，
 * 因此在 upsert 成功后若仍有 SKU 未写入 {@value #CANONICAL_PDD_SKU_ID}，将自动补调 {@code pdd.goods.detail.get} 回填。</p>
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OGoodsPddMappingPersistence {

    public static final String CANONICAL_PDD_GOODS_ID = "pddGoodsId";
    public static final String CANONICAL_PDD_SKU_ID = "pddSkuId";

    private final OGoodsService goodsService;
    private final OGoodsSkuService skuService;
    private final ExternalPddGoodsDetailAppService externalPddGoodsDetailAppService;

    /**
     * 在 upsert 拼多多链路成功（{@link ExternalGoodsUpsertResultVo#getPddPublishSuccess()}==true）后调用。
     *
     * @param req 用于携带 {@code pddPopAuth}，在需补拉 {@code pdd.goods.detail.get} 时使用；可为 {@code null}（则无法补全 SKU 映射）
     */
    public void persistAfterPddPublishSuccess(Long erpGoodsId, ExternalGoodsUpsertRequest req,
                                              ExternalGoodsUpsertResultVo vo) {
        if (erpGoodsId == null || vo == null || !Boolean.TRUE.equals(vo.getPddPublishSuccess())) {
            return;
        }
        Long pddGoodsId = vo.getPddGoodsId();
        if (pddGoodsId == null || pddGoodsId <= 0) {
            log.warn("[PDD] skip persist mapping: pddGoodsId missing erpGoodsId={}", erpGoodsId);
            return;
        }
        OGoods g = goodsService.getById(erpGoodsId);
        if (g == null) {
            return;
        }
        g.setCanonicalExt(mergeJsonLongField(g.getCanonicalExt(), CANONICAL_PDD_GOODS_ID, pddGoodsId));
        g.setUpdateTime(new Date());
        goodsService.updateById(g);

        Map<String, Long> outerToPddSku = new LinkedHashMap<>();
        String lane = vo.getPddPublishLane();
        if (lane != null && "GOODS_ADD".equalsIgnoreCase(lane.trim())) {
            outerToPddSku.putAll(PddOpenApiSupport.parseOuterKeyToPddSkuIdFromGoodsAddResponse(vo.getPddResponseSnippet()));
        }
        int fromAdd = applyPddSkuMappings(erpGoodsId, outerToPddSku);
        if (!outerToPddSku.isEmpty()) {
            log.info("[PDD] persisted pddGoodsId + sku from GOODS_ADD snippet erpGoodsId={} lane={} skuRowsUpdated={}",
                    erpGoodsId, lane, fromAdd);
        } else {
            log.info("[PDD] persisted pddGoodsId on o_goods (no GOODS_ADD sku_list) erpGoodsId={} lane={}",
                    erpGoodsId, lane);
        }

        if (!anySkuMissingPddSkuId(erpGoodsId)) {
            return;
        }
        if (req == null || req.getPddPopAuth() == null) {
            log.warn("[PDD] skip detail.get backfill: missing pddPopAuth erpGoodsId={} lane={}",
                    erpGoodsId, lane);
            return;
        }

        ExternalPddGoodsDetailRequest dreq = new ExternalPddGoodsDetailRequest();
        dreq.setPddGoodsId(pddGoodsId);
        dreq.setPddPopAuth(req.getPddPopAuth());
        ExternalPddGoodsDetailResultVo detailVo = externalPddGoodsDetailAppService.fetchGoodsDetail(dreq);
        if (!Boolean.TRUE.equals(detailVo.getPopBizSuccess()) || !StringUtils.hasText(detailVo.getPopResponseBody())) {
            log.warn("[PDD] detail.get backfill failed erpGoodsId={} pddGoodsId={} msg={}",
                    erpGoodsId, pddGoodsId, detailVo.getMessage());
            return;
        }
        Map<String, Long> fromDetail =
                PddOpenApiSupport.parseOuterKeyToPddSkuIdFromGoodsDetailGetResponse(detailVo.getPopResponseBody());
        int fromDetailCount = applyPddSkuMappings(erpGoodsId, fromDetail);
        if (fromDetailCount > 0) {
            log.info("[PDD] detail.get backfill applied erpGoodsId={} pddGoodsId={} skuRowsUpdated={}",
                    erpGoodsId, pddGoodsId, fromDetailCount);
        } else if (anySkuMissingPddSkuId(erpGoodsId)) {
            log.warn("[PDD] detail.get ok but no sku_id matched outer_erp_sku_id erpGoodsId={} pddGoodsId={}",
                    erpGoodsId, pddGoodsId);
        }
    }

    /**
     * 将 {@code outerKey -> 拼多多 sku_id} 合并写入 {@code o_goods_sku.canonicalExt}（键 {@value #CANONICAL_PDD_SKU_ID}）。
     *
     * @return 实际更新行数
     */
    private int applyPddSkuMappings(Long erpGoodsId, Map<String, Long> outerToPddSku) {
        if (outerToPddSku == null || outerToPddSku.isEmpty()) {
            return 0;
        }
        List<OGoodsSku> rows = skuService.list(new LambdaQueryWrapper<OGoodsSku>()
                .eq(OGoodsSku::getGoodsId, erpGoodsId));
        if (rows == null || rows.isEmpty()) {
            return 0;
        }
        int updated = 0;
        for (OGoodsSku row : rows) {
            if (row == null || !StringUtils.hasText(row.getOuterErpSkuId())) {
                continue;
            }
            Long pddSkuId = outerToPddSku.get(row.getOuterErpSkuId().trim());
            if (pddSkuId == null || pddSkuId <= 0) {
                continue;
            }
            row.setCanonicalExt(mergeJsonLongField(row.getCanonicalExt(), CANONICAL_PDD_SKU_ID, pddSkuId));
            row.setUpdateTime(new Date());
            skuService.updateById(row);
            updated++;
        }
        return updated;
    }

    private boolean anySkuMissingPddSkuId(Long erpGoodsId) {
        List<OGoodsSku> rows = skuService.list(new LambdaQueryWrapper<OGoodsSku>()
                .eq(OGoodsSku::getGoodsId, erpGoodsId));
        if (rows == null || rows.isEmpty()) {
            return false;
        }
        for (OGoodsSku row : rows) {
            if (row == null || !StringUtils.hasText(row.getOuterErpSkuId())) {
                continue;
            }
            Long v = readCanonicalLong(row.getCanonicalExt(), CANONICAL_PDD_SKU_ID);
            if (v == null || v <= 0) {
                return true;
            }
        }
        return false;
    }

    private static Long readCanonicalLong(String json, String key) {
        if (!StringUtils.hasText(json) || !StringUtils.hasText(key)) {
            return null;
        }
        try {
            JSONObject o = JSON.parseObject(json);
            if (o == null || !o.containsKey(key)) {
                return null;
            }
            return o.getLong(key);
        } catch (Exception e) {
            return null;
        }
    }

    private static String mergeJsonLongField(String existingJson, String field, long value) {
        JSONObject o;
        if (StringUtils.hasText(existingJson)) {
            try {
                o = JSON.parseObject(existingJson);
            } catch (Exception e) {
                o = new JSONObject();
            }
            if (o == null) {
                o = new JSONObject();
            }
        } else {
            o = new JSONObject();
        }
        o.put(field, value);
        return o.toJSONString();
    }
}
