package dialect

// 函数映射与保留字来自 https://github.com/tobymao/sqlglot
// dialects/bigquery.py, dialects/presto.py, dialects/trino.py, generator.py

// PrestoConfig Athena/Presto/Trino 方言配置
// 标识符引用：双引号 " (Trino/Presto 标准)
var PrestoConfig = &dialectConfig{
	funcMap:          prestoFuncMap,
	paramReorder:     prestoParamReorder,
	reservedKeywords: toSet(prestoReservedKeywords),
	identQuote:       `"`,
	castTypeReplaces: []castTypeReplace{
		{"signed", "BIGINT"},
		{"unsigned", "BIGINT"},
	},
}

// BigQueryConfig BigQuery 方言配置
// 标识符引用：反引号 ` (BigQuery 标准)
var BigQueryConfig = &dialectConfig{
	funcMap:          bigQueryFuncMap,
	paramReorder:     bigQueryParamReorder,
	reservedKeywords: toSet(bigqueryReservedKeywords),
	identQuote:       "`",
	castTypeReplaces: []castTypeReplace{
		{"signed", "INT64"},
		{"unsigned", "INT64"},
	},
}

// MaxComputeConfig MaxCompute (ODPS) 方言配置
// 标识符引用：反引号 ` (Hive 兼容)，函数名与 MySQL 差异较大
var MaxComputeConfig = &dialectConfig{
	funcMap:          maxComputeFuncMap,
	paramReorder:     maxComputeParamReorder,
	reservedKeywords: toSet(maxComputeReservedKeywords),
	identQuote:       "`",
}

// SynapseConfig T-SQL/Synapse Serverless SQL 方言配置
// 标识符引用使用双引号，Synapse 默认 QUOTED_IDENTIFIER ON 时可识别。
var SynapseConfig = &dialectConfig{
	funcMap:          synapseFuncMap,
	paramReorder:     synapseParamReorder,
	reservedKeywords: toSet(synapseReservedKeywords),
	identQuote:       `"`,
	castTypeReplaces: []castTypeReplace{
		{"signed", "BIGINT"},
		{"unsigned", "BIGINT"},
	},
}

// prestoParamReorder 目标函数名 -> 参数置换 newArgs[i]=oldArgs[perm[i]]
// Presto DATE_DIFF(unit, date1, date2)，输入约定 (date1, date2, unit)
var prestoParamReorder = map[string][]int{
	"date_diff": {2, 0, 1}, // (d1,d2,unit) -> (unit,d1,d2)
}

// bigQueryParamReorder 目标函数名 -> 参数置换
// BigQuery FORMAT_TIMESTAMP(format, timestamp[, tz])，输入约定 (timestamp, format[, tz])
// BigQuery PARSE_TIMESTAMP/PARSE_DATE(format, string)，输入约定 (string, format)
var bigQueryParamReorder = map[string][]int{
	"format_timestamp": {1, 0, 2}, // (ts, fmt[, tz]) -> (fmt, ts[, tz])
	"parse_timestamp":  {1, 0},    // (str, fmt) -> (fmt, str)
	"parse_date":       {1, 0},    // (str, fmt) -> (fmt, str)
}

// maxComputeParamReorder MaxCompute 目标函数名 -> 参数置换
// GET_JSON_OBJECT(jsonStr, path) 与 json_extract(json, path) 参数顺序一致
var maxComputeParamReorder = map[string][]int{}

var synapseParamReorder = map[string][]int{}

// maxComputeFuncMap 逻辑/通用函数 -> MaxCompute 函数（仅保留名称不同的映射，函数名大小写不敏感）
// 参考 https://www.alibabacloud.com/help/zh/maxcompute/user-guide/overview 及与 Hive/MySQL/Oracle 内建函数对照表
var maxComputeFuncMap = funcMap{
	"json_get":              "GET_JSON_OBJECT",
	"json_extract":          "GET_JSON_OBJECT",
	"json_value":            "GET_JSON_OBJECT",
	"json_extract_scalar":   "GET_JSON_OBJECT",
	"to_timestamp":          "FROM_UNIXTIME",
	"from_unixtime":         "FROM_UNIXTIME",
	"to_unixtime":           "UNIX_TIMESTAMP",
	"current_time":          "CURRENT_TIMESTAMP",
	"now":                   "GETDATE",
	"date_format":           "TO_CHAR",
	"date_parse":            "TO_DATE",
	"str_to_date":           "TO_DATE",
	"date_diff":             "DATEDIFF",
	"date_trunc":            "DATETRUNC",
	"regex_match":           "REGEXP_CONTAINS",
	"regexp_like":           "REGEXP_CONTAINS",
	"char_length":           "LENGTH",
	"character_length":      "LENGTH",
	"substring":             "SUBSTR",
	"upper":                 "TOUPPER",
	"lower":                 "TOLOWER",
	"position":              "INSTR",
	"ifnull":                "COALESCE",
	"approx_distinct":       "APPROX_DISTINCT",
	"approx_count_distinct": "APPROX_DISTINCT",
	"arbitrary":             "ANY_VALUE",
	"group_concat":          "WM_CONCAT",
	"string_agg":            "WM_CONCAT",
	"array_agg":             "COLLECT_LIST",
	"var_pop":               "VARIANCE",
	"variance":              "VAR_SAMP",
	"stddev_pop":            "STDDEV",
	"stddev":                "STDDEV_SAMP",
	"try_cast":              "CAST",
	"truncate":              "TRUNC",
	"ceiling":               "CEIL",
	"power":                 "POW",
	"sha256":                "SHA2",
}

