package suite

import (
	"flag"
	"fmt"
	"testing"

	"github.com/spf13/pflag"

	"github.com/tidbcloud/eks-provider/tests/e2e/dag"
	"github.com/tidbcloud/eks-provider/tests/e2e/label"
	"github.com/tidbcloud/eks-provider/tests/e2e/types"
	"github.com/tidbcloud/eks-provider/tests/e2e/utils/namer"
)

var global = mustNewSuite()

type suite struct {
	opt    *Options
	runner Runner
}

func mustNewSuite() *suite {
	s, err := newSuite()
	Must(err)
	return s
}

func newSuite() (*suite, error) {
	return &suite{
		opt:    NewOptions(),
		runner: NewRunner(),
	}, nil
}

func RegisterFlags(fs *pflag.FlagSet) {
	global.opt.RegisterFlags(fs)
}

func CopyGoFlags(fs *pflag.FlagSet, gfs *flag.FlagSet) {
	gfs.VisitAll(func(f *flag.Flag) {
		switch f.Name {
		case "kubeconfig", "test.run", "test.skip":
			// disable these flags
			return
		case "test.timeout":
			Must(f.Value.Set("4h"))
		case "test.v":
			Must(f.Value.Set("true"))
		}
		fs.AddGoFlag(f)
	})
}

func PrintFlags(fs *pflag.FlagSet) {
	fs.Visit(func(f *pflag.Flag) {
		fmt.Printf("--%s=%v, %v\n", f.Name, f.Value.String(), f.Value.Type())
	})
}

func GetOptions() *Options {
	return global.opt
}

func Must(err error) {
	if err != nil {
		panic(err)
	}
}

func AddEnv(es ...label.Object[dag.Env]) {
	global.runner.AddEnv(es...)
}

func AddCase(cs ...label.Object[dag.Case]) {
	global.runner.AddCase(cs...)
}

func Run(t *testing.T) {
	namer.Seed(global.opt.Seed)
	namer.Register(types.Resources...)

	fmt.Println("[RANDOM SEED]:", global.opt.Seed)

	err := global.runner.Run(t, global.opt.Selector)
	Must(err)
}

func Interrupt(err error) {
	fmt.Println("interrupt test because of", err)
	global.runner.Cancel(fmt.Errorf("stop test by some unexpected errors: %w", err))
}

func PrintSummary() {
	s := global.runner.Summary()
	fmt.Println(s.String())
}
