package main

import (
	"fmt"
	"math"

	"github.com/filecoin-project/go-address"
	"gopkg.in/urfave/cli.v2"

	"github.com/filecoin-project/lotus/chain/types"
	lcli "github.com/filecoin-project/lotus/cli"
)

var noncefix = &cli.Command{
	Name: "noncefix",
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name:    "repo",
			EnvVars: []string{"LOTUS_PATH"},
			Hidden:  true,
			Value:   "~/.lotus", // TODO: Consider XDG_DATA_HOME
		},
		&cli.Uint64Flag{
			Name: "start",
		},
		&cli.Uint64Flag{
			Name: "end",
		},
		&cli.StringFlag{
			Name: "addr",
		},
		&cli.BoolFlag{
			Name: "auto",
		},
	},
	Action: func(cctx *cli.Context) error {
		api, closer, err := lcli.GetFullNodeAPI(cctx)
		if err != nil {
			return err
		}

		defer closer()
		ctx := lcli.ReqContext(cctx)

		addr, err := address.NewFromString(cctx.String("addr"))
		if err != nil {
			return err
		}

		start := cctx.Uint64("start")
		end := cctx.Uint64("end")
		if end == 0 {
			end = math.MaxUint64
		}

		if cctx.Bool("auto") {
			a, err := api.StateGetActor(ctx, addr, types.EmptyTSK)
			if err != nil {
				return err
			}
			start = a.Nonce

			msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
			if err != nil {
				return err
			}

			for _, msg := range msgs {
				if msg.Message.From != addr {
					continue
				}
				if msg.Message.Nonce < start {
					continue // past
				}
				if msg.Message.Nonce < end {
					end = msg.Message.Nonce
				}
			}

		}
		if end == math.MaxUint64 {
			fmt.Println("No nonce gap found or no --end flag specified")
			return nil
		}
		fmt.Printf("Creating %d filler messages (%d ~ %d)\n", end-start, start, end)

		for i := start; i < end; i++ {
			msg := &types.Message{
				From:     addr,
				To:       addr,
				Value:    types.NewInt(1),
				GasLimit: 10000,
				GasPrice: types.NewInt(1),
				Nonce:    i,
			}
			smsg, err := api.WalletSignMessage(ctx, addr, msg)
			if err != nil {
				return err
			}

			_, err = api.MpoolPush(ctx, smsg)
			if err != nil {
				return err
			}
		}

		return nil
	},
}