var synapseFuncMap = funcMap{
	"ifnull":                "coalesce",
	"char_length":           "len",
	"character_length":      "len",
	"substring":             "substring",
	"any_value":             "min",
	"arbitrary":             "min",
	"approx_distinct":       "approx_count_distinct",
	"approx_count_distinct": "approx_count_distinct",
	"try_cast":              "try_cast",
}

// maxComputeReservedKeywords MaxCompute 官方保留字
// https://www.alibabacloud.com/help/zh/maxcompute/user-guide/reserved-words-and-keywords
var maxComputeReservedKeywords = []string{
	"add", "after", "all", "alter", "analyze", "and", "archive", "array", "as", "asc",
	"before", "between", "bigint", "binary", "blob", "boolean", "both", "bucket", "buckets", "by",
	"cascade", "case", "cast", "cfile", "change", "cluster", "clustered", "clusterstatus", "collection", "column", "columns",
	"comment", "compute", "concatenate", "continue", "create", "cross", "current", "cursor",
	"data", "database", "databases", "date", "datetime", "dbproperties", "decimal", "deferred", "delete", "delimited",
	"desc", "describe", "directory", "disable", "distinct", "distribute", "div", "double", "drop",
	"else", "enable", "end", "except", "escaped", "exclusive", "exists", "explain", "export", "extended", "external",
	"false", "fetch", "fields", "fileformat", "first", "float", "following", "format", "formatted",
	"from", "full", "function", "functions", "grant", "group", "having", "hold_ddltime",
	"idxproperties", "if", "import", "in", "index", "indexes", "inputdriver", "inputformat", "insert", "int",
	"intersect", "into", "is", "items", "join", "keys", "lateral", "left", "lifecycle", "like",
	"limit", "lines", "load", "local", "location", "lock", "locks", "long", "map", "mapjoin", "materialized",
	"minus", "msck", "no_drop", "not", "null", "of", "offline", "offset", "on", "option", "or", "order",
	"out", "outer", "outputdriver", "outputformat", "over", "overwrite", "partition", "partitioned",
	"partitionproperties", "partitions", "percent", "plus", "preceding", "preserve", "procedure", "purge",
	"range", "rcfile", "read", "readonly", "reads", "rebuild", "recordreader", "recordwriter", "reduce",
	"regexp", "rename", "repair", "replace", "restrict", "revoke", "right", "rlike", "row", "rows",
	"schema", "schemas", "select", "semi", "sequencefile", "serde", "serdeproperties", "set", "shared", "show",
	"show_database", "smallint", "sort", "sorted", "ssl", "statistics", "status", "stored", "streamtable",
	"string", "struct", "table", "tables", "tablesample", "tblproperties", "temporary", "terminated",
	"textfile", "then", "timestamp", "tinyint", "to", "touch", "transform", "trigger", "true", "type",
	"unarchive", "unbounded", "undo", "union", "uniontype", "uniquejoin", "unlock", "unsigned", "update",
	"use", "using", "utc", "utc_timestamp", "view", "when", "where", "while",
}

func toSet(ss []string) map[string]bool {
	m := make(map[string]bool, len(ss))
	for _, s := range ss {
		m[s] = true
	}
	return m
}

// prestoFuncMap 逻辑/通用函数 -> Presto/Trino 函数（仅保留名称不同的映射，函数名大小写不敏感）
var prestoFuncMap = funcMap{
	"json_get":         "json_extract",
	"json_value":       "json_extract_scalar",
	"to_timestamp":     "from_unixtime",
	"unix_timestamp":   "to_unixtime",
	"to_unixtime":      "to_unixtime",
	"str_to_date":      "date_parse",
	"regex_match":      "regexp_like",
	"char_length":      "length",
	"character_length": "length",
	"position":         "strpos",
	"instr":            "strpos",
	"ifnull":           "coalesce",
	"any_value":        "arbitrary",
	"group_concat":     "array_join",
	"string_agg":       "array_join",
	"variance":         "var_samp",
	"stddev":           "stddev_samp",
	"try_cast":         "try_cast",
	"array_length":     "cardinality",
	"array_contains":   "contains",
}

