package blockchain

import (
	"context"
	"fmt"
	"ktogame/contractgo/Collect"
	"ktogame/dbUtil"
	"ktogame/models"
	"os"
	"strings"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"github.com/ethereum/go-ethereum/accounts/abi"

	utilAddress "github.com/korthochain/korthochain/pkg/address"
	"github.com/korthochain/korthochain/pkg/block"
	pb "github.com/korthochain/korthochain/pkg/server/grpcserver/message"
	"github.com/korthochain/korthochain/pkg/transaction"
	"google.golang.org/grpc"
)

var ktoClient pb.GreeterClient
var ktoRpc = beego.AppConfig.String("hostHttp_mit_kto")
var currentBlock uint64

var TopsMap map[string]string

func init() {
	kc, err := grpc.Dial(ktoRpc, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		logs.Info(err)
		os.Exit(1)
	}
	ktoClient = pb.NewGreeterClient(kc)
	utilAddress.SetNetWork("mainnet")

	tm := make(map[string]string, 0)
	tm[TopicParticipate] = COLLECT_PARTICIPATE
	TopsMap = tm

	go scanBlock()
}

func scanBlock() {
	time.Sleep(time.Second * 2)
	var bi models.BlockInfo
	ok, err := dbUtil.Engine.Id(1).Get(&bi)
	if err != nil {
		fmt.Println("获取最新快高错误=", err)
		return
	}
	if !ok {
		fmt.Println("获取最新快高失败!")
		return
	}
	currentBlock = uint64(bi.BlockNumber) + 1
	//currentBlock =62203394
	for {
		time.Sleep(time.Second * 5)
		res, err := ktoClient.GetMaxBlockHeight(context.Background(), &pb.ReqMaxBlockHeight{})
		if err != nil {
			fmt.Println("获取交易block number错误=", err)
			time.Sleep(time.Second * 5)
			continue
		}
		if res.MaxHeight < currentBlock {
			time.Sleep(time.Second * time.Duration(((currentBlock - res.MaxHeight) * 5)))
			continue
		}

		bl, err := ktoClient.GetBlockByNum(context.Background(), &pb.ReqBlockByNumber{Height: currentBlock})
		if err != nil || bl.Code != 0 {
			fmt.Println("获取交易block错误=", err)
			continue
		}
		blc, errs := block.Deserialize(bl.Data)
		if errs != nil {
			fmt.Println("解析blcock错误=", errs)
			continue
		}
		var ERR error
		for _, v := range blc.Transactions {
			evm, err := transaction.DecodeEvmData(v.Input)
			if err != nil {
				ERR = err
				break
			}
			if len(evm.Logs) == 0 {
				break
			}
			for _, l := range evm.Logs {
				th := l.Topics[0].Hex()
				method := TopsMap[th]
				addr := l.Address.String()
				if method == COLLECT_PARTICIPATE && addr == COLLECTCONTRACT {
					var ev EventParticipate
					abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI))
					if err != nil {
						ERR = err
						break
					}
					err = abi.UnpackIntoInterface(&ev, method, l.Data)
					if err != nil {
						ERR = err
						break
					}
					fmt.Printf("data=%+v\n ", ev)
					//handle user participate

					//usdrido(ev.User.String(), ev.Referrer.String(), v.HashToString(), decimal.NewFromBigInt(ev.Amount, -11), decimal.NewFromBigInt(ev.Price, -18), currentBlock)
				}
			}
		}
		if ERR != nil {
			fmt.Println("处理错误=", ERR)
			continue
		}
		bi.BlockNumber = int64(currentBlock)
		_, err = dbUtil.Engine.ID(1).Update(&bi)
		if err != nil {
			fmt.Println("更新最新快高错误=", err)
			return
		}

		currentBlock++
	}
}
