package com.ruoyi.jarvis.wecom;

import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 调用 wxSend 的企微应用文本主动推送（POST /wecom/active-push）。
 */
@Component
public class WxSendWeComPushClient {

    private static final Logger log = LoggerFactory.getLogger(WxSendWeComPushClient.class);

    public static final String HEADER_PUSH_SECRET = "X-WxSend-WeCom-Push-Secret";

    @Value("${jarvis.wecom.wxsend-base-url:}")
    private String wxsendBaseUrl;

    @Value("${jarvis.wecom.push-secret:}")
    private String pushSecret;

    /**
     * 在被动回复返回后延迟再发，保证企微侧先出现首条被动消息。
     */
    public void scheduleActivePushes(String toUser, List<String> contents) {
        if (!StringUtils.hasText(wxsendBaseUrl) || !StringUtils.hasText(pushSecret)
                || !StringUtils.hasText(toUser) || contents == null || contents.isEmpty()) {
            return;
        }
        final String userId = toUser.trim();
        final List<String> list = new ArrayList<>(contents);
        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(450);
                String base = normalizeBase(wxsendBaseUrl);
                String url = base + "/wecom/active-push";
                for (String c : list) {
                    if (!StringUtils.hasText(c)) {
                        continue;
                    }
                    postJson(url, userId, c.trim());
                    Thread.sleep(120);
                }
            } catch (Exception e) {
                log.warn("企微主动推送任务异常 userId={} msg={}", userId, e.toString());
            }
        });
    }

    private static String normalizeBase(String base) {
        String b = base.trim();
        if (b.endsWith("/")) {
            return b.substring(0, b.length() - 1);
        }
        return b;
    }

    private void postJson(String url, String toUser, String content) {
        JSONObject body = new JSONObject();
        body.put("toUser", toUser);
        body.put("content", content);
        byte[] bytes = body.toJSONString().getBytes(StandardCharsets.UTF_8);
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("POST");
            conn.setConnectTimeout(15000);
            conn.setReadTimeout(60000);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            conn.setRequestProperty(HEADER_PUSH_SECRET, pushSecret);
            try (OutputStream os = conn.getOutputStream()) {
                os.write(bytes);
            }
            int code = conn.getResponseCode();
            InputStream is = code >= 200 && code < 300 ? conn.getInputStream() : conn.getErrorStream();
            String resp = readAll(is);
            if (code < 200 || code >= 300) {
                log.warn("wxSend active-push HTTP {} body={}", code, resp);
            } else {
                log.debug("wxSend active-push OK http={} resp={}", code, resp);
            }
        } catch (Exception e) {
            log.warn("wxSend active-push 请求失败 url={} err={}", url, e.toString());
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    private static String readAll(InputStream is) throws java.io.IOException {
        if (is == null) {
            return "";
        }
        byte[] buf = new byte[4096];
        StringBuilder sb = new StringBuilder();
        int n;
        while ((n = is.read(buf)) >= 0) {
            sb.append(new String(buf, 0, n, StandardCharsets.UTF_8));
        }
        return sb.toString();
    }
}
