package steps

import (
	"context"
	"fmt"
	"strconv"

	"github.com/pingcap/errors"
)

type assertCode int

const (
	Larger assertCode = iota
	Less
)

type assertValue struct {
	actual *string
	opt    assertCode
	expect float64
}

func (o assertCode) String() string {
	switch o {
	case Larger:
		return "Larger"
	case Less:
		return "Less"
	}
	return "(unknown)"
}

func (c assertValue) String() string {
	return fmt.Sprintf("Assert Value, actual text: %s, assertCode: %s, expect value: %f", *c.actual, c.opt.String(), c.expect)
}

func (c assertValue) Execute(ctx context.Context) error {
	actual, err := strconv.ParseFloat(*c.actual, 64)
	if err != nil {
		return errors.Trace(err)
	}
	switch c.opt {
	case Less:
		if actual > c.expect {
			return errors.New(fmt.Sprintf("the assert value exceeded. expect: <%f, actual: %f", c.expect, actual))
		}
		return nil
	}
	return errors.New("Assert Values failed")
}

var _ Step = &assertValue{}

func AssertValue(actual *string, opt assertCode, expect float64) *assertValue {
	return &assertValue{
		actual,
		opt,
		expect,
	}
}

func (b *Builder) AssertValue(s *string, opt assertCode, expect float64) *Builder {
	b.steps = append(b.steps, AssertValue(s, opt, expect))
	return b
}
