package utils

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
)

// 原子表达式描述:
// eq arg1 arg2: arg1 == arg2时为true
// ne arg1 arg2: arg1 != arg2时为true
// lt arg1 arg2: arg1 < arg2时为true
// le arg1 arg2: arg1 <= arg2时为true
// gt arg1 arg2: arg1 > arg2时为true
// ge arg1 arg2: arg1 >= arg2时为true
// and arg1 arg2: arg1 && arg2
// or arg1 arg2: arg1 || arg2
// contain arg1 arg2: arg1 包含 arg2时为true
var operators = map[string]interface{}{
	"eq": func(a, b interface{}) bool {
		return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
	},
	"ge":      func(a, b float64) bool { return a >= b },
	"le":      func(a, b float64) bool { return a <= b },
	"gt":      func(a, b float64) bool { return a > b },
	"lt":      func(a, b float64) bool { return a < b },
	"and":     func(a, b bool) bool { return a && b },
	"or":      func(a, b bool) bool { return a || b },
	"contain": func(a, b string) bool { return strings.Contains(a, b) },
}

// 执行判断条件
func ExecConditionalStr(conditionalStr string) (bool, error) {
	// 正则表达式匹配括号内的表达式
	re := regexp.MustCompile(`\(([^()]*)\)`)
	matches := re.FindAllStringSubmatch(conditionalStr, -1)
	// 找到最里面的(原子表达式)
	for _, match := range matches {
		subCondition := match[1]
		result, err := ExecConditionalStr(subCondition)
		if err != nil {
			return false, err
		}
		// 用结果替换原子表达式
		conditionalStr = strings.ReplaceAll(conditionalStr, match[0], fmt.Sprintf("%t", result))
	}

	fields := strings.Fields(conditionalStr)
	// 执行原子表达式
	if len(fields) == 3 {
		compareFunc := operators[fields[0]]
		switch fc := compareFunc.(type) {
		default:
			return false, fmt.Errorf("invalid conditional func %v", compareFunc)
		case func(a, b float64) bool:
			a, err := strconv.ParseFloat(fields[1], 64)
			if err != nil {
				return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
			}
			b, err := strconv.ParseFloat(fields[2], 64)
			if err != nil {
				return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
			}
			return fc(a, b), nil
		case func(a, b bool) bool:
			a, err := strconv.ParseBool(fields[1])
			if err != nil {
				return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
			}
			b, err := strconv.ParseBool(fields[2])
			if err != nil {
				return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
			}
			return fc(a, b), nil
		case func(a, b string) bool:
			a := fields[1]
			b := fields[2]
			return fc(a, b), nil
		case func(a, b interface{}) bool:
			a := fields[1]
			b := fields[2]
			return fc(a, b), nil
		}
		// 继续获取上一层的(原子表达式)
	} else if strings.Contains(conditionalStr, "(") || strings.Contains(conditionalStr, ")") {
		return ExecConditionalStr(conditionalStr)
		// 原子表达式有问题，返回
	} else {
		return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
	}

}

// 通过正则表达式寻找模板中的 ｛｛foo｝｝ 字符串foo
// 返回 {{foo}} : foo
func ParseTmplStr(tmpl string) map[string]string {
	result := make(map[string]string)
	re := regexp.MustCompile(`\{\{(.*?)\}\}`)
	matches := re.FindAllStringSubmatch(tmpl, -1)
	for _, match := range matches {
		result[match[0]] = match[1]
	}
	return result
}

// 使用kv替换模板中的字符
// 例如 模板是`hello,{{foo}}` 使用{"{{foo}}":"bot"} 替换后为`hello,bot`
func ReplacedStr(tmpl string, kvs map[string]string) string {

	for k, v := range kvs {
		tmpl = strings.Replace(tmpl, k, v, -1)
	}

	return tmpl
}
