package genex

import (
	"context"
	"fmt"
	"math/big"
	"strings"

	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
)

// Settlement 合约 ABI（executeSwap 函数签名）
const settlementABIJSON = `[{"name":"executeSwap","type":"function","inputs":[{"name":"tokenId","type":"uint256"},{"name":"buyer","type":"address"},{"name":"seller","type":"address"},{"name":"price","type":"uint256"},{"name":"stablecoin","type":"address"}],"outputs":[]}]`

// SettlementContractAddress 默认 Settlement 合约地址（可通过配置覆盖）
var SettlementContractAddress = common.HexToAddress("0x0000000000000000000000000000000000000004")

// TxReceipt 交易回执
type TxReceipt struct {
	TxHash      string `json:"txHash"`
	BlockNumber int64  `json:"blockNumber"`
	GasUsed     uint64 `json:"gasUsed"`
	Status      uint64 `json:"status"` // 1=success, 0=failed
}

// ExecuteSwap 构造+签名+广播券原子交换交易
func (c *Client) ExecuteSwap(params SwapParams, signer Signer) (*TxReceipt, error) {
	parsedABI, err := abi.JSON(strings.NewReader(settlementABIJSON))
	if err != nil {
		return nil, fmt.Errorf("parse settlement ABI: %w", err)
	}

	calldata, err := parsedABI.Pack("executeSwap",
		params.TokenID,
		params.Buyer,
		params.Seller,
		params.Price,
		params.Stablecoin,
	)
	if err != nil {
		return nil, fmt.Errorf("pack executeSwap: %w", err)
	}

	// 获取 nonce
	nonce, err := c.ethClient.PendingNonceAt(context.Background(), signer.GetAddress())
	if err != nil {
		return nil, fmt.Errorf("get nonce: %w", err)
	}

	// 获取 gas price
	gasPrice, err := c.ethClient.SuggestGasPrice(context.Background())
	if err != nil {
		return nil, fmt.Errorf("suggest gas price: %w", err)
	}

	// 构造交易
	tx := types.NewTransaction(
		nonce,
		SettlementContractAddress,
		big.NewInt(0),
		uint64(300000), // gas limit
		gasPrice,
		calldata,
	)

	// 签名
	signedBytes, err := signer.SignTransaction(tx)
	if err != nil {
		return nil, fmt.Errorf("sign transaction: %w", err)
	}

	// 广播
	var signedTx types.Transaction
	if err := signedTx.UnmarshalBinary(signedBytes); err != nil {
		return nil, fmt.Errorf("unmarshal signed tx: %w", err)
	}

	if err := c.ethClient.SendTransaction(context.Background(), &signedTx); err != nil {
		return nil, fmt.Errorf("send transaction: %w", err)
	}

	// 等待回执
	receipt, err := c.ethClient.TransactionReceipt(context.Background(), signedTx.Hash())
	if err != nil {
		return nil, fmt.Errorf("get receipt: %w", err)
	}

	return &TxReceipt{
		TxHash:      signedTx.Hash().Hex(),
		BlockNumber: receipt.BlockNumber.Int64(),
		GasUsed:     receipt.GasUsed,
		Status:      receipt.Status,
	}, nil
}
