package utils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"regexp"
	"strings"

	"github.com/juju/errors"
	"gopkg.in/yaml.v3"
	"k8s.io/client-go/util/jsonpath"
)

func MarshalYamlWithIndent(v any, indent int) ([]byte, error) {
	var buf bytes.Buffer
	encoder := yaml.NewEncoder(&buf)
	encoder.SetIndent(2)
	err := encoder.Encode(v)
	return buf.Bytes(), err
}

// isSimpleKey 判断 key 是否是“简单”的：只能包含字母、数字、下划线
func isSimpleKey(key string) bool {
	re := regexp.MustCompile(`^[A-Za-z0-9_]+$`)
	return re.MatchString(key)
}

// toJSONPath 把点分路径转换为 JSONPath 表达式
func toJSONPath(path string) string {
	parts := strings.Split(path, ".")
	var b strings.Builder
	b.WriteString("{.")

	for i, p := range parts {
		// 忽略第一个.
		if i == 0 && p == "" {
			continue
		}
		if isSimpleKey(p) {
			if i > 0 {
				b.WriteString(".")
			}
			b.WriteString(p)
		} else {
			b.WriteString("['")
			b.WriteString(p)
			b.WriteString("']")
		}
	}

	b.WriteString("}")
	return b.String()
}

func GetStringByJsonPath(data []byte, path string) (string, error) {
	// yaml -> json -> map
	doc := make(map[string]any)
	err := yaml.Unmarshal(data, doc)
	if err != nil {
		return "", errors.Annotatef(err, "Failed to load yaml")
	}

	jPath := jsonpath.New("map")
	if err := jPath.Parse(toJSONPath(path)); err != nil {
		return "", err
	}

	out, err := jPath.FindResults(doc)
	if err != nil {
		return "", err
	}

	if len(out) > 0 && len(out[0]) > 0 {
		val := out[0][0].Interface()

		switch v := val.(type) {
		case string:
			return v, nil
		case fmt.Stringer:
			return v.String(), nil
		default:
			b, _ := json.Marshal(val)
			return string(b), nil
		}
	}
	return "", errors.NotFoundf("Path %s not found", path)
}
