package com.ruoyi.web.controller.jarvis;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.jarvis.domain.JDOrder;
import com.ruoyi.jarvis.domain.OrderRows;
import com.ruoyi.jarvis.service.IJDOrderService;
import com.ruoyi.jarvis.service.ILogisticsService;
import com.ruoyi.jarvis.service.IOrderRowsService;
import com.ruoyi.jarvis.service.IGiftCouponService;
import com.ruoyi.jarvis.domain.GiftCoupon;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * @author Leo
 * @version 1.0
 * @create 2025/8/15 10:53
 * @description：京东指令类
 */
@RestController
@RequestMapping("/jarvis/jdorder")
public class JDOrderController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(JDOrderController.class);
    
    private final IJDOrderService jdOrderService;
    private final IOrderRowsService orderRowsService;
    private final IGiftCouponService giftCouponService;
    private final ISysConfigService sysConfigService;
    private final ILogisticsService logisticsService;
    private static final String CONFIG_KEY_PREFIX = "logistics.push.touser.";
    private static final java.util.regex.Pattern URL_DETECT_PATTERN = java.util.regex.Pattern.compile(
        "(https?://[^\\s]+)|(u\\.jd\\.com/[^\\s]+)",
        java.util.regex.Pattern.CASE_INSENSITIVE);
    private static final java.util.regex.Pattern UJD_LINK_PATTERN = java.util.regex.Pattern.compile(
        "^https?://u\\.jd\\.com/[A-Za-z0-9]+[A-Za-z0-9_-]*$",
        java.util.regex.Pattern.CASE_INSENSITIVE);
    private static final java.util.regex.Pattern JINGFEN_LINK_PATTERN = java.util.regex.Pattern.compile(
        "^https?://jingfen\\.jd\\.com/detail/[A-Za-z0-9]+\\.html$",
        java.util.regex.Pattern.CASE_INSENSITIVE);

    public JDOrderController(IJDOrderService jdOrderService, IOrderRowsService orderRowsService, 
                             IGiftCouponService giftCouponService, ISysConfigService sysConfigService,
                             ILogisticsService logisticsService) {
        this.jdOrderService = jdOrderService;
        this.orderRowsService = orderRowsService;
        this.giftCouponService = giftCouponService;
        this.sysConfigService = sysConfigService;
        this.logisticsService = logisticsService;
    }

    private final static String skey = "2192057370ef8140c201079969c956a3";
    
    @Value("${jarvis.server.jarvis-java.base-url:http://127.0.0.1:6666}")
    private String jarvisJavaBaseUrl;
    
    @Value("${jarvis.server.jarvis-java.jd-api-path:/jd}")
    private String jdApiPath;
    
    /**
     * 获取JD接口请求URL
     */
    private String getRequestUrl() {
        return jarvisJavaBaseUrl + jdApiPath + "/";
    }




    @PostMapping("/generatePromotionContent")
    public AjaxResult generatePromotionContent(@RequestBody Map<String, String> requestBody) {
        String promotionContent = requestBody.get("promotionContent");
        String result = "";
        try {
            String url = getRequestUrl() + "generatePromotionContent";
            JSONObject param = new JSONObject();
            param.put("skey", skey);
            param.put("promotionContent", promotionContent);
            result = HttpUtils.sendJsonPost(url, param.toJSONString());

            // 尝试将 priceInfo.price 提取为顶层 price 字段，并清理文案中的 URL
            try {
                Object parsed = JSON.parse(result);
                if (parsed instanceof JSONArray) {
                    JSONArray arr = (JSONArray) parsed;
                    for (int i = 0; i < arr.size(); i++) {
                        Object el = arr.get(i);
                        if (el instanceof JSONObject) {
                            JSONObject obj = (JSONObject) el;
                            JSONObject priceInfo = obj.getJSONObject("priceInfo");
                            if (priceInfo != null && priceInfo.get("price") != null) {
                                obj.put("price", priceInfo.get("price"));
                            }
                            sanitizeWenan(obj);
                        }
                    }
                    result = arr.toJSONString();
                } else if (parsed instanceof JSONObject) {
                    JSONObject obj = (JSONObject) parsed;
                    if (obj.get("list") instanceof JSONArray) {
                        JSONArray list = obj.getJSONArray("list");
                        for (int i = 0; i < list.size(); i++) {
                            JSONObject o = list.getJSONObject(i);
                            if (o != null) {
                                JSONObject priceInfo = o.getJSONObject("priceInfo");
                                if (priceInfo != null && priceInfo.get("price") != null) {
                                    o.put("price", priceInfo.get("price"));
                                }
                                sanitizeWenan(o);
                            }
                        }
                        obj.put("list", list);
                    } else if (obj.get("data") instanceof JSONArray) {
                        JSONArray data = obj.getJSONArray("data");
                        for (int i = 0; i < data.size(); i++) {
                            JSONObject o = data.getJSONObject(i);
                            if (o != null) {
                                JSONObject priceInfo = o.getJSONObject("priceInfo");
                                if (priceInfo != null && priceInfo.get("price") != null) {
                                    o.put("price", priceInfo.get("price"));
                                }
                                sanitizeWenan(o);
                            }
                        }
                        obj.put("data", data);
                    } else {
                        // 单对象结构也尝试清理
                        sanitizeWenan(obj);
                    }
                    result = obj.toJSONString();
                }
            } catch (Exception ignore) {
                // 返回不是有效JSON时忽略
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return AjaxResult.success(result);
    }

    /**
     * 清理对象中 wenan[].content 的 URL（包含 http/https 及裸露的 u.jd.com 短链）
     */
    private void sanitizeWenan(JSONObject obj) {
        if (obj == null) return;
        Object wenan = obj.get("wenan");
        if (wenan instanceof JSONArray) {
            JSONArray wa = (JSONArray) wenan;
            for (int i = 0; i < wa.size(); i++) {
                Object w = wa.get(i);
                if (w instanceof JSONObject) {
                    JSONObject wj = (JSONObject) w;
                    Object content = wj.get("content");
                    if (!(content instanceof String)) {
                        continue;
                    }
                    String type = wj.getString("type");
                    if ("通用文案".equals(type)) {
                        // 通用文案需要保留链接，用于后续替换/复制
                        continue;
                    }
                    String cleaned = stripUrls((String) content);
                    wj.put("content", cleaned);
                }
            }
        }
    }

    /**
     * 移除文本中的 URL 链接
     */
    private String stripUrls(String text) {
        if (text == null || text.isEmpty()) return text;
        // 移除 http/https 链接
        String cleaned = text.replaceAll("https?://\\S+", "");
        // 移除裸露的 u.jd.com 短链
        cleaned = cleaned.replaceAll("(?i)\\bu\\.jd\\.com/\\S+", "");
        // 压缩多余空白
        cleaned = cleaned.replaceAll("[\\t ]+", " ").replaceAll("\n{3,}", "\n\n").trim();
        return cleaned;
    }

    /**
     * 开礼金（转发到内部服务）
     * 入参：materialUrl 或 skuId，amount(金额，单位元)，quantity(数量)，owner(g/pop)，skuName(可选)
     * 返回：内部服务原样JSON
     */
    @PostMapping("/createGiftCoupon")
    public AjaxResult createGiftCoupon(@RequestBody Map<String, Object> body) {
        try {
            // 添加日志
            logger.info("创建礼金请求 - 参数: materialUrl={}, skuId={}, amount={}, quantity={}, owner={}, skuName={}", 
                body.get("materialUrl"), body.get("skuId"), body.get("amount"), 
                body.get("quantity"), body.get("owner"), body.get("skuName"));
            
            String url = getRequestUrl() + "createGiftCoupon";
            JSONObject param = new JSONObject();
            param.put("skey", skey);
            // 透传必要参数
            if (body.get("materialUrl") != null) param.put("materialUrl", body.get("materialUrl"));
            if (body.get("skuId") != null) param.put("skuId", body.get("skuId"));
            if (body.get("amount") != null) param.put("amount", body.get("amount"));
            if (body.get("quantity") != null) param.put("quantity", body.get("quantity"));
            if (body.get("owner") != null) param.put("owner", body.get("owner"));
            if (body.get("skuName") != null) param.put("skuName", body.get("skuName"));

            logger.info("创建礼金请求 - 发送到内部服务: {}, 参数: {}", url, param.toJSONString());
            
            String result = HttpUtils.sendJsonPost(url, param.toJSONString());
            
            logger.info("创建礼金响应 - 原始响应: {}", result);
            
            // 优先返回JSON对象；若非JSON则按字符串返回
            try {
                Object parsed = JSON.parse(result);
                logger.info("创建礼金响应 - 解析后: {}", parsed);
                
                // 检查返回结果格式
                if (parsed instanceof JSONObject) {
                    JSONObject jsonObj = (JSONObject) parsed;
                    
                    // 检查是否是错误响应（JD项目error方法返回的是{"error": "..."}格式）
                    if (jsonObj.containsKey("error")) {
                        String errorMsg = jsonObj.getString("error");
                        logger.error("创建礼金失败 - JD项目返回错误，请求参数: materialUrl={}, skuId={}, amount={}, quantity={}, owner={}, skuName={}, 错误信息: {}", 
                            body.get("materialUrl"), body.get("skuId"), body.get("amount"), body.get("quantity"), 
                            body.get("owner"), body.get("skuName"), errorMsg);
                        return AjaxResult.error(errorMsg);
                    }
                    
                    // 检查giftCouponKey是否为null（兼容旧格式）
                    Object giftKey = jsonObj.get("giftCouponKey");
                    if (giftKey == null || (giftKey instanceof String && ((String) giftKey).trim().isEmpty())) {
                        // giftCouponKey为null或空，说明创建失败
                        String errorMsg = jsonObj.getString("msg");
                        if (errorMsg == null || errorMsg.isEmpty()) {
                            errorMsg = "礼金创建失败，返回的giftCouponKey为null。可能是商品不支持创建礼金、参数错误或京东API调用失败，请查看JD项目日志";
                        }
                        logger.error("创建礼金失败 - giftCouponKey为null，请求参数: materialUrl={}, skuId={}, amount={}, quantity={}, owner={}, skuName={}, 返回数据: {}", 
                            body.get("materialUrl"), body.get("skuId"), body.get("amount"), body.get("quantity"), 
                            body.get("owner"), body.get("skuName"), jsonObj.toJSONString());
                        return AjaxResult.error(errorMsg);
                    }
                    
                    logger.info("创建礼金成功 - giftCouponKey: {}, 请求参数: owner={}, skuId={}", giftKey, body.get("owner"), body.get("skuId"));
                    
                    // 保存礼金信息到数据库，以便立即在列表中显示
                    try {
                        GiftCoupon giftCoupon = new GiftCoupon();
                        giftCoupon.setGiftCouponKey((String) giftKey);
                        // 优先使用skuId，如果没有则尝试从materialUrl提取
                        String skuId = (String) body.get("skuId");
                        if (skuId == null || skuId.trim().isEmpty()) {
                            String materialUrl = (String) body.get("materialUrl");
                            if (materialUrl != null && !materialUrl.trim().isEmpty()) {
                                // 尝试从URL中提取SKU ID（简单提取，如 item.jd.com/123456.html）
                                java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(?:item\\.jd\\.com|jd\\.com)/(\\d+)", java.util.regex.Pattern.CASE_INSENSITIVE);
                                java.util.regex.Matcher matcher = pattern.matcher(materialUrl);
                                if (matcher.find()) {
                                    skuId = matcher.group(1);
                                } else if (materialUrl.matches("^\\d+$")) {
                                    // 如果是纯数字，直接作为SKU ID
                                    skuId = materialUrl;
                                }
                            }
                        }
                        giftCoupon.setSkuId(skuId);
                        giftCoupon.setSkuName((String) body.get("skuName"));
                        giftCoupon.setOwner((String) body.get("owner"));
                        Object amountObj = body.get("amount");
                        if (amountObj != null) {
                            giftCoupon.setAmount(Double.parseDouble(String.valueOf(amountObj)));
                        }
                        Object quantityObj = body.get("quantity");
                        if (quantityObj != null) {
                            giftCoupon.setQuantity(Integer.parseInt(String.valueOf(quantityObj)));
                        }
                        giftCoupon.setCreateTime(new java.util.Date());
                        
                        // 设置过期时间：自营1天，POP 7天
                        java.util.Calendar cal = java.util.Calendar.getInstance();
                        if ("pop".equalsIgnoreCase((String) body.get("owner"))) {
                            cal.add(java.util.Calendar.DAY_OF_YEAR, 7);
                        } else {
                            cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                        }
                        giftCoupon.setExpireTime(cal.getTime());
                        
                        giftCouponService.insertGiftCoupon(giftCoupon);
                        logger.info("礼金信息已保存到数据库: giftCouponKey={}", giftKey);
                    } catch (Exception e) {
                        logger.error("保存礼金信息到数据库失败", e);
                        // 不中断流程，继续返回成功
                    }
                }
                
                return AjaxResult.success(parsed);
            } catch (Exception ignore) {
                logger.warn("创建礼金响应 - JSON解析失败，返回字符串: {}", result);
                return AjaxResult.success(result);
            }
        } catch (Exception e) {
            logger.error("创建礼金异常", e);
            return AjaxResult.error("开礼金失败: " + e.getMessage());
        }
    }

    /**
     * 转链接口（支持礼金Key），返回短链
     * 入参：materialUrl，giftCouponKey(可选)
     */
    @PostMapping("/transfer")
    public AjaxResult transfer(@RequestBody Map<String, Object> body) {
        try {
            String url = getRequestUrl() + "transfer";
            JSONObject param = new JSONObject();
            param.put("skey", skey);
            if (body.get("materialUrl") != null) param.put("materialUrl", body.get("materialUrl"));
            if (body.get("giftCouponKey") != null) param.put("giftCouponKey", body.get("giftCouponKey"));

            String result = HttpUtils.sendJsonPost(url, param.toJSONString());
            try {
                Object parsed = JSON.parse(result);
                return AjaxResult.success(parsed);
            } catch (Exception ignore) {
                return AjaxResult.success(result);
            }
        } catch (Exception e) {
            return AjaxResult.error("转链失败: " + e.getMessage());
        }
    }

    /**
     * 批量创建礼金券并生成包含礼金的推广链接
     * 入参：skuId/materialUrl, amount, quantity, batchSize, owner, skuName
     * 返回：批量创建结果
     */
    @PostMapping("/batchCreateGiftCoupons")
    public AjaxResult batchCreateGiftCoupons(@RequestBody Map<String, Object> body) {
        try {
            logger.info("批量创建礼金请求 - 参数: materialUrl={}, skuId={}, amount={}, quantity={}, batchSize={}, owner={}, skuName={}", 
                body.get("materialUrl"), body.get("skuId"), body.get("amount"), 
                body.get("quantity"), body.get("batchSize"), body.get("owner"), body.get("skuName"));

            String url = getRequestUrl() + "batchCreateGiftCoupons";
            JSONObject param = new JSONObject();
            param.put("skey", skey);
            if (body.get("materialUrl") != null) param.put("materialUrl", body.get("materialUrl"));
            if (body.get("skuId") != null) param.put("skuId", body.get("skuId"));
            if (body.get("amount") != null) param.put("amount", body.get("amount"));
            if (body.get("quantity") != null) param.put("quantity", body.get("quantity"));
            if (body.get("batchSize") != null) param.put("batchSize", body.get("batchSize"));
            if (body.get("owner") != null) param.put("owner", body.get("owner"));
            if (body.get("skuName") != null) param.put("skuName", body.get("skuName"));

            logger.info("批量创建礼金请求 - 发送到内部服务: {}, 参数: {}", url, param.toJSONString());

            String result = HttpUtils.sendJsonPost(url, param.toJSONString());
            logger.info("批量创建礼金响应 - 原始响应: {}", result);

            try {
                Object parsed = JSON.parse(result);
                
                if (parsed instanceof JSONObject) {
                    JSONObject jsonObj = (JSONObject) parsed;
                    
                    // 检查是否是错误响应
                    if (jsonObj.containsKey("error")) {
                        String errorMsg = jsonObj.getString("error");
                        logger.error("批量创建礼金失败 - JD项目返回错误: {}", errorMsg);
                        return AjaxResult.error(errorMsg);
                    }
                    
                    // 保存成功的礼金到数据库
                    try {
                        JSONArray results = jsonObj.getJSONArray("results");
                        if (results != null) {
                            int savedCount = 0;
                            for (int i = 0; i < results.size(); i++) {
                                JSONObject item = results.getJSONObject(i);
                                if (Boolean.TRUE.equals(item.getBoolean("success"))) {
                                    String giftKey = item.getString("giftCouponKey");
                                    if (giftKey != null && !giftKey.trim().isEmpty()) {
                                        try {
                                            GiftCoupon giftCoupon = new GiftCoupon();
                                            giftCoupon.setGiftCouponKey(giftKey);
                                            
                                            String skuId = (String) body.get("skuId");
                                            if (skuId == null || skuId.trim().isEmpty()) {
                                                String materialUrl = (String) body.get("materialUrl");
                                                if (materialUrl != null && !materialUrl.trim().isEmpty()) {
                                                    java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(?:item\\.jd\\.com|jd\\.com)/(\\d+)", java.util.regex.Pattern.CASE_INSENSITIVE);
                                                    java.util.regex.Matcher matcher = pattern.matcher(materialUrl);
                                                    if (matcher.find()) {
                                                        skuId = matcher.group(1);
                                                    } else if (materialUrl.matches("^\\d+$")) {
                                                        skuId = materialUrl;
                                                    }
                                                }
                                            }
                                            giftCoupon.setSkuId(skuId);
                                            giftCoupon.setSkuName((String) body.get("skuName"));
                                            giftCoupon.setOwner((String) body.get("owner"));
                                            
                                            Object amountObj = body.get("amount");
                                            if (amountObj != null) {
                                                giftCoupon.setAmount(Double.parseDouble(String.valueOf(amountObj)));
                                            }
                                            Object quantityObj = body.get("quantity");
                                            if (quantityObj != null) {
                                                giftCoupon.setQuantity(Integer.parseInt(String.valueOf(quantityObj)));
                                            }
                                            giftCoupon.setCreateTime(new java.util.Date());
                                            
                                            java.util.Calendar cal = java.util.Calendar.getInstance();
                                            if ("pop".equalsIgnoreCase((String) body.get("owner"))) {
                                                cal.add(java.util.Calendar.DAY_OF_YEAR, 7);
                                            } else {
                                                cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                                            }
                                            giftCoupon.setExpireTime(cal.getTime());
                                            
                                            giftCouponService.insertGiftCoupon(giftCoupon);
                                            savedCount++;
                                        } catch (Exception e) {
                                            logger.warn("保存礼金信息到数据库失败 - giftCouponKey={}, error={}", giftKey, e.getMessage());
                                        }
                                    }
                                }
                            }
                            logger.info("批量创建礼金 - 保存到数据库: {}/{}", savedCount, results.size());
                        }
                    } catch (Exception e) {
                        logger.error("保存礼金信息到数据库失败", e);
                    }
                }
                
                return AjaxResult.success(parsed);
            } catch (Exception e) {
                logger.warn("批量创建礼金响应 - JSON解析失败，返回字符串: {}", result);
                return AjaxResult.success(result);
            }
        } catch (Exception e) {
            logger.error("批量创建礼金异常", e);
            return AjaxResult.error("批量创建礼金失败: " + e.getMessage());
        }
    }

    /**
     * 从文案中提取u.jd链接并查询商品信息
     * 入参：{ content }
     * 返回：商品信息列表
     */
    @PostMapping("/extractUrlsAndQueryProducts")
    public AjaxResult extractUrlsAndQueryProducts(@RequestBody Map<String, Object> body) {
        try {
            String content = (String) body.get("content");
            if (content == null || content.trim().isEmpty()) {
                return AjaxResult.error("content is required");
            }

            logger.info("提取URL并查询商品 - content长度={}", content.length());

            // 提取文本中的所有u.jd链接
            java.util.List<String> urls = new java.util.ArrayList<>();
            java.util.regex.Pattern urlPattern = java.util.regex.Pattern.compile(
                "(?:https?://)?u\\.jd\\.com/[^\\s]+", 
                java.util.regex.Pattern.CASE_INSENSITIVE);
            java.util.regex.Matcher matcher = urlPattern.matcher(content);
            
            while (matcher.find()) {
                String url = matcher.group(0);
                if (url != null && !url.trim().isEmpty()) {
                    // 如果没有协议，添加https://
                    String fullUrl = url.trim();
                    if (!fullUrl.startsWith("http://") && !fullUrl.startsWith("https://")) {
                        fullUrl = "https://" + fullUrl;
                    }
                    urls.add(fullUrl);
                }
            }

            logger.info("提取URL并查询商品 - 提取到{}个u.jd链接", urls.size());

            if (urls.isEmpty()) {
                return AjaxResult.success(new JSONObject()
                    .fluentPut("products", new JSONArray())
                    .fluentPut("urls", new JSONArray())
                    .fluentPut("message", "未找到u.jd链接"));
            }

            // 去重
            java.util.Set<String> uniqueUrls = new java.util.LinkedHashSet<>(urls);
            urls = new java.util.ArrayList<>(uniqueUrls);

            // 为每个URL查询商品信息
            JSONArray products = new JSONArray();
            for (String url : urls) {
                try {
                    logger.info("查询商品信息 - URL: {}", url);
                    String queryUrl = getRequestUrl() + "generatePromotionContent";
                    JSONObject param = new JSONObject();
                    param.put("skey", skey);
                    param.put("promotionContent", url);

                    String result = HttpUtils.sendJsonPost(queryUrl, param.toJSONString());
                    logger.debug("商品查询响应: {}", result);

                    try {
                        Object parsed = JSON.parse(result);
                        if (parsed instanceof JSONArray) {
                            JSONArray arr = (JSONArray) parsed;
                            for (int i = 0; i < arr.size(); i++) {
                                JSONObject product = arr.getJSONObject(i);
                                if (product != null) {
                                    product.put("originalUrl", url); // 保存原始URL
                                    products.add(product);
                                }
                            }
                        } else if (parsed instanceof JSONObject) {
                            JSONObject obj = (JSONObject) parsed;
                            if (obj.get("list") instanceof JSONArray) {
                                JSONArray list = obj.getJSONArray("list");
                                for (int i = 0; i < list.size(); i++) {
                                    JSONObject product = list.getJSONObject(i);
                                    if (product != null) {
                                        product.put("originalUrl", url);
                                        products.add(product);
                                    }
                                }
                            } else if (obj.get("data") instanceof JSONArray) {
                                JSONArray data = obj.getJSONArray("data");
                                for (int i = 0; i < data.size(); i++) {
                                    JSONObject product = data.getJSONObject(i);
                                    if (product != null) {
                                        product.put("originalUrl", url);
                                        products.add(product);
                                    }
                                }
                            } else if (obj.containsKey("materialUrl") || obj.containsKey("skuName")) {
                                obj.put("originalUrl", url);
                                products.add(obj);
                            }
                        }
                    } catch (Exception e) {
                        logger.warn("解析商品信息失败 - URL: {}, error: {}", url, e.getMessage());
                    }
                } catch (Exception e) {
                    logger.error("查询商品信息异常 - URL: {}", url, e);
                }
            }

            logger.info("提取URL并查询商品完成 - 找到{}个商品", products.size());

            JSONObject response = new JSONObject();
            response.put("products", products);
            response.put("urls", urls);
            response.put("totalUrls", urls.size());
            response.put("totalProducts", products.size());

            return AjaxResult.success(response);
        } catch (Exception e) {
            logger.error("提取URL并查询商品异常", e);
            return AjaxResult.error("提取URL并查询商品失败: " + e.getMessage());
        }
    }

    /**
     * 文本替换：为每个URL单独查询商品并创建礼金券，然后替换
     * 入参：{ content, amount, quantity, owner }
     * 返回：替换后的文本和礼金信息
     */
    @PostMapping("/replaceUrlsWithGiftCoupons")
    public AjaxResult replaceUrlsWithGiftCoupons(@RequestBody Map<String, Object> body) {
        try {
            String content = (String) body.get("content");
            if (content == null || content.trim().isEmpty()) {
                return AjaxResult.error("content is required");
            }

            Object amountObj = body.get("amount");
            Object quantityObj = body.get("quantity");
            String owner = body.get("owner") != null ? String.valueOf(body.get("owner")) : "g";

            double amount = amountObj != null ? Double.parseDouble(String.valueOf(amountObj)) : 1.8;
            int quantity = quantityObj != null ? Integer.parseInt(String.valueOf(quantityObj)) : 12;

            logger.info("文本URL替换请求 - content长度={}, amount={}, quantity={}, owner={}", 
                content.length(), amount, quantity, owner);

            // 提取文本中的所有URL（京东链接）
            java.util.List<UrlSegment> urlSegments = new java.util.ArrayList<>();
            java.util.regex.Matcher matcher = URL_DETECT_PATTERN.matcher(content);

            while (matcher.find()) {
                String segment = matcher.group(0);
                UrlSegment urlInfo = parseUrlSegment(segment);
                if (urlInfo != null) {
                    urlSegments.add(urlInfo);
                }
            }

            logger.info("文本URL替换 - 提取到{}个URL", urlSegments.size());

            if (urlSegments.isEmpty()) {
                return AjaxResult.success(new JSONObject()
                    .fluentPut("replacedContent", content)
                    .fluentPut("originalContent", content)
                    .fluentPut("replacements", new JSONArray())
                    .fluentPut("totalUrls", 0)
                    .fluentPut("replacedCount", 0)
                    .fluentPut("message", "未找到URL，无需替换"));
            }

            // 为每个URL单独处理：查询商品 → 创建礼金 → 转链 → 替换
            String replacedContent = content;
            JSONArray replacementInfo = new JSONArray();
            int successCount = 0;

            for (int i = 0; i < urlSegments.size(); i++) {
                UrlSegment urlSegment = urlSegments.get(i);
                logger.info("处理第{}/{}个URL: {}", i + 1, urlSegments.size(), urlSegment.urlPart);

                JSONObject product = null; // 在try外部声明，以便在catch中使用
                try {
                    if (urlSegment.normalizedJdUrl == null) {
                        logger.warn("URL{}不是京东推广链接，跳过: {}", i + 1, urlSegment.original);
                        JSONObject info = new JSONObject();
                        info.put("index", i + 1);
                        info.put("originalUrl", urlSegment.urlPart);
                        info.put("newUrl", urlSegment.urlPart);
                        info.put("success", false);
                        info.put("error", "非京东推广链接或格式不支持");
                        replacementInfo.add(info);
                        continue;
                    }

                    // 1. 查询该URL的商品信息
                    String queryUrl = getRequestUrl() + "generatePromotionContent";
                    JSONObject queryParam = new JSONObject();
                    queryParam.put("skey", skey);
                    queryParam.put("promotionContent", urlSegment.normalizedJdUrl);

                    String queryResult = HttpUtils.sendJsonPost(queryUrl, queryParam.toJSONString());
                    logger.debug("商品查询响应: {}", queryResult);

                    Object parsed = JSON.parse(queryResult);

                    // 解析商品信息
                    if (parsed instanceof JSONArray) {
                        JSONArray arr = (JSONArray) parsed;
                        if (arr.size() > 0 && arr.get(0) instanceof JSONObject) {
                            product = arr.getJSONObject(0);
                        }
                    } else if (parsed instanceof JSONObject) {
                        JSONObject obj = (JSONObject) parsed;
                        if (obj.get("list") instanceof JSONArray) {
                            JSONArray list = obj.getJSONArray("list");
                            if (list.size() > 0) product = list.getJSONObject(0);
                        } else if (obj.get("data") instanceof JSONArray) {
                            JSONArray data = obj.getJSONArray("data");
                            if (data.size() > 0) product = data.getJSONObject(0);
                        } else if (obj.containsKey("materialUrl") || obj.containsKey("skuName")) {
                            product = obj;
                        }
                    }

                    if (product == null || product.containsKey("error")) {
                        String errorMsg = "商品信息查询失败";
                        if (product != null) {
                            String apiError = product.getString("error");
                            String apiMessage = product.getString("message");
                            if (apiMessage != null && !apiMessage.trim().isEmpty()) {
                                errorMsg = apiMessage;
                            } else if (apiError != null && !apiError.trim().isEmpty()) {
                                errorMsg = apiError;
                            }
                        }
                        logger.warn("URL{}商品信息查询失败: {}", urlSegment.urlPart, errorMsg);
                        JSONObject info = new JSONObject();
                        info.put("index", i + 1);
                        info.put("originalUrl", urlSegment.urlPart);
                        info.put("newUrl", urlSegment.urlPart);
                        info.put("success", false);
                        info.put("error", errorMsg);
                        replacementInfo.add(info);
                        continue;
                    }

                    // 2. 为该商品创建礼金券
                    String createUrl = getRequestUrl() + "createGiftCoupon";
                    JSONObject createParam = new JSONObject();
                    createParam.put("skey", skey);
                    createParam.put("amount", amount);
                    createParam.put("quantity", quantity);
                    createParam.put("skuName", product.getString("skuName"));

                    // 处理owner字段：p -> pop, g -> g
                    String productOwner = product.getString("owner");
                    if (productOwner == null || productOwner.trim().isEmpty()) {
                        productOwner = owner; // 使用用户选择的
                    } else if ("p".equalsIgnoreCase(productOwner)) {
                        productOwner = "pop";
                    }
                    createParam.put("owner", productOwner);

                    // 设置skuId或materialUrl（注意：POP商品优先使用materialUrl或oriItemId）
                    String skuId = product.getString("skuId");
                    String materialUrl = product.getString("materialUrl");
                    String oriItemId = product.getString("oriItemId");
                    
                    // 判断skuId是否有效（排除字符串"null"）
                    boolean hasValidSkuId = skuId != null && !skuId.trim().isEmpty() && 
                                           !"null".equalsIgnoreCase(skuId) && 
                                           !"undefined".equalsIgnoreCase(skuId);
                    
                    // 判断materialUrl是否有效
                    boolean hasValidMaterialUrl = materialUrl != null && !materialUrl.trim().isEmpty() && 
                                                 !"null".equalsIgnoreCase(materialUrl);
                    
                    // 判断oriItemId是否有效
                    boolean hasValidOriItemId = oriItemId != null && !oriItemId.trim().isEmpty() && 
                                               !"null".equalsIgnoreCase(oriItemId);
                    
                    if ("pop".equalsIgnoreCase(productOwner)) {
                        // POP商品优先使用oriItemId或materialUrl
                        if (hasValidOriItemId) {
                            createParam.put("materialUrl", oriItemId);
                            logger.info("POP商品使用oriItemId: {}", oriItemId);
                        } else if (hasValidMaterialUrl) {
                            createParam.put("materialUrl", materialUrl);
                            logger.info("POP商品使用materialUrl: {}", materialUrl);
                        } else if (hasValidSkuId) {
                            createParam.put("skuId", skuId);
                            logger.info("POP商品使用skuId: {}", skuId);
                        } else {
                            logger.warn("POP商品{}缺少有效的oriItemId/materialUrl/skuId", product.getString("skuName"));
                            JSONObject info = new JSONObject();
                            info.put("index", i + 1);
                            info.put("originalUrl", urlSegment.urlPart);
                            info.put("newUrl", urlSegment.urlPart);
                            info.put("success", false);
                            info.put("error", "POP商品信息不完整");
                            replacementInfo.add(info);
                            continue;
                        }
                    } else {
                        // 自营商品优先使用skuId
                        if (hasValidSkuId) {
                            createParam.put("skuId", skuId);
                            logger.info("自营商品使用skuId: {}", skuId);
                        } else if (hasValidMaterialUrl) {
                            createParam.put("materialUrl", materialUrl);
                            logger.info("自营商品使用materialUrl: {}", materialUrl);
                        } else {
                            logger.warn("自营商品{}缺少有效的skuId/materialUrl", product.getString("skuName"));
                            JSONObject info = new JSONObject();
                            info.put("index", i + 1);
                            info.put("originalUrl", urlSegment.urlPart);
                            info.put("newUrl", urlSegment.urlPart);
                            info.put("success", false);
                            info.put("error", "自营商品信息不完整");
                            replacementInfo.add(info);
                            continue;
                        }
                    }

                    String createResult = HttpUtils.sendJsonPost(createUrl, createParam.toJSONString());
                    logger.debug("礼金创建响应: {}", createResult);

                    JSONObject createData = JSON.parseObject(createResult);
                    if (createData == null || createData.containsKey("error") || 
                        createData.getString("giftCouponKey") == null || 
                        createData.getString("giftCouponKey").trim().isEmpty()) {
                        String errorMsg = "礼金创建失败";
                        if (createData != null) {
                            String apiError = createData.getString("error");
                            String apiMessage = createData.getString("message");
                            if (apiMessage != null && !apiMessage.trim().isEmpty()) {
                                errorMsg = apiMessage;
                            } else if (apiError != null && !apiError.trim().isEmpty()) {
                                errorMsg = apiError;
                            }
                        }
                        logger.warn("URL{}礼金创建失败: {}", urlSegment.urlPart, errorMsg);
                        JSONObject info = new JSONObject();
                        info.put("index", i + 1);
                        info.put("originalUrl", urlSegment.urlPart);
                        info.put("newUrl", urlSegment.urlPart);
                        info.put("success", false);
                        info.put("error", errorMsg);
                        if (product != null && product.getString("skuName") != null) {
                            info.put("skuName", product.getString("skuName"));
                        }
                        replacementInfo.add(info);
                        continue;
                    }

                    String giftCouponKey = createData.getString("giftCouponKey");

                    // 3. 转链（带礼金）
                    String transferUrl = getRequestUrl() + "transfer";
                    JSONObject transferParam = new JSONObject();
                    transferParam.put("skey", skey);
                    transferParam.put("materialUrl", urlSegment.normalizedJdUrl);
                    transferParam.put("giftCouponKey", giftCouponKey);

                    String transferResult = HttpUtils.sendJsonPost(transferUrl, transferParam.toJSONString());
                    logger.debug("转链响应: {}", transferResult);

                    JSONObject transferData = JSON.parseObject(transferResult);
                    if (transferData == null || transferData.containsKey("error") || 
                        transferData.getString("shortURL") == null || 
                        transferData.getString("shortURL").trim().isEmpty()) {
                        String errorMsg = "转链失败";
                        if (transferData != null) {
                            String apiError = transferData.getString("error");
                            String apiMessage = transferData.getString("message");
                            if (apiMessage != null && !apiMessage.trim().isEmpty()) {
                                errorMsg = apiMessage;
                            } else if (apiError != null && !apiError.trim().isEmpty()) {
                                errorMsg = apiError;
                            }
                        }
                        logger.warn("URL{}转链失败: {}", urlSegment.urlPart, errorMsg);
                        JSONObject info = new JSONObject();
                        info.put("index", i + 1);
                        info.put("originalUrl", urlSegment.urlPart);
                        info.put("newUrl", urlSegment.urlPart);
                        info.put("success", false);
                        info.put("giftCouponKey", giftCouponKey);
                        info.put("error", errorMsg);
                        if (product != null && product.getString("skuName") != null) {
                            info.put("skuName", product.getString("skuName"));
                        }
                        replacementInfo.add(info);
                        continue;
                    }

                    String shortURL = transferData.getString("shortURL");

                    // 4. 替换文本中的URL
                    replacedContent = replaceUrlInContent(replacedContent, urlSegment, shortURL);

                    JSONObject info = new JSONObject();
                    info.put("index", i + 1);
                    info.put("originalUrl", urlSegment.urlPart);
                    info.put("newUrl", shortURL);
                    info.put("success", true);
                    info.put("giftCouponKey", giftCouponKey);
                    info.put("skuName", product.getString("skuName"));
                    replacementInfo.add(info);

                    successCount++;
                    logger.info("URL{}处理成功: {} -> {}", i + 1, urlSegment.urlPart, shortURL);

                } catch (Exception e) {
                    logger.error("处理URL{}失败: {}", urlSegment.urlPart, e.getMessage(), e);
                    String errorMsg = e.getMessage();
                    if (errorMsg == null || errorMsg.trim().isEmpty()) {
                        errorMsg = "处理失败: " + e.getClass().getSimpleName();
                    }
                    JSONObject info = new JSONObject();
                    info.put("index", i + 1);
                    info.put("originalUrl", urlSegment.urlPart);
                    info.put("newUrl", urlSegment.urlPart);
                    info.put("success", false);
                    info.put("error", errorMsg);
                    if (product != null && product.getString("skuName") != null) {
                        info.put("skuName", product.getString("skuName"));
                    }
                    replacementInfo.add(info);
                }
            }

            logger.info("文本URL替换完成 - 成功{}/{}", successCount, urlSegments.size());

            JSONObject response = new JSONObject();
            response.put("replacedContent", replacedContent);
            response.put("originalContent", content);
            response.put("replacements", replacementInfo);
            response.put("totalUrls", urlSegments.size());
            response.put("replacedCount", successCount);

            return AjaxResult.success(response);
        } catch (Exception e) {
            logger.error("文本URL替换异常", e);
            return AjaxResult.error("文本URL替换失败: " + e.getMessage());
        }
    }

    /**
     * 手动获取物流信息（用于调试）
     * 如果订单的分销标识是F或PDD，调用外部接口获取物流信息并记录
     * 入参：{ orderId: 订单ID }
     * 返回：接口返回的数据和记录状态
     */
    @PostMapping("/fetchLogisticsManually")
    public AjaxResult fetchLogisticsManually(@RequestBody Map<String, Object> body) {
        try {
            Long orderId = null;
            if (body.get("orderId") != null) {
                if (body.get("orderId") instanceof Number) {
                    orderId = ((Number) body.get("orderId")).longValue();
                } else {
                    orderId = Long.parseLong(body.get("orderId").toString());
                }
            }
            
            if (orderId == null) {
                return AjaxResult.error("订单ID不能为空");
            }
            
            // 查询订单信息
            JDOrder order = jdOrderService.selectJDOrderById(orderId);
            if (order == null) {
                return AjaxResult.error("订单不存在");
            }
            
            // 检查分销标识
            String distributionMark = order.getDistributionMark();

            
            // 检查物流链接
            String logisticsLink = order.getLogisticsLink();
            if (logisticsLink == null || logisticsLink.trim().isEmpty()) {
                return AjaxResult.error("该订单暂无物流链接");
            }
            
            logger.info("手动获取物流信息 - 订单ID: {}, 订单号: {}, 分销标识: {}, 物流链接: {}", 
                orderId, order.getOrderId(), distributionMark, logisticsLink);
            
            String externalUrl = logisticsService.buildFetchLogisticsRequestUrl(logisticsLink);
            
            logger.info("准备调用外部接口 - URL: {}", externalUrl);
            
            // 在服务端执行HTTP请求
            String result = null;
            try {
                // 使用HttpUtils在服务端发起GET请求
                result = HttpUtils.sendGet(externalUrl);
                
                // 检查返回结果是否为空
                if (result == null || result.trim().isEmpty()) {
                    logger.warn("外部接口返回空结果 - 订单ID: {}, 订单号: {}", orderId, order.getOrderId());
                    return AjaxResult.error("外部接口返回空结果，请检查接口是否正常");
                }
                
                logger.info("外部接口调用成功 - 订单ID: {}, 订单号: {}, 返回数据长度: {}", 
                    orderId, order.getOrderId(), result.length());
                logger.debug("外部接口返回数据: {}", result);
            } catch (Exception e) {
                logger.error("调用外部接口异常 - 订单ID: {}, 订单号: {}, 错误: {}", 
                    orderId, order.getOrderId(), e.getMessage(), e);
                return AjaxResult.error("调用外部接口失败: " + e.getMessage());
            }
            
            // 记录返回数据到日志文件（方便debug）
            logger.info("========== 物流信息获取记录 ==========");
            logger.info("订单ID: {}", orderId);
            logger.info("订单号: {}", order.getOrderId());
            logger.info("分销标识: {}", distributionMark);
            logger.info("物流链接: {}", logisticsLink);
            logger.info("请求URL: {}", externalUrl);
            logger.info("返回数据: {}", result);
            logger.info("=====================================");
            
            // 解析返回结果并构建响应
            JSONObject responseData = new JSONObject();
            responseData.put("orderId", orderId);
            responseData.put("orderNo", order.getOrderId());
            responseData.put("distributionMark", distributionMark);
            responseData.put("logisticsLink", logisticsLink);
            responseData.put("requestUrl", externalUrl);
            responseData.put("responseRaw", result); // 原始返回数据
            
            JSONObject parsedData = null;
            try {
                // 尝试解析为JSON
                Object parsed = JSON.parse(result);
                if (parsed instanceof JSONObject) {
                    parsedData = (JSONObject) parsed;
                    responseData.put("responseData", parsedData);
                    logger.info("返回数据已解析为JSON对象");
                } else {
                    responseData.put("responseData", parsed);
                }
            } catch (Exception e) {
                // 如果不是JSON，只保存原始字符串
                logger.warn("返回数据不是有效的JSON格式，将作为原始字符串返回: {}", e.getMessage());
            }
            
            // 检查waybill_no，如果不为空则调用企业应用推送
            if (parsedData != null) {
                try {
                    // 检查是否有data字段
                    JSONObject dataObj = parsedData.getJSONObject("data");
                    if (dataObj != null) {
                        String waybillNo = dataObj.getString("waybill_no");
                        if (waybillNo != null && !waybillNo.trim().isEmpty()) {
                            logger.info("检测到waybill_no不为空: {}, 开始调用企业应用推送 - 订单ID: {}", waybillNo, orderId);
                            // 调用企业应用推送逻辑
                            sendEnterprisePushNotification(order, waybillNo, parsedData);
                            responseData.put("pushSent", true);
                            logger.info("企业应用推送已发送 - 订单ID: {}, waybill_no: {}", orderId, waybillNo);
                        } else {
                            logger.info("waybill_no为空，无需推送 - 订单ID: {}", orderId);
                            responseData.put("pushSent", false);
                        }
                    }
                } catch (Exception e) {
                    logger.error("检查waybill_no或推送时发生异常 - 订单ID: {}", orderId, e);
                    responseData.put("pushSent", false);
                    responseData.put("pushError", e.getMessage());
                }
            }
            
            logger.info("返回响应数据给前端 - 订单ID: {}", orderId);
            return AjaxResult.success(responseData);
        } catch (Exception e) {
            logger.error("手动获取物流信息异常", e);
            return AjaxResult.error("获取物流信息失败: " + e.getMessage());
        }
    }

    /**
     * 根据分销标识获取接收人列表
     * 从系统配置中读取，配置键名格式：logistics.push.touser.{分销标识}
     * 配置值格式：接收人1,接收人2,接收人3（逗号分隔）
     * 
     * @param distributionMark 分销标识
     * @return 接收人列表（逗号分隔），如果未配置则返回null
     */
    private String getTouserByDistributionMark(String distributionMark) {
        if (!StringUtils.hasText(distributionMark)) {
            logger.warn("分销标识为空，无法获取接收人配置");
            return null;
        }
        
        try {
            String trimmed = distributionMark.trim();
            String configKey = CONFIG_KEY_PREFIX + trimmed;
            String configValue = sysConfigService.selectConfigByKey(configKey);
            
            if (StringUtils.hasText(configValue)) {
                String touser = configValue.trim().replaceAll(",\\s+", ",");
                logger.info("从配置获取接收人列表 - 分销标识: {}, 配置键: {}, 接收人: {}", 
                    distributionMark, configKey, touser);
                return touser;
            }
            if (trimmed.startsWith("F-") || "F".equals(trimmed)) {
                if (!trimmed.equals("F")) {
                    String fallbackKey = CONFIG_KEY_PREFIX + "F";
                    String fallbackVal = sysConfigService.selectConfigByKey(fallbackKey);
                    if (StringUtils.hasText(fallbackVal)) {
                        String touser = fallbackVal.trim().replaceAll(",\\s+", ",");
                        logger.info("从配置获取接收人列表（F 系回退） - 分销标识: {}, 配置键: {}, 接收人: {}",
                            distributionMark, fallbackKey, touser);
                        return touser;
                    }
                }
            }
            logger.debug("未找到接收人配置 - 分销标识: {}, 配置键: {}", distributionMark, configKey);
            return null;
        } catch (Exception e) {
            logger.error("获取接收人配置失败 - 分销标识: {}, 错误: {}", distributionMark, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 调用企业应用推送逻辑
     * @param order 订单信息
     * @param waybillNo 运单号
     * @param logisticsData 物流数据
     */
    private void sendEnterprisePushNotification(JDOrder order, String waybillNo, JSONObject logisticsData) {
        try {
            // 构建推送消息内容
            StringBuilder pushContent = new StringBuilder();
            
            // 第一行：分销标识（F或PDD）
            String distributionMark = order.getDistributionMark() != null ? order.getDistributionMark() : "未知";
            pushContent.append(distributionMark).append("\n");
            
            // PDD订单包含第三方单号，F订单不包含
            if ("PDD".equals(distributionMark)) {
                String thirdPartyOrderNo = order.getThirdPartyOrderNo();
                if (thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty()) {
                    pushContent.append("第三方单号：").append(thirdPartyOrderNo).append("\n");
                }
            }
            
            // 型号
            pushContent.append("型号：").append(order.getModelNumber() != null ? order.getModelNumber() : "无").append("\n");
            // 收货地址
            pushContent.append("收货地址：").append(order.getAddress() != null ? order.getAddress() : "无").append("\n");
            // 运单号
            pushContent.append("运单号：").append("\n").append("\n").append("\n").append("\n").append(waybillNo).append("\n");
            
            // 调用企业微信推送接口（参考WxtsUtil的实现）
            String pushUrl = "https://wxts.van333.cn/wx/send/pdd";
            String token = "super_token_b62190c26"; // 与WxtsUtil中的TOKEN保持一致
            JSONObject pushParam = new JSONObject();
            pushParam.put("title", "JD物流信息推送");
            String content = pushContent.toString();
            pushParam.put("text", content);
            
            // 根据分销标识获取接收人列表
            String touser = getTouserByDistributionMark(distributionMark);
            if (StringUtils.hasText(touser)) {
                pushParam.put("touser", touser);
                logger.info("企业微信推送设置接收人 - 订单ID: {}, 分销标识: {}, 接收人: {}", 
                    order.getId(), distributionMark, touser);
            } else {
                logger.warn("未找到分销标识对应的接收人配置 - 订单ID: {}, 分销标识: {}", 
                    order.getId(), distributionMark);
            }
            
            // 记录完整的推送参数（用于调试）
            String jsonBody = pushParam.toJSONString();
            logger.info("企业微信推送完整参数 - 订单ID: {}, JSON: {}", order.getId(), jsonBody);
            
            // 使用支持自定义header的HTTP请求
            String pushResult = sendPostWithHeaders(pushUrl, jsonBody, token);
            logger.info("企业应用推送调用结果 - 订单ID: {}, waybill_no: {}, 推送结果: {}", 
                order.getId(), waybillNo, pushResult);
            
        } catch (Exception e) {
            logger.error("调用企业应用推送失败 - 订单ID: {}, waybill_no: {}, 错误: {}", 
                order.getId(), waybillNo, e.getMessage(), e);
            // 不抛出异常，避免影响主流程
        }
    }

    /**
     * 发送POST请求，支持自定义header（用于企业微信推送）
     * @param url 请求URL
     * @param jsonBody JSON请求体
     * @param token 认证token
     * @return 响应结果
     */
    private String sendPostWithHeaders(String url, String jsonBody, String token) {
        java.io.BufferedReader in = null;
        java.io.PrintWriter out = null;
        StringBuilder result = new StringBuilder();
        try {
            java.net.URL realUrl = new java.net.URL(url);
            java.net.URLConnection conn = realUrl.openConnection();
            
            // 设置请求头
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("vanToken", token);
            conn.setRequestProperty("source", "XZJ_UBUNTU");
            
            conn.setDoOutput(true);
            conn.setDoInput(true);
            
            // 发送请求体
            out = new java.io.PrintWriter(conn.getOutputStream());
            out.print(jsonBody);
            out.flush();
            
            // 读取响应
            in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(), java.nio.charset.StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            
            logger.info("企业微信推送请求成功 - URL: {}, 响应: {}", url, result.toString());
        } catch (java.net.ConnectException e) {
            logger.error("企业微信推送连接失败 - URL: {}", url, e);
            throw new RuntimeException("推送连接失败: " + e.getMessage(), e);
        } catch (java.net.SocketTimeoutException e) {
            logger.error("企业微信推送超时 - URL: {}", url, e);
            throw new RuntimeException("推送请求超时: " + e.getMessage(), e);
        } catch (java.io.IOException e) {
            logger.error("企业微信推送IO异常 - URL: {}", url, e);
            throw new RuntimeException("推送IO异常: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("企业微信推送异常 - URL: {}", url, e);
            throw new RuntimeException("推送异常: " + e.getMessage(), e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (java.io.IOException ex) {
                logger.error("关闭流异常", ex);
            }
        }
        return result.toString();
    }

    private static class UrlSegment {
        private final String original;
        private final String urlPart;
        private final String suffix;
        private final String normalizedJdUrl;

        private UrlSegment(String original, String urlPart, String suffix, String normalizedJdUrl) {
            this.original = original;
            this.urlPart = urlPart;
            this.suffix = suffix;
            this.normalizedJdUrl = normalizedJdUrl;
        }
    }

    private static UrlSegment parseUrlSegment(String segment) {
        if (segment == null || segment.trim().isEmpty()) {
            return null;
        }
        String original = segment.trim();
        int urlLength = calculateUrlLength(original);
        if (urlLength <= 0) {
            return null;
        }
        String urlPart = original.substring(0, urlLength);
        String suffix = original.substring(urlLength);
        String normalized = normalizeJdUrl(urlPart);
        return new UrlSegment(original, urlPart, suffix, normalized);
    }

    private static int calculateUrlLength(String text) {
        int length = 0;
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (isAllowedUrlChar(c)) {
                length++;
            } else {
                break;
            }
        }
        return length;
    }

    private static boolean isAllowedUrlChar(char c) {
        if (c <= 0x7F) {
            return Character.isLetterOrDigit(c) || "-._~:/?#[]@!$&'()*+,;=%".indexOf(c) >= 0;
        }
        return false;
    }

    private static String normalizeJdUrl(String urlPart) {
        if (urlPart == null || urlPart.isEmpty()) {
            return null;
        }
        String normalized = urlPart;
        if (!normalized.startsWith("http://") && !normalized.startsWith("https://")) {
            normalized = "https://" + normalized;
        }
        if (UJD_LINK_PATTERN.matcher(normalized).matches() || JINGFEN_LINK_PATTERN.matcher(normalized).matches()) {
            return normalized;
        }
        return null;
    }

    private static String replaceUrlInContent(String content, UrlSegment segment, String newUrl) {
        if (content == null || segment == null || newUrl == null || newUrl.trim().isEmpty()) {
            return content;
        }
        String suffix = segment.suffix != null ? segment.suffix : "";
        String replacementWithSuffix = newUrl + suffix;
        String result = content.replace(segment.original, replacementWithSuffix);
        if (result.equals(content) && !segment.original.equals(segment.urlPart)) {
            result = result.replace(segment.urlPart, newUrl);
        }
        return result;
    }
}
