package dialect

import "strings"

// 转换规则参考 https://github.com/tobymao/sqlglot
// dialects/bigquery.py, dialects/athena.py, dialects/presto.py, dialects/trino.py, generator.py

// castTypeReplace 定义 CAST 类型名的方言替换规则
// TiDB parser 将 CAST(x AS SIGNED) 序列化为 "cast(x as signed)"（小写关键字），
// 目标引擎可能不识别 signed/unsigned，需要替换为对应类型名（如 BigQuery 的 INT64）
type castTypeReplace struct {
	from string // 源类型关键字，如 "signed"、"unsigned"
	to   string // 目标类型名，如 "INT64"、"BIGINT"
}

// dialectConfig 方言配置：函数映射 + 参数顺序 + 标识符引用规则
type dialectConfig struct {
	funcMap          funcMap
	paramReorder     map[string][]int // 目标函数名 -> 参数置换，newArgs[i]=oldArgs[perm[i]]
	reservedKeywords map[string]bool
	identQuote       string             // BigQuery: "`", Athena/Presto: `"`
	castTypeReplaces []castTypeReplace   // CAST 类型替换规则
}

// quoteIdent 对保留字或含特殊字符的标识符加引号
func (c *dialectConfig) quoteIdent(s string) string {
	normalized := trimQuotes(strings.TrimSpace(s))
	if normalized == "" {
		return s
	}
	lower := strings.ToLower(normalized)
	if !c.reservedKeywords[lower] && isSimpleIdent(normalized) {
		return normalized
	}
	return c.identQuote + escapeIdent(normalized, c.identQuote) + c.identQuote
}

func isSimpleIdent(s string) bool {
	if len(s) == 0 {
		return false
	}
	for i, c := range s {
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' {
			continue
		}
		if c >= '0' && c <= '9' && i > 0 {
			continue
		}
		return false
	}
	return true
}

func escapeIdent(s, quote string) string {
	if len(quote) != 1 {
		return s
	}
	q := quote[0]
	var b strings.Builder
	for i := 0; i < len(s); i++ {
		if s[i] == q {
			b.WriteByte(q)
			b.WriteByte(q)
		} else {
			b.WriteByte(s[i])
		}
	}
	return b.String()
}
