use hashbrown::HashSet;

use crate::ansi_keywords::{ANSI_RESERVED_KEYWORDS, ANSI_UNRESERVED_KEYWORDS};

/// T-SQL reserved keywords from Microsoft documentation
/// https://learn.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql
/// T-SQL specific keywords (to be added to ANSI keywords, not replace them)
pub(crate) fn tsql_additional_reserved_keywords() -> HashSet<&'static str> {
    [
        // Current T-SQL Reserved Keywords (from Microsoft documentation)
        "ADD",
        "ALL",
        "ALTER",
        "AND",
        "ANY",
        "AS",
        "ASC",
        "AUTHORIZATION",
        "BACKUP",
        "BEGIN",
        "BETWEEN",
        "BREAK",
        "BROWSE",
        "BULK",
        "BY",
        "CASCADE",
        "CASE",
        "CATCH",
        "CHECK",
        "CHECKPOINT",
        "CLOSE",
        "CLUSTERED",
        "COALESCE",
        "COLLATE",
        "COLUMN",
        "COMMIT",
        "COMPUTE",
        "CONSTRAINT",
        "CONTAINS",
        "CONTAINSTABLE",
        "CONTINUE",
        "CONVERT",
        "CREATE",
        "CROSS",
        "CURRENT",
        "CURRENT_DATE",
        "CURRENT_TIME",
        "CURRENT_TIMESTAMP",
        "CURRENT_USER",
        "CURSOR",
        "DATABASE",
        "DBCC",
        "DEALLOCATE",
        "DECLARE",
        "DEFAULT",
        "DELETE",
        "DENY",
        "DESC",
        "DISK",
        "DISTINCT",
        "DISTRIBUTED",
        "DOUBLE",
        "DROP",
        "DUMP",
        "ELSE",
        "END",
        "ERRLVL",
        "ERROR_LINE",
        "ERROR_MESSAGE",
        "ERROR_NUMBER",
        "ERROR_PROCEDURE",
        "ERROR_SEVERITY",
        "ERROR_STATE",
        "ESCAPE",
        "EXCEPT",
        "EXEC",
        "EXECUTE",
        "EXISTS",
        "EXIT",
        "EXTERNAL",
        "FETCH",
        "FILE",
        "FILLFACTOR",
        "FOR",
        "FOREIGN",
        "FREETEXT",
        "FREETEXTTABLE",
        "FROM",
        "FULL",
        "FUNCTION",
        "GOTO",
        "GRANT",
        "GROUP",
        "HAVING",
        "HOLDLOCK",
        "IDENTITY",
        "IDENTITY_INSERT",
        "IDENTITYCOL",
        "IF",
        "IN",
        "INDEX",
        "INNER",
        "INSERT",
        "INTERSECT",
        "INTO",
        "IS",
        "JOIN",
        "KEY",
        "KILL",
        "LEFT",
        "LIKE",
        "LINENO",
        "LOAD",
        "MERGE",
        "NATIONAL",
        "NOCHECK",
        "NONCLUSTERED",
        "NOT",
        "NULL",
        "NULLIF",
        "OF",
        "OFF",
        "OFFSETS",
        "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",
        "ROWCOUNT",
        "ROWGUIDCOL",
        "RULE",
        "SAVE",
        "SCHEMA",
        "SECURITYAUDIT",
        "SELECT",
        "SEMANTICKEYPHRASETABLE",
        "SEMANTICSIMILARITYDETAILSTABLE",
        "SEMANTICSIMILARITYTABLE",
        "SESSION_USER",
        "SET",
        "SETUSER",
        "SHUTDOWN",
        "SOME",
        "STATISTICS",
        "SYSTEM_USER",
        "TABLE",
        "TABLESAMPLE",
        "TEXTSIZE",
        "THEN",
        "TO",
        "TOP",
        "TRAN",
        "TRANSACTION",
        "TRIGGER",
        "TRUNCATE",
        "TRY",
        "TRY_CONVERT",
        "TSEQUAL",
        "UNION",
        "UNIQUE",
        "UNPIVOT",
        "UPDATE",
        "UPDATETEXT",
        "USE",
        "USER",
        "VALUES",
        "VARYING",
        "VIEW",
        "WAITFOR",
        "WHEN",
        "WHERE",
        "WHILE",
        "WITH",
        "WITHIN GROUP",
        "WRITETEXT",
    ]
    .into_iter()
    .collect()
}

