package com.table.transfer.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.*;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.security.Security;
import java.util.Arrays;
import java.util.Collections;

public class CryptoUtil {
    
    // secp256k1曲线的阶n
    private static final BigInteger SECP256K1_N = new BigInteger("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16);
    
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    
    public static ECKeyPair createKeyPairFromPrivateKey(String privateKeyHex) {
        try {
            // 处理0x前缀
            if (privateKeyHex.startsWith("0x")) {
                privateKeyHex = privateKeyHex.substring(2);
            }
            
            BigInteger privateKey = new BigInteger(privateKeyHex, 16);
            return ECKeyPair.create(privateKey);
        } catch (Exception e) {
            throw new RuntimeException("无效的私钥: " + e.getMessage());
        }
    }
    
    public static String getAddressFromPrivateKey(String privateKeyHex) {
        ECKeyPair keyPair = createKeyPairFromPrivateKey(privateKeyHex);
        return Keys.getAddress(keyPair);
    }
    
    public static String getChecksumAddress(String address) {
        return Keys.toChecksumAddress(address);
    }
    
    public static RawTransaction createEthTransaction(
            BigInteger nonce, 
            BigInteger gasPrice, 
            BigInteger gasLimit, 
            String toAddress,
            BigInteger value, 
            String data) {
        
        return RawTransaction.createTransaction(
            nonce,
            gasPrice,
            gasLimit,
            toAddress,
            value,
            data
        );
    }
    
    public static String signTransaction(RawTransaction rawTransaction, byte chainId, ECKeyPair keyPair) {
        Credentials credentials = Credentials.create(keyPair);
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials);
        return Numeric.toHexString(signedMessage);
    }
    
    public static String buildTokenTransferData(String toAddress, BigInteger value) {
        try {
            // 确保地址格式正确
            String normalizedToAddress = toAddress;
            if (normalizedToAddress.startsWith("0x")) {
                normalizedToAddress = normalizedToAddress.substring(2);
            }
            
            Function function = new Function(
                "transfer",
                Arrays.asList(
                    new Address(normalizedToAddress),
                    new Uint256(value)
                ),
                Collections.singletonList(new TypeReference<org.web3j.abi.datatypes.Bool>() {})
            );
            
            return FunctionEncoder.encode(function);
        } catch (Exception e) {
            throw new RuntimeException("构建代币转账数据失败: " + e.getMessage());
        }
    }
    
    public static boolean validatePrivateKey(String privateKey) {
        try {
            if (privateKey.startsWith("0x")) {
                privateKey = privateKey.substring(2);
            }
            
            if (privateKey.length() != 64) {
                return false;
            }
            
            BigInteger pk = new BigInteger(privateKey, 16);
            
            // 检查私钥范围: 1 <= privateKey < n
            return pk.compareTo(BigInteger.ONE) >= 0 && 
                   pk.compareTo(SECP256K1_N) < 0;
            
        } catch (Exception e) {
            return false;
        }
    }
    
    public static boolean validateEthAddress(String address) {
        if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) {
            return false;
        }
        
        // 简单的校验和验证
        try {
            String checksumAddress = Keys.toChecksumAddress(address);
            return address.equals(checksumAddress) || 
                   address.equalsIgnoreCase(checksumAddress);
        } catch (Exception e) {
            return false;
        }
    }
    
    public static BigInteger weiToEther(BigInteger wei) {
        return wei.divide(BigInteger.TEN.pow(18));
    }
    
    public static BigInteger etherToWei(BigInteger ether) {
        return ether.multiply(BigInteger.TEN.pow(18));
    }
    
    public static BigInteger etherToWei(String etherAmount) {
        try {
            // 处理小数
            String[] parts = etherAmount.split("\\.");
            BigInteger integerPart = new BigInteger(parts[0]).multiply(BigInteger.TEN.pow(18));
            
            if (parts.length > 1) {
                String decimalPart = parts[1];
                if (decimalPart.length() > 18) {
                    decimalPart = decimalPart.substring(0, 18);
                }
                BigInteger decimalValue = new BigInteger(decimalPart)
                    .multiply(BigInteger.TEN.pow(18 - decimalPart.length()));
                integerPart = integerPart.add(decimalValue);
            }
            
            return integerPart;
        } catch (Exception e) {
            throw new RuntimeException("ETH金额格式错误: " + etherAmount);
        }
    }
}