package com.table.transfer.util;

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.table.transfer.module.enpty.TransactionInfoDTO;
import com.table.transfer.util.tron.TronHexAndBase58Util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

/**
 * TRONGrid 查询工具类
 * 封装独立查询功能，避免使用有问题的一次性接口
 */
public class TronGridQueryUtil {

    private static final String TRONGRID_BASE_URL = "https://api.trongrid.io";
    private static String apiKey = "8c5536e3-a852-43f6-add4-55421317f61c"; // 可选：设置你的 TRONGrid API Key
    private static final String QUICKNODE_URL = "https://quaint-wild-layer.tron-mainnet.quiknode.pro/7d1ea336b14b5f53d8c897fe012aceec97a55fd7/";

    /**
     * 设置 TRONGrid API Key（可选）
     */
    public static void setApiKey(String key) {
        apiKey = key;
    }

    public static void main(String[] args) {
        String usdtContract = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
        String address = "TDTAYsJDnUNCHJgPWLbyE1GutRJ5KBh1Bd";
//        String address = "TDFtN7nyfweR8WeUraZM7WuCrtUTruD4Er";
        System.out.println(getTRXBalance(address));
        System.out.println(getTokenBalance(address, usdtContract,6));
//
//        System.out.println(JSONUtil.toJsonStr(getTransactionStatus("a8cd72046d1f6f60a86366cc006c7106037f7188a9bad5aca813389bf0cfec75")));

    }

    /**
     * 1. 通过地址查询主币余额（TRX）
     *
     * @param address TRON地址
     * @return TRX余额（单位：TRX）
     */
    public static BigDecimal getTRXBalance(String address) {
        String url = TRONGRID_BASE_URL + "/wallet/getaccount";

        JSONObject params = new JSONObject();
        params.put("address", address);
        params.put("visible", true);

        try {
            String response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .timeout(10000)
                    .body(params.toString())
                    .execute()
                    .body();

            JSONObject jsonResponse = JSONUtil.parseObj(response);

            if (jsonResponse.containsKey("balance")) {
                long balanceSun = jsonResponse.getLong("balance");
                // 转换为 TRX: 1 TRX = 1,000,000 SUN
                return BigDecimal.valueOf(balanceSun)
                        .divide(BigDecimal.valueOf(1_000_000L), 6, BigDecimal.ROUND_DOWN);
            } else {
                // 账户不存在或没有余额
                return BigDecimal.ZERO;
            }

        } catch (Exception e) {
            throw new RuntimeException("查询TRX余额失败: " + e.getMessage(), e);
        }
    }



    /**
     * 查询可读代币余额
     * @param targetAddress 目标地址
     * @param contractAddress 合约地址
     * @param decimals 代币精度
     * @return 转换后的金额
     */
    public static BigDecimal getTokenBalance(String targetAddress, String contractAddress, int decimals) {
        BigInteger balanceWei = getTokenBalanceWei(targetAddress, contractAddress);
        BigDecimal divisor = BigDecimal.TEN.pow(decimals);
        return new BigDecimal(balanceWei).divide(divisor, decimals, RoundingMode.DOWN);
    }

    /**
     * 通过地址和合约查询代币余额
     * @param ownerAddress    持有者地址
     * @param contractAddress 代币合约地址
     * @return 未转换的代币余额(wei)
     */
    public static BigInteger getTokenBalanceWei(String ownerAddress, String contractAddress) {
        String url = TRONGRID_BASE_URL + "/wallet/triggerconstantcontract";

        // 编码地址参数
        String parameter = TronHexAndBase58Util.base58ToHex(ownerAddress);

        JSONObject params = new JSONObject();
        params.set("owner_address", ownerAddress);
        params.set("contract_address", contractAddress);
        params.set("function_selector", "balanceOf(address)");
        params.set("parameter", parameter);
        params.set("visible", true);

        try {
            String response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .timeout(10000)
                    .body(params.toString())
                    .execute()
                    .body();

            JSONObject jsonResponse = JSONUtil.parseObj(response);

            if (jsonResponse.containsKey("constant_result")) {
                String hexBalance = jsonResponse.getJSONArray("constant_result").getStr(0);
                if (hexBalance != null && !hexBalance.isEmpty()) {
                    try {
                        return new BigInteger(hexBalance,16);//解析16进制
                    } catch (NumberFormatException e) {
                        throw new RuntimeException("解析代币余额失败: " + hexBalance, e);
                    }
                }
            }
            return BigInteger.ZERO;

        } catch (Exception e) {
            throw new RuntimeException("查询代币余额失败: " + e.getMessage(), e);
        }
    }




