package workflow

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)

func evalJSONPathValue(input any, path string) any {
	path = strings.TrimSpace(path)
	if path == "" || path == "$" || path == "." {
		return input
	}
	if strings.HasPrefix(path, "$.") {
		path = strings.TrimPrefix(path, "$.")
	} else if strings.HasPrefix(path, ".") {
		path = strings.TrimPrefix(path, ".")
	} else if strings.HasPrefix(path, "$") {
		path = strings.TrimPrefix(path, "$")
	}
	cur := normalizeJSONInput(input)
	for _, token := range parseJSONPathTokens(path) {
		if token == "" {
			continue
		}
		switch v := cur.(type) {
		case map[string]any:
			cur = v[token]
		case []any:
			idx, err := strconv.Atoi(token)
			if err != nil || idx < 0 || idx >= len(v) {
				return ""
			}
			cur = v[idx]
		default:
			return ""
		}
	}
	if cur == nil {
		return ""
	}
	return cur
}

func normalizeJSONInput(input any) any {
	switch v := input.(type) {
	case string:
		var decoded any
		if err := json.Unmarshal([]byte(v), &decoded); err == nil {
			return decoded
		}
		return v
	case []byte:
		var decoded any
		if err := json.Unmarshal(v, &decoded); err == nil {
			return decoded
		}
		return string(v)
	default:
		return input
	}
}

func parseJSONPathTokens(path string) []string {
	var tokens []string
	var buf strings.Builder
	for i := 0; i < len(path); i++ {
		ch := path[i]
		switch ch {
		case '.':
			if buf.Len() > 0 {
				tokens = append(tokens, buf.String())
				buf.Reset()
			}
		case '[':
			if buf.Len() > 0 {
				tokens = append(tokens, buf.String())
				buf.Reset()
			}
			j := i + 1
			for j < len(path) && path[j] != ']' {
				j++
			}
			if j <= len(path) {
				token := strings.Trim(path[i+1:j], `"' `)
				tokens = append(tokens, token)
				i = j
			}
		default:
			buf.WriteByte(ch)
		}
	}
	if buf.Len() > 0 {
		tokens = append(tokens, buf.String())
	}
	return tokens
}

func validateJSONPathSyntax(path string) error {
	path = strings.TrimSpace(path)
	if path == "" {
		return fmt.Errorf("JSONPath 不能为空")
	}
	if !strings.HasPrefix(path, "$") && !strings.HasPrefix(path, ".") {
		return fmt.Errorf("JSONPath/JQ 路径必须以 $ 或 . 开头")
	}
	if strings.Contains(path, "..") || strings.ContainsAny(path, "*?()|") {
		return fmt.Errorf("仅支持安全路径子集，不支持通配符、递归或表达式")
	}
	if strings.Count(path, "[") != strings.Count(path, "]") {
		return fmt.Errorf("JSONPath 方括号不匹配")
	}
	return nil
}
