package tutus_test

import (
	"cmp"
	"context"
	"math/big"
	"slices"

	"git.marketally.com/tutus-one/tutus-chain/pkg/encoding/address"
	"git.marketally.com/tutus-one/tutus-chain/pkg/tutusrpc/result"
	"git.marketally.com/tutus-one/tutus-chain/pkg/rpcclient"
	"git.marketally.com/tutus-one/tutus-chain/pkg/rpcclient/actor"
	"git.marketally.com/tutus-one/tutus-chain/pkg/rpcclient/invoker"
	"git.marketally.com/tutus-one/tutus-chain/pkg/rpcclient/tutus"
	"git.marketally.com/tutus-one/tutus-chain/pkg/wallet"
)

func ExampleContractReader() {
	// No error checking done at all, intentionally.
	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Safe methods are reachable with just an invoker, no need for an account there.
	inv := invoker.New(c, nil)

	// Create a reader interface.
	neoToken := tutus.NewReader(inv)

	// Account hash we're interested in.
	accHash, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Get the account balance.
	balance, _ := neoToken.BalanceOf(accHash)
	_ = balance

	// Get the extended NEO-specific balance data.
	bNeo, _ := neoToken.GetAccountState(accHash)

	// Account can have no associated vote.
	if bNeo.VoteTo == nil {
		return
	}
	// Committee keys.
	comm, _ := neoToken.GetCommittee()

	// Check if the vote is made for a committee member.
	var votedForCommitteeMember bool
	if slices.ContainsFunc(comm, bNeo.VoteTo.Equal) {
		votedForCommitteeMember = true
	}
	_ = votedForCommitteeMember
}

func ExampleContract() {
	// No error checking done at all, intentionally.
	w, _ := wallet.NewWalletFromFile("somewhere")
	defer w.Close()

	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Create a simple CalledByEntry-scoped actor (assuming there is an account
	// inside the wallet).
	a, _ := actor.NewSimple(c, w.Accounts[0])

	// Create a complete contract representation.
	neoToken := tutus.New(a)

	tgtAcc, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Send a transaction that transfers one token to another account.
	txid, vub, _ := neoToken.Transfer(a.Sender(), tgtAcc, big.NewInt(1), nil)
	_ = txid
	_ = vub

	// Get a list of candidates (it's limited, but should be sufficient in most cases).
	cands, _ := neoToken.GetCandidates()

	// Sort by votes.
	slices.SortFunc(cands, func(a, b result.Validator) int { return cmp.Compare(a.Votes, b.Votes) })

	// Get the extended NEO-specific balance data.
	bNeo, _ := neoToken.GetAccountState(a.Sender())

	// If not yet voted, or voted for suboptimal candidate (we want the one with the least votes),
	// send a new voting transaction
	if bNeo.VoteTo == nil || !bNeo.VoteTo.Equal(&cands[0].PublicKey) {
		txid, vub, _ = neoToken.Vote(a.Sender(), &cands[0].PublicKey)
		_ = txid
		_ = vub
	}
}