    /**
     * 通过交易哈希查询交易状态（基于实际的事件日志数据）
     */
    public static TransactionInfoDTO getTransactionStatus(String txHash) {
        // 获取交易收据（包含事件日志）
        JSONObject txReceipt = getTransactionReceipt(txHash);

        TransactionInfoDTO dto = new TransactionInfoDTO();

        // 基础信息
        dto.setHash(txHash);
        dto.setBlockNumber(txReceipt.getLong("blockNumber"));
        dto.setTimestamp(txReceipt.getLong("blockTimeStamp"));

        // 交易状态
        String result = txReceipt.getJSONObject("receipt").getStr("result");
        dto.setStatus("SUCCESS".equals(result) ? "success" : "failed");

        // 手续费信息
        long feeSun = txReceipt.getLong("fee", 0L);
        dto.setGasFee(BigDecimal.valueOf(feeSun).divide(BigDecimal.valueOf(1_000_000L), 6, RoundingMode.DOWN));

        // 解析事件日志
        JSONArray logs = txReceipt.getJSONArray("log");
        if (!logs.isEmpty()) {
            JSONObject log = logs.getJSONObject(0);
            JSONArray topics = log.getJSONArray("topics");
            String data = log.getStr("data");

            // 解析 Transfer 事件
            if (topics.size() >= 3) {
                // 解析 from 地址（topics[1]）
                String fromHex = topics.getStr(1).substring(24); // 取后40个字符
                dto.setFromAddress(TronHexAndBase58Util.hexToBase58(fromHex));

                // 解析 to 地址（topics[2]）
                String toHex = topics.getStr(2).substring(24); // 取后40个字符
                dto.setToAddress(TronHexAndBase58Util.hexToBase58(toHex));

                // 解析金额（data 字段）
                if (data != null && !data.isEmpty()) {
                    BigInteger valueWei = new BigInteger(data.substring(24), 16); // 取后64个字符

                    // 代币信息
                    String contractAddress = txReceipt.getStr("contract_address");
                    dto.setContractAddress(contractAddress);


                    // todo 根据合约地址确定代币符号和精度
                    dto.setDecimals(6);
                    // 金额处理
                    BigDecimal amount = new BigDecimal(valueWei).divide(BigDecimal.TEN.pow(dto.getDecimals()), dto.getDecimals(), RoundingMode.DOWN);
                    dto.setAmount(amount);
                }
            }
        }

        return dto;
    }

