package flow

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

const (
	TypeIf = "if"
)

type IfBuildParams struct {
	ConditionComponent *SubComponentBuildParams `mapstructure:"condition" structs:"condition"`
	TrueComponent      *SubComponentBuildParams `mapstructure:"condition_true" structs:"condition_true"`
	FalseComponent     *SubComponentBuildParams `mapstructure:"condition_false" structs:"condition_false"`
}

func (params *IfBuildParams) Check() error {
	if params.ConditionComponent == nil {
		return errors.New(TypeIf + "流程的条件参数为空")
	}

	if params.TrueComponent == nil {
		return errors.New(TypeIf + "流程的真组件参数为空")
	}

	if params.FalseComponent == nil {
		return errors.New(TypeIf + "流程的假组件参数为空")
	}

	err := params.ConditionComponent.Check(TypeIf)
	if err != nil {
		return err
	}

	err = params.TrueComponent.Check(TypeIf)
	if err != nil {
		return err
	}

	if params.ConditionComponent.Name == params.TrueComponent.Name ||
		params.TrueComponent.Name == params.FalseComponent.Name ||
		params.ConditionComponent.Name == params.FalseComponent.Name {
		return fmt.Errorf("流程中存在同名的组件: condition: %s true: %s false: %s",
			params.ConditionComponent.Name, params.TrueComponent.Name, params.FalseComponent.Name)
	}

	return nil
}

type If struct {
	component.BaseComponent
	ConditionComponent component.Component
	TrueComponent      component.Component
	FalseComponent     component.Component
}

func (f *If) Run(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
	return f.OnRun(globalRunParams, dynamicParams,
		func(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
			lastResult := globalRunParams.GetLastResult()

			var conditionDynamicParamsMap map[string]any
			conditionDynamicParams, ok := dynamicParams[f.ConditionComponent.GetName()]
			if ok {
				innerConditionDynamicParamsMap, ok := conditionDynamicParams.(map[string]any)
				if !ok {
					return nil, errors.New(TypeIf + "流程" + f.GetName() + "的条件组件" + f.ConditionComponent.GetName() + "动态参数类型错误")
				}

				conditionDynamicParamsMap = innerConditionDynamicParamsMap
			}

			conditionResult, err := f.ConditionComponent.Run(globalRunParams, conditionDynamicParamsMap)
			if err != nil {
				return nil, err
			}

			condition, ok := conditionResult.(bool)
			if !ok {
				return nil, errors.New(TypeIf + "流程的条件子组件返回结果应当为bool")
			}

			if condition {
				var trueDynamicParamsMap map[string]any
				trueDynamicParams, ok := dynamicParams[f.TrueComponent.GetName()]
				if ok {
					innerTrueDynamicParamsMap, ok := trueDynamicParams.(map[string]any)
					if !ok {
						return nil, errors.New(TypeIf + "流程" + f.GetName() + "的真组件" + f.TrueComponent.GetName() + "动态参数类型错误")
					}

					trueDynamicParamsMap = innerTrueDynamicParamsMap
				}

				result, err := f.TrueComponent.Run(globalRunParams, trueDynamicParamsMap)
				if err != nil {
					return nil, err
				}

				return result, nil
			} else {
				if f.FalseComponent != nil {
					var falseDynamicParamsMap map[string]any
					falseDynamicParams, ok := dynamicParams[f.FalseComponent.GetName()]
					if ok {
						innerFalseDynamicParamsMap, ok := falseDynamicParams.(map[string]any)
						if !ok {
							return nil, errors.New(TypeIf + "流程" + f.GetName() + "的假组件" + f.FalseComponent.GetName() + "动态参数类型错误")
						}

						falseDynamicParamsMap = innerFalseDynamicParamsMap
					}

					result, err := f.FalseComponent.Run(globalRunParams, falseDynamicParamsMap)
					if err != nil {
						return nil, err
					}

					return result, nil
				}
			}

			return lastResult, nil
		})
}

type IfBuilder struct{}

func (builder *IfBuilder) ProductType() string {
	return TypeIf
}

func (builder *IfBuilder) Build(name string, buildParams map[string]any, runParams map[string]any) (component.Component, error) {
	if buildParams == nil || len(buildParams) == 0 {
		return nil, errors.New(TypeIf + "流没有传递构建参数")
	}

	flowBuildParams := new(IfBuildParams)
	err := mapstructure.Decode(buildParams, flowBuildParams)
	if err != nil {
		return nil, errors.New(TypeIf + "流程构建参数Decode失败: " + err.Error())
	}

	err = flowBuildParams.Check()
	if err != nil {
		return nil, err
	}

	conditionFlow, err := flowBuildParams.ConditionComponent.BuildComponent()
	if err != nil {
		return nil, err
	}

	trueFlow, err := flowBuildParams.TrueComponent.BuildComponent()
	if err != nil {
		return nil, err
	}

	var falseFlow component.Component
	if flowBuildParams.FalseComponent != nil {
		innerFalseFlow, err := flowBuildParams.FalseComponent.BuildComponent()
		if err != nil {
			return nil, err
		}

		falseFlow = innerFalseFlow
	}

	return &If{
		BaseComponent:      *component.NewBaseComponent(TypeIf, name, runParams),
		ConditionComponent: conditionFlow,
		TrueComponent:      trueFlow,
		FalseComponent:     falseFlow,
	}, nil
}