package com.payment.sdk;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;

/**
 * USDT支付网关 Java SDK
 *
 * @version 2.0.0
 * @author USDT Payment Team
 *
 * 接口说明:
 * - /api/address/create  动态生成收款地址
 * - /api/pay/create      创建支付订单
 * - /api/pay/query       查询订单状态
 */
public class UsdtPaySDK {

    private final String baseUrl;
    private final String merchantNo;
    private final String apiKey;
    private final String apiSecret;

    public UsdtPaySDK(String baseUrl, String merchantNo, String apiKey, String apiSecret) {
        this.baseUrl = baseUrl.replaceAll("/$", "");
        this.merchantNo = merchantNo;
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
    }

    /**
     * 动态生成收款地址
     *
     * @param label 地址别名（可选，传null忽略）
     * @return 响应结果JSON字符串
     */
    public String createAddress(String label) throws Exception {
        long timestamp = System.currentTimeMillis();

        Map<String, Object> params = new LinkedHashMap<>();
        params.put("merchantNo", merchantNo);
        params.put("timestamp", timestamp);
        if (label != null && !label.isEmpty()) {
            params.put("label", label);
        }

        String sign = generateSign(params);
        params.put("sign", sign);

        return request("/api/address/create", toJson(params));
    }

    /**
     * 创建支付订单
     *
     * @param payAddress         收款地址
     * @param productName        商品名称
     * @param productDescription 商品描述（可选）
     * @return 响应结果JSON字符串
     */
    public String createOrder(String payAddress, String productName, String productDescription) throws Exception {
        long timestamp = System.currentTimeMillis();

        Map<String, Object> params = new LinkedHashMap<>();
        params.put("merchantNo", merchantNo);
        params.put("payAddress", payAddress);
        params.put("productName", productName);
        params.put("timestamp", timestamp);
        if (productDescription != null && !productDescription.isEmpty()) {
            params.put("productDescription", productDescription);
        }

        String sign = generateSign(params);
        params.put("sign", sign);

        return request("/api/pay/create", toJson(params));
    }

    /**
     * 查询订单状态
     *
     * @param orderNo 订单号
     * @return 响应结果JSON字符串
     */
    public String queryOrder(String orderNo) throws Exception {
        long timestamp = System.currentTimeMillis();

        Map<String, Object> params = new LinkedHashMap<>();
        params.put("merchantNo", merchantNo);
        params.put("orderNo", orderNo);
        params.put("timestamp", timestamp);

        String sign = generateSign(params);
        params.put("sign", sign);

        return request("/api/pay/query", toJson(params));
    }

    /**
     * 验证回调签名
     *
     * @param data 回调数据Map
     * @return 验证是否通过
     */
    public boolean verifyCallback(Map<String, Object> data) {
        try {
            if (!data.containsKey("sign")) {
                return false;
            }

            String sign = (String) data.get("sign");
            Map<String, Object> signData = new LinkedHashMap<>(data);
            signData.remove("sign");

            String expectedSign = generateSign(signData);

            return sign.equalsIgnoreCase(expectedSign);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 生成签名
     * 签名算法: SHA256(参数按键名排序拼接 + key=apiSecret)
     * 拼接格式: key1=value1&key2=value2&...&key=apiSecret
     */
    private String generateSign(Map<String, Object> params) throws Exception {
        // 按键名排序
        java.util.TreeMap<String, Object> sortedParams = new java.util.TreeMap<>(params);
        
        // 拼接参数
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().toString().isEmpty()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        // 追加密钥
        sb.append("key=").append(apiSecret);
        
        return sha256Hex(sb.toString());
    }

    private String sha256Hex(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * 简单Map转JSON
     */
    private String toJson(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder("{");
        boolean first = true;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (!first) sb.append(",");
            first = false;
            sb.append("\"").append(entry.getKey()).append("\":");
            Object value = entry.getValue();
            if (value instanceof String) {
                sb.append("\"").append(escapeJson((String) value)).append("\"");
            } else {
                sb.append(value);
            }
        }
        sb.append("}");
        return sb.toString();
    }

    private String escapeJson(String str) {
        return str.replace("\\", "\\\\")
                  .replace("\"", "\\\"")
                  .replace("\n", "\\n")
                  .replace("\r", "\\r")
                  .replace("\t", "\\t");
    }

    /**
     * 发送HTTP请求
     */
    private String request(String path, String jsonBody) throws Exception {
        URL url = new URL(baseUrl + path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("X-API-KEY", apiKey);
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        conn.setDoOutput(true);

        try (OutputStream os = conn.getOutputStream()) {
            os.write(jsonBody.getBytes(StandardCharsets.UTF_8));
        }

        int responseCode = conn.getResponseCode();
        InputStream is = (responseCode >= 200 && responseCode < 300)
                ? conn.getInputStream()
                : conn.getErrorStream();

        StringBuilder response = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
        }

        return response.toString();
    }

    // ==================== 使用示例 ====================
    public static void main(String[] args) {
        try {
            // 初始化SDK
            UsdtPaySDK sdk = new UsdtPaySDK(
                    "https://zhifu.markexia.icu",
                    "M2032545595611709440",  // 商户编号
                    "AK_xxxxxxxx",            // API Key
                    "AS_xxxxxxxx"             // API Secret
            );

            // 1. 动态生成收款地址
            String result = sdk.createAddress("用户充值-订单123");
            System.out.println("生成地址结果: " + result);
            // 从返回结果中解析address...

            // 2. 创建支付订单
            result = sdk.createOrder(
                    "T9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",  // 收款地址
                    "购买VIP会员",
                    "购买1个月VIP会员服务"
            );
            System.out.println("创建订单结果: " + result);

            // 3. 查询订单状态
            result = sdk.queryOrder("P2032545595611709440");
            System.out.println("查询订单结果: " + result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/*
===================== 完整对接流程 =====================

1. 从商户后台获取凭证：
   - 商户编号 (merchantNo)
   - API Key
   - API Secret

2. 用户发起支付时：
   a) 调用 createAddress() 动态生成收款地址
   b) 调用 createOrder() 创建支付订单
   c) 展示收款地址给用户进行转账

3. 用户转账后：
   - 系统自动检测链上交易
   - 支付成功后回调您的通知地址

4. 验证回调签名，更新订单状态

=====================================================

注意: 实际项目建议使用Gson或Jackson处理JSON
*/