    /**
     * 查询交易事件
     */
    private static JSONObject getTransactionEvents(String txHash) {
        String url = TRONGRID_BASE_URL + "/v1/transactions/" + txHash + "/events";

        try {
            String response = HttpRequest.get(url)
                    .header("accept", "application/json")
                    .timeout(10000)
                    .execute()
                    .body();

            return JSONUtil.parseObj(response);

        } catch (Exception e) {
            throw new RuntimeException("查询交易事件失败: " + e.getMessage(), e);
        }
    }
    /**
     * 3.1 查询交易基本信息
     */
    private static JSONObject getTransactionInfo(String txHash) {
        String url = TRONGRID_BASE_URL + "/wallet/gettransactionbyid";

        JSONObject params = new JSONObject();
        params.put("value", txHash);
        params.put("visible", true);

        try {
            String response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .timeout(10000)
                    .body(params.toString())
                    .execute()
                    .body();

            return JSONUtil.parseObj(response);

        } catch (Exception e) {
            throw new RuntimeException("查询交易信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 3.2 查询交易收据（包含执行结果）
     */
    private static JSONObject getTransactionReceipt(String txHash) {
        String url = TRONGRID_BASE_URL + "/wallet/gettransactioninfobyid";

        JSONObject params = new JSONObject();
        params.set("value", txHash);
        params.set("visible", true);

        try {
            String response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .timeout(10000)
                    .body(params.toString())
                    .execute()
                    .body();

            return JSONUtil.parseObj(response);

        } catch (Exception e) {
            // 交易收据可能不存在，返回空对象
            return new JSONObject();
        }
    }

//    /**
//     * 3.3 分析交易状态
//     */
//    private static JSONObject analyzeTransactionStatus(JSONObject txInfo, JSONObject txReceipt) {
//        JSONObject status = new JSONObject();
//        status.set("tx_hash", txInfo.getStr("txID"));
//
//        // 判断交易是否确认
//        if (txInfo.containsKey("ret")) {
//            JSONArray retArray = txInfo.getJSONArray("ret");
//            if (retArray.size() > 0) {
//                JSONObject ret = retArray.getJSONObject(0);
//                String retCode = ret.getStr("ret");
//                status.set("confirmed", !"FAILED".equals(retCode));
//                status.set("ret_code", retCode);
//            }
//        }
//
//        // 检查交易收据（更详细的状态）
//        if (!txReceipt.isEmpty() && txReceipt.containsKey("result")) {
//            String result = txReceipt.getStr("result");
//            status.set("execution_result", result);
//            status.set("success", "SUCCESS".equals(result));
//
//            // 能量消耗
//            if (txReceipt.containsKey("energy_usage")) {
//                status.set("energy_used", txReceipt.getLong("energy_usage"));
//            }
//            if (txReceipt.containsKey("energy_penalty")) {
//                status.set("energy_penalty", txReceipt.getLong("energy_penalty"));
//            }
//
//            // 合约结果（代币交易）
//            if (txReceipt.containsKey("contract_result")) {
//                status.set("contract_result", txReceipt.getJSONArray("contract_result"));
//            }
//        }
//
//        // 交易基本信息
//        if (txInfo.containsKey("raw_data")) {
//            JSONObject rawData = txInfo.getJSONObject("raw_data");
//            status.set("timestamp", rawData.getLong("timestamp"));
//            status.set("expiration", rawData.getLong("expiration"));
//
//            // 交易类型
//            if (rawData.containsKey("contract")) {
//                JSONArray contracts = rawData.getJSONArray("contract");
//                if (contracts.size() > 0) {
//                    JSONObject contract = contracts.getJSONObject(0);
//                    status.set("contract_type", contract.getStr("type"));
//                }
//            }
//        }
//
//        return status;
//    }

    /**
     * 4. 通过地址查询账户能量余额
     *
     * @param address TRON地址
     * @return 能量信息
     */
    public static JSONObject getAccountEnergy(String address) {
        String url = TRONGRID_BASE_URL + "/wallet/getaccountresource";

        JSONObject params = new JSONObject();
        params.put("address", address);
        params.put("visible", true);

        try {
            String response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .timeout(10000)
                    .body(params.toString())
                    .execute()
                    .body();

            JSONObject resourceData = JSONUtil.parseObj(response);
            return parseEnergyInfo(address, resourceData);

        } catch (Exception e) {
            throw new RuntimeException("查询账户能量失败: " + e.getMessage(), e);
        }
    }

    /**
     * 4.1 解析能量信息
     */
    private static JSONObject parseEnergyInfo(String address, JSONObject resourceData) {
        JSONObject energyInfo = new JSONObject();
        energyInfo.set("address", address);

        // 能量信息
        if (resourceData.containsKey("EnergyUsed")) {
            energyInfo.set("energy_used", resourceData.getLong("EnergyUsed"));
        }
        if (resourceData.containsKey("EnergyLimit")) {
            energyInfo.set("energy_limit", resourceData.getLong("EnergyLimit"));
        }

        // 计算剩余能量
        long energyUsed = resourceData.getLong("EnergyUsed", 0L);
        long energyLimit = resourceData.getLong("EnergyLimit", 0L);
        long energyRemaining = Math.max(0, energyLimit - energyUsed);
        energyInfo.set("energy_remaining", energyRemaining);

        // 带宽信息
        if (resourceData.containsKey("free_net_used")) {
            energyInfo.set("free_bandwidth_used", resourceData.getLong("free_net_used"));
        }
        if (resourceData.containsKey("free_net_limit")) {
            energyInfo.set("free_bandwidth_limit", resourceData.getLong("free_net_limit"));
        }

        // 计算剩余带宽
        long bandwidthUsed = resourceData.getLong("free_net_used", 0L);
        long bandwidthLimit = resourceData.getLong("free_net_limit", 0L);
        long bandwidthRemaining = Math.max(0, bandwidthLimit - bandwidthUsed);
        energyInfo.set("free_bandwidth_remaining", bandwidthRemaining);

        return energyInfo;
    }

    // ========== 工具方法 ==========


//
//    /**
//     * 解析代币余额
//     */
//    private static BigDecimal parseTokenBalance(JSONObject response, int decimals) {
//        if (response.containsKey("constant_result")) {
//            String hexBalance = response.getJSONArray("constant_result").getStr(0);
//            if (hexBalance != null && !hexBalance.isEmpty()) {
//                try {
//                    BigInteger balanceWei = new BigInteger(hexBalance, 16);
//                    BigDecimal divisor = BigDecimal.TEN.pow(decimals);
//                    return new BigDecimal(balanceWei).divide(divisor, decimals, BigDecimal.ROUND_DOWN);
//                } catch (NumberFormatException e) {
//                    throw new RuntimeException("解析代币余额失败: " + hexBalance, e);
//                }
//            }
//        }
//        return BigDecimal.ZERO;
//    }
//
//    /**
//     * 添加请求头（包含API Key）
//     */
//    private static HttpRequest addHeaders(HttpRequest request) {
//        request.header("Content-Type", "application/json");
//        if (apiKey != null && !apiKey.isEmpty()) {
//            request.header("TRON-PRO-API-KEY", apiKey);
//        }
//        return request;
//    }
}