package test_node

import (
	"fmt"
	"git.sxidc.com/go-tools/utils/pipeline/component"
	"git.sxidc.com/go-tools/utils/strutils"
	"github.com/mitchellh/mapstructure"
	"github.com/pkg/errors"
	"math/rand"
)

const (
	TypeBool = "bool"
)

const (
	BoolOperationPass          = "pass"
	BoolOperationReverse       = "reverse"
	BoolOperationRand          = "rand"
	BoolOperationUseLastResult = "last"
)

type BoolRunParams struct {
	Operation string `mapstructure:"op" structs:"op"`
	Value     *bool  `mapstructure:"value" structs:"value"`
}

type BoolNode struct {
	component.BaseComponent
}

func (n *BoolNode) Run(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
	return n.OnRun(globalRunParams, dynamicParams,
		func(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
			params := new(BoolRunParams)
			err := mapstructure.Decode(dynamicParams, params)
			if err != nil {
				return nil, errors.New(TypeBool + "节点运行时参数Decode失败: " + err.Error())
			}

			if strutils.IsStringEmpty(params.Operation) {
				params.Operation = BoolOperationPass
			}

			switch params.Operation {
			case BoolOperationPass:
				if params.Value == nil {
					return false, nil
				}

				return *params.Value, nil
			case BoolOperationReverse:
				if params.Value == nil {
					return false, nil
				}

				return !*params.Value, nil
			case BoolOperationRand:
				result := rand.Uint32()%2 == 0
				fmt.Println("rand bool is", result)
				return result, nil
			case BoolOperationUseLastResult:
				lastResult := globalRunParams.GetLastResult()
				lastResultBool, ok := lastResult.(bool)
				if !ok {
					return lastResult != nil, nil
				}

				return lastResultBool, nil
			default:
				return nil, errors.New(TypeBool + "不支持的操作: " + params.Operation)
			}
		})
}

type BoolBuilder struct{}

func (builder *BoolBuilder) ProductType() string {
	return TypeBool
}

func (builder *BoolBuilder) Build(name string, _ map[string]any, runParams map[string]any) (component.Component, error) {
	return &BoolNode{
		BaseComponent: *component.NewBaseComponent(TypeBool, name, runParams),
	}, nil
}