package tron

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"encoding/hex"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/mr-tron/base58"
	"wallet-system/internal/pkg/logging/applogger"
)

var (
	Trx   = "Trx"
	Trc20 = "Trc20"
)

// TronWalletAddress Generate Torn wallet address and private key
//
//	@Description:
//	@return string
//	@return string
//	@return error
func TronWalletAddress() (string, string, error) {
	walletAddress, privateKey, err := generateKeyPair()
	if err != nil {
		applogger.Error("Failed to generate Torn wallet address:%v", err)
		return "", "", err
	}

	applogger.Debug("Tron Wallet Address:%v", walletAddress)
	applogger.Debug("Tron wallet address private key:%v", privateKey)

	return walletAddress, privateKey, nil
}

// generateKeyPair Generate key pairs
//
//	@Description:
//	@return b5
//	@return pk
//	@return err
func generateKeyPair() (b5, pk string, err error) {
	privateKey, privateKeyBytes, err := tornPrivateKey()
	if err != nil {
		return "", "", err
	}

	publicKeyECDSA := tornPublicKey(privateKey)

	address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()

	address = "41" + address[2:]
	addNew, err := hex.DecodeString(address)
	if err != nil {
		return "", "", err
	}
	firstHash := sha256.Sum256(addNew)
	secondHash := sha256.Sum256(firstHash[:])
	secret := secondHash[:4]
	addNew = append(addNew, secret...)

	wallerAddr := base58.Encode(addNew)
	privateKeyStr := hexutil.Encode(privateKeyBytes)[2:]

	return wallerAddr, privateKeyStr, nil
}

// tornPrivateKey Generate private key
//
//	@Description:
//	@return *ecdsa.PrivateKey
//	@return []byte
//	@return error
func tornPrivateKey() (*ecdsa.PrivateKey, []byte, error) {
	privateKey, err := crypto.GenerateKey()
	if err != nil {
		return nil, []byte{}, err
	}
	privateKeyBytes := crypto.FromECDSA(privateKey)

	return privateKey, privateKeyBytes, nil
}

// tornPublicKey Generate public key
//
//	@Description:
//	@param privateKey
//	@return *ecdsa.PublicKey
func tornPublicKey(privateKey *ecdsa.PrivateKey) *ecdsa.PublicKey {
	publicKey := privateKey.Public()
	publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)

	return publicKeyECDSA
}