// bigQueryFuncMap 逻辑/通用函数 -> BigQuery 函数（仅保留名称不同的映射，函数名大小写不敏感）
var bigQueryFuncMap = funcMap{
	"json_get":              "JSON_VALUE",
	"json_extract":          "JSON_EXTRACT",
	"json_extract_scalar":   "JSON_VALUE",
	"to_timestamp":          "TIMESTAMP_SECONDS",
	"from_unixtime":         "TIMESTAMP_SECONDS",
	"unix_timestamp":        "UNIX_SECONDS",
	"to_unixtime":           "UNIX_SECONDS",
	"date_format":           "FORMAT_TIMESTAMP",
	"date_parse":            "PARSE_TIMESTAMP",
	"str_to_date":           "PARSE_DATE",
	"regex_match":           "REGEXP_CONTAINS",
	"regexp_like":           "REGEXP_CONTAINS",
	"char_length":           "LENGTH",
	"character_length":      "LENGTH",
	"substring":             "SUBSTR",
	"position":              "STRPOS",
	"ifnull":                "COALESCE",
	"approx_distinct":       "APPROX_COUNT_DISTINCT",
	"approx_count_distinct": "APPROX_COUNT_DISTINCT",
	"arbitrary":             "ANY_VALUE",
	"group_concat":          "STRING_AGG",
	"string_agg":            "STRING_AGG",
	"variance":              "VAR_SAMP",
	"stddev_pop":            "STDDEV_POP",
	"stddev":                "STDDEV_SAMP",
	"countif":               "COUNTIF",
	"try_cast":              "SAFE_CAST",
	"cardinality":           "ARRAY_LENGTH",
	"contains":              "CONTAINS_SUBSTR",
	"slice":                 "ARRAY_SLICE",
	"array_join":            "ARRAY_TO_STRING",
}

// prestoReservedKeywords 来自 sqlglot dialects/presto.py RESERVED_KEYWORDS
var prestoReservedKeywords = []string{
	"alter", "and", "as", "between", "by", "case", "cast", "constraint",
	"create", "cross", "current_time", "current_timestamp", "deallocate",
	"delete", "describe", "distinct", "drop", "else", "end", "escape",
	"except", "execute", "exists", "extract", "false", "for", "from",
	"full", "group", "having", "in", "inner", "insert", "intersect",
	"into", "is", "join", "left", "like", "natural", "not", "null",
	"on", "or", "order", "outer", "prepare", "right", "select", "table",
	"then", "true", "union", "using", "values", "when", "where", "with",
	"date", "time", "timestamp", "interval", "limit", "offset",
}

// bigqueryReservedKeywords 来自 sqlglot dialects/bigquery.py RESERVED_KEYWORDS
var bigqueryReservedKeywords = []string{
	"all", "and", "any", "array", "as", "asc", "assert_rows_modified",
	"at", "between", "by", "case", "cast", "collate", "contains",
	"create", "cross", "cube", "current", "default", "define", "desc",
	"distinct", "else", "end", "enum", "escape", "except", "exclude",
	"exists", "extract", "false", "fetch", "following", "for", "from",
	"full", "group", "grouping", "groups", "hash", "having", "if",
	"ignore", "in", "inner", "intersect", "interval", "into", "is",
	"join", "lateral", "left", "like", "limit", "lookup", "merge",
	"natural", "new", "no", "not", "null", "nulls", "of", "on", "or",
	"order", "outer", "over", "partition", "preceding", "proto",
	"qualify", "range", "recursive", "respect", "right", "rollup",
	"rows", "select", "set", "some", "struct", "tablesample", "then",
	"to", "treat", "true", "unbounded", "union", "unnest", "using",
	"when", "where", "window", "with", "within",
	"date", "time", "timestamp", "offset",
}

var synapseReservedKeywords = []string{
	"add", "all", "alter", "and", "any", "as", "asc", "authorization",
	"backup", "begin", "between", "break", "browse", "bulk", "by",
	"cascade", "case", "check", "checkpoint", "close", "clustered", "coalesce",
	"collate", "column", "commit", "compute", "constraint", "contains", "continue",
	"convert", "create", "cross", "current", "current_date", "current_time",
	"current_timestamp", "current_user", "cursor", "database", "date", "dbcc",
	"deallocate", "declare", "default", "delete", "deny", "desc", "distinct",
	"distributed", "double", "drop", "else", "end", "errlvl", "escape", "except",
	"exec", "execute", "exists", "exit", "external", "fetch", "file", "fillfactor",
	"for", "foreign", "from", "full", "function", "goto", "grant", "group",
	"having", "holdlock", "identity", "if", "in", "index", "inner", "insert",
	"intersect", "into", "is", "join", "key", "kill", "left", "like", "lineno",
	"load", "merge", "national", "nocheck", "nonclustered", "not", "null",
	"nullif", "of", "off", "offset", "on", "open", "opendatasource", "openquery",
	"openrowset", "openxml", "option", "or", "order", "outer", "over", "percent",
	"pivot", "plan", "precision", "primary", "print", "proc", "procedure",
	"public", "raiserror", "read", "readtext", "reconfigure", "references",
	"replication", "restore", "restrict", "return", "revert", "revoke", "right",
	"rollback", "row", "rows", "rule", "save", "schema", "select", "session_user",
	"set", "setuser", "shutdown", "some", "statistics", "system_user", "table",
	"textsize", "then", "time", "timestamp", "to", "top", "tran", "transaction",
	"trigger", "truncate", "try_convert", "tsequal", "union", "unique", "unpivot",
	"update", "updatetext", "use", "user", "values", "varying", "view", "waitfor",
	"when", "where", "while", "with", "within", "writetext",
}
