import { getWeb3, buildSignatureParams } from "@/utils/utils.js";
import jlabiData from "@/utils/abijson/jlabi.json";
import bmabiData from "@/utils/abijson/bmabi.json";
import pubData from "@/utils/abijson/pub.json";

const TOKEN_ADDRESSES = {
    wgt: "0x1b7fE9d431a8357dBf7BB1621df9e7Bd2973eBB2",
    stt: "0xC891A3F6E9B560a4F21eEABc884d92073D36fF87"
};

const MANAGER_ADDRESS = "0x87803B5d8d426359fef52474C19280f35d355f69";

function normalizePrivateKey(pk) {
    return pk.startsWith("0x") ? pk : "0x" + pk;
}
function scaleGasPrice(originalGasPrice, gasRate) {
    if (gasRate >= 1) {
        return BigInt(originalGasPrice) * BigInt(Math.floor(gasRate));
    }

    // 小于1的小数处理
    const gasRateStr = gasRate.toString(); // 比如 "0.1"
    const decimalPlaces = gasRateStr.split(".")[1]?.length || 0;
    const denominator = 10 ** decimalPlaces;
    const numerator = Math.floor(gasRate * denominator);

    const scaled = (BigInt(originalGasPrice) * BigInt(numerator)) / BigInt(denominator);
    return scaled;
}

// 获取余额
async function getBalance(privateKey, type) {
    try {
        const web3 = await getWeb3();
        privateKey = normalizePrivateKey(privateKey);
        const { address } = web3.eth.accounts.privateKeyToAccount(privateKey);
        const tokenAddress = TOKEN_ADDRESSES[type.toLowerCase()];
        const tokenContract = new web3.eth.Contract(pubData, tokenAddress);

        const balanceWei = await tokenContract.methods.balanceOf(address).call();
        return web3.utils.fromWei(balanceWei, 'ether');
    } catch (error) {
        return {
            success: false,
            message: error?.message || '未知错误'
        };
    }
}


// 发放奖励
async function sendSingleReward(privateKey, amount, GasRate) {
    if (!privateKey) {
        return { status: "error", message: "未获取到私钥，无法发放奖励" };
    }

    privateKey = normalizePrivateKey(privateKey);

    try {
        const web3 = await getWeb3();
        const account = web3.eth.accounts.privateKeyToAccount(privateKey);
        const sender = account.address;
        const amountWei = web3.utils.toWei(amount.toString(), "ether");
        const contractAddress = "0x712fA39BF916C30697768dC5c00298f9340C7b27";
        const contract = new web3.eth.Contract(jlabiData, contractAddress);

        const { timestamp, nonceForSig, signature } = await buildSignatureParams(sender, amountWei, contractAddress);

        if (!signature) throw new Error("签名为空");

        const gasPrice = await web3.eth.getGasPrice();
        let adjustedGasPrice = scaleGasPrice(gasPrice, GasRate);
        const maxTotalFee = BigInt(web3.utils.toWei("1", "ether")); // 1 ACC 上限
        const gasLimit = 500000n;

        // 如果 gasPrice 太高，限制为不会超过 1 ACC 的值
        if (adjustedGasPrice * gasLimit > maxTotalFee) {
            adjustedGasPrice = maxTotalFee / gasLimit;
        }
        const tx = {
            from: sender,
            to: contractAddress,
            data: contract.methods
                .distributeSingleReward(sender, amountWei, timestamp, nonceForSig, signature)
                .encodeABI(),
            gas: gasLimit,
            gasPrice: adjustedGasPrice.toString(),
            nonce: await web3.eth.getTransactionCount(sender, "pending"),
            chainId: await web3.eth.getChainId()
        };

        const signed = await web3.eth.accounts.signTransaction(tx, privateKey);
        const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);

        return { status: "success", hash: receipt.transactionHash };

    } catch (error) {
        const errMsg = error.message || "奖励发放失败，未知错误";
        const fullError = JSON.stringify(error, Object.getOwnPropertyNames(error), 2);
        console.error("🧾 奖励发放失败：", fullError);
        return { status: "error", message: errMsg, errorData: fullError };
    }
}

