package svctaskrunhandler

import (
	"encoding/json"
	"fmt"

	"github.com/valyala/fasttemplate"

	taskM "github.com/pingcap/test-infra/common/model/tcms/taskruns"
)

func ExtractParams(binds []taskM.TaskInputBind, decls []taskM.TaskInputDecl) (map[string]any, error) {
	rt := make(map[string]any, len(decls))
	declared := make(map[string]any, len(decls))
	for _, inputDecl := range decls {
		declared[inputDecl.Name] = inputDecl
	}
	for _, inputBind := range binds {
		if _, ok := declared[inputBind.Name]; !ok {
			return nil, fmt.Errorf("unknown argument: %s", inputBind.Name)
		}
		if inputBind.Value == "" {
			return nil, fmt.Errorf("no value for argument: %s", inputBind.Name)
		}
		rt[fmt.Sprintf("inputs.%s", inputBind.Name)] = inputBind.Value
	}
	return rt, nil
}

func RenderWithInputs[T any](obj T, binds []taskM.TaskInputBind, decls []taskM.TaskInputDecl) (*T, error) {
	params, err := ExtractParams(binds, decls)
	if err != nil {
		return nil, err
	}
	marshaled, err := json.Marshal(obj)
	if err != nil {
		return nil, err
	}
	template := fasttemplate.New(string(marshaled), "{{", "}}")
	rendered := template.ExecuteStringStd(params)
	err = json.Unmarshal([]byte(rendered), &obj)
	if err != nil {
		return nil, err
	}
	return &obj, nil
}