/// T-SQL future keywords from Microsoft documentation
/// These are potential reserved keywords in future versions
#[allow(dead_code)]
pub(crate) fn tsql_future_keywords() -> HashSet<&'static str> {
    [
        // Future Keywords (from Microsoft documentation)
        "ABSOLUTE",
        "ACTION",
        "ADMIN",
        "AFTER",
        "AGGREGATE",
        "ALIAS",
        "ALLOCATE",
        "ARE",
        "ARRAY",
        "ASENSITIVE",
        "ASSERTION",
        "ASYMMETRIC",
        "AT",
        "ATOMIC",
        "BEFORE",
        "BINARY",
        "BIT",
        "BLOB",
        "BOOLEAN",
        "BOTH",
        "BREADTH",
        "CALL",
        "CALLED",
        "CARDINALITY",
        "CASCADED",
        "CAST",
        "CATALOG",
        "CHAR",
        "CHARACTER",
        "CLASS",
        "CLOB",
        "COLLATION",
        "COLLECT",
        "COMPLETION",
        "CONDITION",
        "CONNECT",
        "CONNECTION",
        "CONSTRAINTS",
        "CONSTRUCTOR",
        "CORR",
        "CORRESPONDING",
        "COVAR_POP",
        "COVAR_SAMP",
        "CUBE",
        "CUME_DIST",
        "CURRENT_CATALOG",
        "CURRENT_DEFAULT_TRANSFORM_GROUP",
        "CURRENT_PATH",
        "CURRENT_ROLE",
        "CURRENT_SCHEMA",
        "CURRENT_TRANSFORM_GROUP_FOR_TYPE",
        "CYCLE",
        "DATA",
        "DATE",
        "DAY",
        "DEC",
        "DECIMAL",
        "DEFERRABLE",
        "DEFERRED",
        "DEPTH",
        "DEREF",
        "DESCRIBE",
        "DESCRIPTOR",
        "DESTROY",
        "DESTRUCTOR",
        "DETERMINISTIC",
        "DIAGNOSTICS",
        "DICTIONARY",
        "DISCONNECT",
        "DOMAIN",
        "DYNAMIC",
        "EACH",
        "ELEMENT",
        "END-EXEC",
        "EQUALS",
        "EVERY",
        "EXCEPTION",
        "FALSE",
        "FILTER",
        "FIRST",
        "FLOAT",
        "FOUND",
        "FREE",
        "FULLTEXTTABLE",
        "FUSION",
        "GENERAL",
        "GET",
        "GLOBAL",
        "GO",
        "GROUPING",
        "HOLD",
        "HOST",
        "HOUR",
        "IGNORE",
        "IMMEDIATE",
        "INDICATOR",
        "INITIALIZE",
        "INITIALLY",
        "INOUT",
        "INPUT",
        "INT",
        "INTEGER",
        "INTERSECTION",
        "INTERVAL",
        "ISOLATION",
        "ITERATE",
        "LANGUAGE",
        "LARGE",
        "LAST",
        "LATERAL",
        "LEADING",
        "LESS",
        "LEVEL",
        "LIKE_REGEX",
        "LIMIT",
        "LN",
        "LOCAL",
        "LOCALTIME",
        "LOCALTIMESTAMP",
        "LOCATOR",
        "MAP",
        "MATCH",
        "MEMBER",
        "METHOD",
        "MINUTE",
        "MOD",
        "MODIFIES",
        "MODIFY",
        "MODULE",
        "MONTH",
        "MULTISET",
        "NAMES",
        "NATURAL",
        "NCHAR",
        "NCLOB",
        "NEW",
        "NEXT",
        "NO",
        "NONE",
        "NORMALIZE",
        "NUMERIC",
        "OBJECT",
        "OCCURRENCES_REGEX",
        "OLD",
        "ONLY",
        "OPERATION",
        "ORDINALITY",
        "OUT",
        "OUTPUT",
        "OVERLAY",
        "PAD",
        "PARAMETER",
        "PARAMETERS",
        "PARTIAL",
        "PARTITION",
        "PATH",
        "PERCENT_RANK",
        "PERCENTILE_CONT",
        "PERCENTILE_DISC",
        "POSITION",
        "POSITION_REGEX",
        "POSTFIX",
        "PREFIX",
        "PREORDER",
        "PREPARE",
        "PRESERVE",
        "PRIOR",
        "PRIVILEGES",
        "RANGE",
        "READS",
        "REAL",
        "RECURSIVE",
        "REF",
        "REFERENCING",
        "REGR_AVGX",
        "REGR_AVGY",
        "REGR_COUNT",
        "REGR_INTERCEPT",
        "REGR_R2",
        "REGR_SLOPE",
        "REGR_SXX",
        "REGR_SXY",
        "REGR_SYY",
        "RELATIVE",
        "RELEASE",
        "RESULT",
        "RETURNS",
        "ROLE",
        "ROLLUP",
        "ROUTINE",
        "ROW",
        "ROWS",
        "SAVEPOINT",
        "SCOPE",
        "SCROLL",
        "SEARCH",
        "SECOND",
        "SECTION",
        "SENSITIVE",
        "SEQUENCE",
        "SESSION",
        "SETS",
        "SIMILAR",
        "SIZE",
        "SMALLINT",
        "SPACE",
        "SPECIFIC",
        "SPECIFICTYPE",
        "SQL",
        "SQLEXCEPTION",
        "SQLSTATE",
        "SQLWARNING",
        "START",
        "STATE",
        "STATEMENT",
        "STATIC",
        "STDDEV_POP",
        "STDDEV_SAMP",
        "STRUCTURE",
        "SUBMULTISET",
        "SUBSTRING_REGEX",
        "SYMMETRIC",
        "SYSTEM",
        "TEMPORARY",
        "TERMINATE",
        "THAN",
        "TIME",
        "TIMESTAMP",
        "TIMEZONE_HOUR",
        "TIMEZONE_MINUTE",
        "TRAILING",
        "TRANSLATE",
        "TRANSLATE_REGEX",
        "TRANSLATION",
        "TREAT",
        "TRUE",
        "UESCAPE",
        "UNDER",
        "UNKNOWN",
        "UNNEST",
        "USAGE",
        "USING",
        // "VALUE", // Commented out to allow "value" as identifier in T-SQL alias equals syntax
        "VAR_POP",
        "VAR_SAMP",
        "VARCHAR",
        "VARIABLE",
        "VARYING",
        "WHEN",
        "WHENEVER",
        "WIDTH_BUCKET",
        "WINDOW",
        "WITHIN",
        "WITHOUT",
        "WORK",
        "WRITE",
        "XMLAGG",
        "XMLATTRIBUTES",
        "XMLBINARY",
        "XMLCAST",
        "XMLCOMMENT",
        "XMLCONCAT",
        "XMLDOCUMENT",
        "XMLELEMENT",
        "XMLEXISTS",
        "XMLFOREST",
        "XMLITERATE",
        "XMLNAMESPACES",
        "XMLPARSE",
        "XMLPI",
        "XMLQUERY",
        "XMLSERIALIZE",
        "XMLTABLE",
        "XMLTEXT",
        "XMLVALIDATE",
        "YEAR",
        "ZONE",
    ]
    .into_iter()
    .collect()
}

