package cn.qihangerp.service.external.impl;

import cn.qihangerp.model.entity.OGoods;
import cn.qihangerp.model.entity.OGoodsSku;
import cn.qihangerp.model.request.ExternalGoodsPddQuantityUpdateRequest;
import cn.qihangerp.model.request.ExternalGoodsUpsertRequest;
import cn.qihangerp.model.vo.ExternalGoodsPddQuantityUpdateResultVo;
import cn.qihangerp.module.service.OGoodsService;
import cn.qihangerp.module.service.OGoodsSkuService;
import cn.qihangerp.service.external.ExternalGoodsPddQuantityUpdateAppService;
import cn.qihangerp.service.external.pdd.ExternalPddProperties;
import cn.qihangerp.service.external.pdd.OGoodsPddMappingPersistence;
import cn.qihangerp.service.external.pdd.PddOpenApiSupport;
import cn.qihangerp.service.external.pdd.PddPopClient;
import cn.qihangerp.service.external.shop.PddShopCredential;
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.Service;
import org.springframework.util.StringUtils;

/**
 * @author guochengyu
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExternalGoodsPddQuantityUpdateAppServiceImpl implements ExternalGoodsPddQuantityUpdateAppService {

    private final ExternalPddProperties props;
    private final PddPopClient pddPopClient;
    private final OGoodsService goodsService;
    private final OGoodsSkuService skuService;

    @Override
    public ExternalGoodsPddQuantityUpdateResultVo updateQuantity(ExternalGoodsPddQuantityUpdateRequest req) {
        if (req == null || req.getShopId() == null || req.getShopId() <= 0) {
            return fail("shopId 无效", null, false, null, null);
        }
        if (!StringUtils.hasText(req.getOutGoodsId())) {
            return fail("outGoodsId 不能为空", null, false, null, null);
        }
        if (!StringUtils.hasText(req.getOutSkuId())) {
            return fail("outSkuId 不能为空", null, false, null, null);
        }
        if (req.getQuantity() == null || req.getQuantity() < 0) {
            return fail("quantity 无效：不能为空且不能为负", null, false, null, null);
        }

        String outGoodsId = req.getOutGoodsId().trim();
        String outSkuId = req.getOutSkuId().trim();

        OGoods goods = goodsService.getOne(new LambdaQueryWrapper<OGoods>()
                .eq(OGoods::getShopId, req.getShopId())
                .eq(OGoods::getOuterErpGoodsId, outGoodsId)
                .last("LIMIT 1"));
        if (goods == null) {
            return fail("商品不存在：shopId=" + req.getShopId() + ", outGoodsId=" + outGoodsId, null, false, null, null);
        }
        Long pddGoodsId = readCanonicalLong(goods.getCanonicalExt(), OGoodsPddMappingPersistence.CANONICAL_PDD_GOODS_ID);
        if (pddGoodsId == null || pddGoodsId <= 0) {
            return fail("本地未找到拼多多 goods_id：请先 upsert 发品成功以写入 o_goods.canonicalExt.pddGoodsId", null, false, null, null);
        }

        OGoodsSku skuRow = skuService.getOne(new LambdaQueryWrapper<OGoodsSku>()
                .eq(OGoodsSku::getShopId, req.getShopId())
                .eq(OGoodsSku::getGoodsId, goods.getId())
                .eq(OGoodsSku::getOuterErpSkuId, outSkuId)
                .last("LIMIT 1"));
        if (skuRow == null) {
            return fail("SKU 不存在：shopId=" + req.getShopId() + ", outSkuId=" + outSkuId, null, false, pddGoodsId, null);
        }
        Long pddSkuId = readCanonicalLong(skuRow.getCanonicalExt(), OGoodsPddMappingPersistence.CANONICAL_PDD_SKU_ID);
        if (pddSkuId == null || pddSkuId <= 0) {
            return fail("本地未找到拼多多 sku_id：请先通过 pdd.goods.add 成功以写入 o_goods_sku.canonicalExt.pddSkuId（information.update 路径可能未回填 SKU 映射）",
                    null, false, pddGoodsId, null);
        }

        PddShopCredential cred = resolveCredential(req);
        if (cred == null || !StringUtils.hasText(cred.getAppKey()) || !StringUtils.hasText(cred.getAppSecret())
                || !StringUtils.hasText(cred.getAccessToken())) {
            return fail("pddPopAuth 不完整：需 appKey、appSecret、accessToken", null, false, pddGoodsId, pddSkuId);
        }
        String gateway = StringUtils.hasText(cred.getGatewayUrl()) ? cred.getGatewayUrl() : props.getGatewayUrl();
        if (!StringUtils.hasText(gateway)) {
            return fail("未配置 POP gatewayUrl", null, false, pddGoodsId, pddSkuId);
        }

        int updateType = req.getUpdateType() != null ? req.getUpdateType() : 1;
        boolean forceUpdate = req.getForceUpdate() == null || Boolean.TRUE.equals(req.getForceUpdate());

        try {
            var biz = PddOpenApiSupport.goodsQuantityUpdateTopLevelParams(
                    pddGoodsId,
                    pddSkuId,
                    req.getOuterId(),
                    req.getQuantity(),
                    updateType,
                    forceUpdate);
            String raw = pddPopClient.invokeTopLevelBiz(
                    gateway,
                    cred.getAppKey(),
                    cred.getAppSecret(),
                    cred.getAccessToken(),
                    "pdd.goods.quantity.update",
                    biz);
            boolean noPopError = !PddOpenApiSupport.isError(raw);
            boolean innerOk = PddOpenApiSupport.parseGoodsQuantityUpdateIsSuccess(raw);
            boolean ok = noPopError && innerOk;
            String msg;
            if (!noPopError) {
                msg = "pdd.goods.quantity.update POP错误: " + PddOpenApiSupport.formatError(raw);
            } else if (!innerOk) {
                msg = "pdd.goods.quantity.update 业务失败: goods_quantity_update_response.is_success=false 或响应缺字段";
            } else {
                msg = "pdd.goods.quantity.update 成功";
            }
            if (log.isDebugEnabled()) {
                log.debug("[PDD] pdd.goods.quantity.update rawResponse shopId={} body={}",
                        req.getShopId(), truncateForLog(raw, 4000));
            }
            log.info("[PDD] pdd.goods.quantity.update outcome shopId={} outGoodsId={} outSkuId={} pddGoodsId={} pddSkuId={} "
                            + "quantity={} updateType={} forceUpdate={} noPopError={} innerSuccess={} popBizSuccess={} message={}",
                    req.getShopId(), outGoodsId, outSkuId, pddGoodsId, pddSkuId, req.getQuantity(), updateType, forceUpdate,
                    noPopError, innerOk, ok, truncateForLog(msg, 500));
            return ExternalGoodsPddQuantityUpdateResultVo.builder()
                    .popBizSuccess(ok)
                    .quantityUpdateSuccess(innerOk)
                    .message(msg)
                    .popResponseBody(raw)
                    .resolvedPddGoodsId(pddGoodsId)
                    .resolvedPddSkuId(pddSkuId)
                    .build();
        } catch (Exception e) {
            log.warn("[PDD] pdd.goods.quantity.update exception shopId={} outGoodsId={} outSkuId={} err={}",
                    req.getShopId(), outGoodsId, outSkuId, e.getMessage(), e);
            return fail(e.getMessage(), null, false, pddGoodsId, pddSkuId);
        }
    }

    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 ExternalGoodsPddQuantityUpdateResultVo fail(String message, String raw, boolean innerOk,
                                                               Long resolvedPddGoodsId, Long resolvedPddSkuId) {
        return ExternalGoodsPddQuantityUpdateResultVo.builder()
                .popBizSuccess(false)
                .quantityUpdateSuccess(innerOk)
                .message(message)
                .popResponseBody(raw)
                .resolvedPddGoodsId(resolvedPddGoodsId)
                .resolvedPddSkuId(resolvedPddSkuId)
                .build();
    }

    private static PddShopCredential resolveCredential(ExternalGoodsPddQuantityUpdateRequest req) {
        if (req == null || req.getPddPopAuth() == null) {
            return null;
        }
        ExternalGoodsUpsertRequest.PddPopAuth a = req.getPddPopAuth();
        PddShopCredential c = new PddShopCredential();
        c.setAppKey(trimToNull(a.getAppKey()));
        c.setAppSecret(trimToNull(a.getAppSecret()));
        c.setAccessToken(trimToNull(a.getAccessToken()));
        if (StringUtils.hasText(a.getGatewayUrl())) {
            c.setGatewayUrl(a.getGatewayUrl().trim());
        }
        c.setSource("REQUEST");
        return c;
    }

    private static String trimToNull(String s) {
        if (!StringUtils.hasText(s)) {
            return null;
        }
        return s.trim();
    }

    private static String truncateForLog(String s, int max) {
        if (s == null) {
            return "";
        }
        return s.length() <= max ? s : s.substring(0, max) + "...(truncated)";
    }
}
