package com.kingdee.eas.custom.weaverTodo.client;

import org.apache.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * EAS server-side HTTP helper (no OkHttp / Spring RestTemplate dependency).
 */
public final class WeaverHttpHelper {
    private static final Logger logger = Logger.getLogger(WeaverHttpHelper.class);
    private static final int LOG_BODY_MAX = 800;

    private WeaverHttpHelper() {
    }

    public static String get(String url, int connectTimeoutMs, int readTimeoutMs) throws Exception {
        Map<String, String> headers = defaultJsonHeaders();
        return request("GET", url, null, null, headers, connectTimeoutMs, readTimeoutMs);
    }

    public static String postForm(String url, Map<String, String> form,
                                  int connectTimeoutMs, int readTimeoutMs) throws Exception {
        StringBuilder sb = new StringBuilder();
        if (form != null) {
            for (Map.Entry<String, String> e : form.entrySet()) {
                if (sb.length() > 0) {
                    sb.append('&');
                }
                sb.append(encode(e.getKey())).append('=').append(encode(e.getValue()));
            }
        }
        Map<String, String> headers = defaultJsonHeaders();
        return request("POST", url, sb.toString(), "application/x-www-form-urlencoded;charset=UTF-8",
                headers, connectTimeoutMs, readTimeoutMs);
    }

    public static String postJson(String url, String json,
                                  int connectTimeoutMs, int readTimeoutMs) throws Exception {
        Map<String, String> headers = defaultJsonHeaders();
        return request("POST", url, json, "application/json;charset=UTF-8",
                headers, connectTimeoutMs, readTimeoutMs);
    }

    private static Map<String, String> defaultJsonHeaders() {
        Map<String, String> headers = new LinkedHashMap<String, String>();
        // 要求开放平台返回 JSON，减少被门户 HTML 路由劫持后难排查
        headers.put("Accept", "application/json");
        return headers;
    }

    private static String request(String method, String url, String body, String contentType,
                                  Map<String, String> headers,
                                  int connectTimeoutMs, int readTimeoutMs) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod(method);
        conn.setConnectTimeout(connectTimeoutMs);
        conn.setReadTimeout(readTimeoutMs);
        conn.setInstanceFollowRedirects(false);
        conn.setDoInput(true);
        if (headers != null) {
            for (Map.Entry<String, String> h : headers.entrySet()) {
                conn.setRequestProperty(h.getKey(), h.getValue());
            }
        }
        if (body != null) {
            conn.setDoOutput(true);
            if (contentType != null) {
                conn.setRequestProperty("Content-Type", contentType);
            }
            byte[] bytes = body.getBytes(StandardCharsets.UTF_8);
            conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
            OutputStream os = conn.getOutputStream();
            try {
                os.write(bytes);
                os.flush();
            } finally {
                os.close();
            }
        }
        int code = conn.getResponseCode();
        String contentTypeResp = conn.getContentType();
        String location = conn.getHeaderField("Location");
        InputStream in = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
        String resp = readFully(in);
        logger.info("HTTP " + method + " url=" + url
                + " -> status=" + code
                + " contentType=" + contentTypeResp
                + " location=" + location
                + " bodyLen=" + (resp == null ? 0 : resp.length())
                + " bodySnippet=" + snippet(resp));
        if (code >= 300 && code < 400) {
            throw new IllegalStateException("OpenAPI HTTP 重定向 status=" + code
                    + " location=" + location
                    + "，多半不是 OPENAPI 网关地址。bodySnippet=" + snippet(resp));
        }
        if (code < 200 || code >= 300) {
            throw new IllegalStateException("HTTP " + code + " contentType=" + contentTypeResp
                    + " bodySnippet=" + snippet(resp));
        }
        return resp == null ? "" : resp;
    }

    static String snippet(String body) {
        if (body == null) {
            return "";
        }
        String s = body.replace('\r', ' ').replace('\n', ' ').trim();
        if (s.length() <= LOG_BODY_MAX) {
            return s;
        }
        return s.substring(0, LOG_BODY_MAX) + "...(truncated)";
    }

    static boolean looksLikeHtml(String body) {
        if (body == null) {
            return false;
        }
        String s = body.trim();
        if (s.length() == 0) {
            return false;
        }
        String lower = s.length() > 64 ? s.substring(0, 64).toLowerCase() : s.toLowerCase();
        return lower.startsWith("<!doctype") || lower.startsWith("<html") || lower.contains("<html");
    }

    private static String readFully(InputStream in) throws Exception {
        if (in == null) {
            return "";
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[4096];
        int n;
        while ((n = in.read(buf)) >= 0) {
            bos.write(buf, 0, n);
        }
        in.close();
        return new String(bos.toByteArray(), StandardCharsets.UTF_8);
    }

    private static String encode(String s) throws Exception {
        return java.net.URLEncoder.encode(s == null ? "" : s, "UTF-8");
    }
}