/// T-SQL unreserved keywords
/// These are keywords that can be used as identifiers without quoting
/// T-SQL additional unreserved keywords (to be added to ANSI keywords)
pub(crate) fn tsql_additional_unreserved_keywords() -> HashSet<&'static str> {
    [
        // T-SQL SET options that can be used as identifiers
        "NOCOUNT",
        "XACT_ABORT",
        "QUOTED_IDENTIFIER",
        "ANSI_NULLS",
        "ANSI_PADDING",
        "ANSI_WARNINGS",
        "ARITHABORT",
        "CONCAT_NULL_YIELDS_NULL",
        "NUMERIC_ROUNDABORT",
        "DEADLOCK_PRIORITY",
        "DATEFIRST",
        "DATEFORMAT",
        "DELAYED_DURABILITY",
        // Function names that can be used as identifiers
        "NEWID",
        // T-SQL priority and format values
        "LOW",
        "NORMAL",
        "HIGH",
        "MDY",
        "DMY",
        "YMD",
        "YDM",
        "MYD",
        "DYM",
        // Transaction isolation levels
        "SERIALIZABLE",
        "SNAPSHOT",
        "ISOLATION",
        "LEVEL",
        // Azure Synapse Analytics keywords that can be identifiers
        "DISTRIBUTION",
        "ROUND_ROBIN",
        "REPLICATE",
        "HASH",
        "HEAP",
        "COLUMNSTORE",
        "PARTITION",
        "RANGE",
        // Common T-SQL keywords that can be used as identifiers
        "ATOMIC",
        // Procedure parameter modifiers
        "READONLY",
        // CREATE PROCEDURE WITH clause options
        "ENCRYPTION",
        "RECOMPILE",
        "NATIVE_COMPILATION",
        "SCHEMABINDING",
        "CALLER",
        "OWNER",
    ]
    .into_iter()
    .collect()
}

/// Complete T-SQL reserved keywords (ANSI + T-SQL specific) - for backwards compatibility
#[allow(dead_code)]
pub(crate) fn tsql_reserved_keywords() -> HashSet<&'static str> {
    // Combine ANSI keywords with T-SQL specific reserved keywords
    ANSI_RESERVED_KEYWORDS
        .lines()
        .chain(ANSI_UNRESERVED_KEYWORDS.lines())
        .chain(tsql_additional_reserved_keywords())
        .collect()
}

/// Complete T-SQL unreserved keywords - for backwards compatibility
#[allow(dead_code)]
pub(crate) fn tsql_unreserved_keywords() -> HashSet<&'static str> {
    tsql_additional_unreserved_keywords()
}