// 通用报名函数（支持 WGT 和 STT）
async function tokenSignUp(privateKey, amount, GasRate,type) {
    try {
        const web3 = await getWeb3();
        privateKey = normalizePrivateKey(privateKey);
        const tokenAddress = TOKEN_ADDRESSES[type.toLowerCase()];
        const tokenAmount = web3.utils.toWei(amount.toString(), "ether");
        const account = web3.eth.accounts.privateKeyToAccount(privateKey);
        const sender = account.address;

        const [chainId, gasPrice, nonce] = await Promise.all([
            web3.eth.getChainId(),
            web3.eth.getGasPrice(),
            web3.eth.getTransactionCount(sender)
        ]);

        let adjustedGasPrice = scaleGasPrice(gasPrice, GasRate);
        const maxTotalFee = BigInt(web3.utils.toWei("1", "ether")); // 1 ACC 上限
        let gasLimit = 500000n;

        // 如果 gasPrice 太高，限制为不会超过 1 ACC 的值
        if (adjustedGasPrice * gasLimit > maxTotalFee) {
            adjustedGasPrice = maxTotalFee / gasLimit;
        }

        const tokenContract = new web3.eth.Contract(pubData, tokenAddress);
        const exchangeContract = new web3.eth.Contract(bmabiData, MANAGER_ADDRESS);

        // 授权
        const approveTx = await web3.eth.accounts.signTransaction({
            from: sender,
            to: tokenAddress,
            data: tokenContract.methods.approve(MANAGER_ADDRESS, tokenAmount).encodeABI(),
            gas: 300000,
            gasPrice: adjustedGasPrice.toString(),
            chainId,
            nonce
        }, privateKey);

        const approveReceipt = await web3.eth.sendSignedTransaction(approveTx.rawTransaction);
        if (!approveReceipt.status) return { status: "error", message: "授权失败" };

        // 验证授权余额
        const [allowance, tokenBalance] = await Promise.all([
            tokenContract.methods.allowance(sender, MANAGER_ADDRESS).call(),
            tokenContract.methods.balanceOf(sender).call()
        ]);
        console.log('授权额度:', allowance)
        console.log('账户余额:', tokenBalance)
        if (BigInt(allowance) < BigInt(tokenAmount)) return { status: "error", message: "授权额度不足" };
        if (BigInt(tokenBalance) < BigInt(tokenAmount)) return { status: "error", message: `${type.toUpperCase()} 余额不足` };

        // gas 估算
        const receiveMethod = type.toLowerCase() === 'wgt' ? 'receiveWGT' : 'receiveSTT';
        const gasEstimate = await exchangeContract.methods[receiveMethod](tokenAmount).estimateGas({ from: sender });
        gasLimit = Math.ceil(Number(gasEstimate) * 1.1);
        const minGasNeeded = BigInt(gasLimit) * adjustedGasPrice; // Use BigInt
        const ethBalance = await web3.eth.getBalance(sender);
        console.log('估算gas:', minGasNeeded)
        console.log('账户ACC余额:', ethBalance)
        if (BigInt(ethBalance) < minGasNeeded) return { status: "error", message: "ACC余额不足以支付Gas" };

        // 发送报名交易
        const depositTx = await web3.eth.accounts.signTransaction({
            from: sender,
            to: MANAGER_ADDRESS,
            data: exchangeContract.methods[receiveMethod](tokenAmount).encodeABI(),
            gas: gasLimit,
            gasPrice: adjustedGasPrice.toString(),
            chainId,
            nonce: await web3.eth.getTransactionCount(sender)
        }, privateKey);

        const receipt = await web3.eth.sendSignedTransaction(depositTx.rawTransaction);
        return { status: "success", hash: receipt.transactionHash };

    } catch (error) {
        console.error("❌ 报名流程出错：", JSON.stringify(error, Object.getOwnPropertyNames(error), 2));
        return {
            status: "error",
            message: error.message || "报名失败",
            errorData: error
        };
    }
}


const WGTForToken = (pk, num, GasRate) => tokenSignUp(pk, num, GasRate, 'wgt');
const STTForToken = (pk, num, GasRate) => tokenSignUp(pk, num, GasRate, 'stt');

export { getBalance, sendSingleReward, WGTForToken, STTForToken };
