#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TokenKind {
    Eof,
    Identifier,
    String,
    DoubleQuotedString,
    QuotedString,
    ByteString,
    Integer,
    Decimal,
    Parameter,
    LParen,
    RParen,
    LBracket,
    RBracket,
    LBrace,
    RBrace,
    Comma,
    Colon,
    Semicolon,
    Dot,
    Plus,
    Minus,
    Question,
    Star,
    Slash,
    Percent,
    Pipe,
    DoublePipe,
    Ampersand,
    Tilde,
    Eq,
    Bang,
    Neq,
    Lt,
    Le,
    Gt,
    Ge,
    DoubleColon,
    ArrowRight,
    ArrowLeft,
    Match,
    Optional,
    Where,
    Filter,
    Let,
    For,
    ParameterKeyword,
    Parameters,
    Characteristics,
    In,
    Between,
    Call,
    Yield,
    Next,
    Select,
    Return,
    Distinct,
    All,
    As,
    With,
    Group,
    Groups,
    Having,
    Keep,
    Order,
    By,
    Asc,
    Ascending,
    Desc,
    Descending,
    Nulls,
    First,
    Last,
    Limit,
    Offset,
    Skip,
    Insert,
    Create,
    Delete,
    Set,
    Remove,
    Detach,
    Nodetach,
    Property,
    Graph,
    Schema,
    Type,
    Node,
    Vertex,
    Edge,
    Relationship,
    Relationships,
    From,
    To,
    Connecting,
    If,
    Not,
    Exists,
    Drop,
    Use,
    At,
    Reset,
    Close,
    Session,
    Start,
    Transaction,
    Read,
    Write,
    Only,
    Isolation,
    Level,
    Serializable,
    Repeatable,
    Committed,
    Uncommitted,
    List,
    Array,
    Record,
    Date,
    Time,
    Zone,
    Datetime,
    Timestamp,
    Interval,
    Duration,
    DurationBetween,
    CurrentDate,
    CurrentTime,
    CurrentTimestamp,
    CurrentUser,
    CurrentRole,
    Localtimestamp,
    ZonedTime,
    ZonedDatetime,
    LocalTime,
    LocalDatetime,
    Avg,
    Count,
    Max,
    Min,
    Sum,
    CollectList,
    StddevSamp,
    StddevPop,
    PercentileCont,
    PercentileDisc,
    Abs,
    Mod,
    Floor,
    Ceil,
    Ceiling,
    Sqrt,
    Power,
    Log,
    Log10,
    Ln,
    Exp,
    Sin,
    Cos,
    Tan,
    Cot,
    Sinh,
    Cosh,
    Tanh,
    Asin,
    Acos,
    Atan,
    Degrees,
    Radians,
    Case,
    Coalesce,
    Nullif,
    Cast,
    When,
    Then,
    Else,
    End,
    PropertyExists,
    ElementId,
    Same,
    AllDifferent,
    Overlay,
    Placing,
    Position,
    Substring,
    Left,
    Right,
    Trim,
    Btrim,
    Ltrim,
    Rtrim,
    Upper,
    Lower,
    Normalize,
    CharLength,
    CharacterLength,
    ByteLength,
    OctetLength,
    PathLength,
    Leading,
    Trailing,
    Both,
    Source,
    Destination,
    Of,
    Normalized,
    Directed,
    Undirected,
    Labeled,
    Label,
    Labels,
    Commit,
    Rollback,
    Replace,
    Like,
    Escape,
    Copy,
    Current,
    CurrentGraph,
    CurrentPropertyGraph,
    CurrentSchema,
    HomeGraph,
    HomePropertyGraph,
    HomeSchema,
    And,
    Or,
    Xor,
    Is,
    Typed,
    Null,
    True,
    False,
    Unknown,
    Value,
    Variable,
    Union,
    Except,
    Intersect,
    Otherwise,
    Ordinality,
    Finish,
    No,
    Binding,
    Bindings,
    Table,
    Temp,
    Different,
    Element,
    Elements,
    Edges,
    Any,
    Shortest,
    Walk,
    Trail,
    Simple,
    Acyclic,
    Path,
    Paths,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Token {
    pub kind: TokenKind,
    pub text: String,
    pub offset: usize,
}

impl Token {
    pub fn new(kind: TokenKind, text: impl Into<String>, offset: usize) -> Self {
        Self {
            kind,
            text: text.into(),
            offset,
        }
    }
}

pub(crate) fn keyword_or_identifier(text: &str) -> TokenKind {
    match text.to_ascii_uppercase().as_str() {
        "MATCH" => TokenKind::Match,
        "OPTIONAL" => TokenKind::Optional,
        "WHERE" => TokenKind::Where,
        "FILTER" => TokenKind::Filter,
        "LET" => TokenKind::Let,
        "FOR" => TokenKind::For,
        "PARAMETER" => TokenKind::ParameterKeyword,
        "PARAMETERS" => TokenKind::Parameters,
        "CHARACTERISTICS" => TokenKind::Characteristics,
        "IN" => TokenKind::In,
        "BETWEEN" => TokenKind::Between,
        "CALL" => TokenKind::Call,
        "YIELD" => TokenKind::Yield,
        "NEXT" => TokenKind::Next,
        "SELECT" => TokenKind::Select,
        "RETURN" => TokenKind::Return,
        "DISTINCT" => TokenKind::Distinct,
        "ALL" => TokenKind::All,
        "AS" => TokenKind::As,
        "WITH" => TokenKind::With,
        "GROUP" => TokenKind::Group,
        "GROUPS" => TokenKind::Groups,
        "HAVING" => TokenKind::Having,
        "KEEP" => TokenKind::Keep,
        "ORDER" => TokenKind::Order,
        "BY" => TokenKind::By,
        "ASC" => TokenKind::Asc,
        "ASCENDING" => TokenKind::Ascending,
        "DESC" => TokenKind::Desc,
        "DESCENDING" => TokenKind::Descending,
        "NULLS" => TokenKind::Nulls,
        "FIRST" => TokenKind::First,
        "LAST" => TokenKind::Last,
        "LIMIT" => TokenKind::Limit,
        "OFFSET" => TokenKind::Offset,
        "SKIP" => TokenKind::Skip,
        "INSERT" => TokenKind::Insert,
        "CREATE" => TokenKind::Create,
        "DELETE" => TokenKind::Delete,
        "SET" => TokenKind::Set,
        "REMOVE" => TokenKind::Remove,
        "DETACH" => TokenKind::Detach,
        "NODETACH" => TokenKind::Nodetach,
        "PROPERTY" => TokenKind::Property,
        "GRAPH" => TokenKind::Graph,
        "SCHEMA" => TokenKind::Schema,
        "TYPE" => TokenKind::Type,
        "NODE" => TokenKind::Node,
        "VERTEX" => TokenKind::Vertex,
        "EDGE" => TokenKind::Edge,
        "RELATIONSHIP" => TokenKind::Relationship,
        "RELATIONSHIPS" => TokenKind::Relationships,
        "FROM" => TokenKind::From,
        "TO" => TokenKind::To,
        "CONNECTING" => TokenKind::Connecting,
        "IF" => TokenKind::If,
        "NOT" => TokenKind::Not,
        "EXISTS" => TokenKind::Exists,
        "DROP" => TokenKind::Drop,
        "USE" => TokenKind::Use,
        "AT" => TokenKind::At,
        "RESET" => TokenKind::Reset,
        "CLOSE" => TokenKind::Close,
        "SESSION" => TokenKind::Session,
        "START" => TokenKind::Start,
        "TRANSACTION" => TokenKind::Transaction,
        "READ" => TokenKind::Read,
        "WRITE" => TokenKind::Write,
        "ONLY" => TokenKind::Only,
        "ISOLATION" => TokenKind::Isolation,
        "LEVEL" => TokenKind::Level,
        "SERIALIZABLE" => TokenKind::Serializable,
        "REPEATABLE" => TokenKind::Repeatable,
        "COMMITTED" => TokenKind::Committed,
        "UNCOMMITTED" => TokenKind::Uncommitted,
        "LIST" => TokenKind::List,
        "ARRAY" => TokenKind::Array,
        "RECORD" => TokenKind::Record,
        "DATE" => TokenKind::Date,
        "TIME" => TokenKind::Time,
        "ZONE" => TokenKind::Zone,
        "DATETIME" => TokenKind::Datetime,
        "TIMESTAMP" => TokenKind::Timestamp,
        "INTERVAL" => TokenKind::Interval,
        "DURATION" => TokenKind::Duration,
        "DURATION_BETWEEN" => TokenKind::DurationBetween,
        "CURRENT_DATE" => TokenKind::CurrentDate,
        "CURRENT_TIME" => TokenKind::CurrentTime,
        "CURRENT_TIMESTAMP" => TokenKind::CurrentTimestamp,
        "CURRENT_USER" => TokenKind::CurrentUser,
        "CURRENT_ROLE" => TokenKind::CurrentRole,
        "ZONED_TIME" => TokenKind::ZonedTime,
        "ZONED_DATETIME" => TokenKind::ZonedDatetime,
        "LOCAL_TIME" => TokenKind::LocalTime,
        "LOCAL_TIMESTAMP" => TokenKind::Localtimestamp,
        "LOCAL_DATETIME" => TokenKind::LocalDatetime,
        "AVG" => TokenKind::Avg,
        "COUNT" => TokenKind::Count,
        "MAX" => TokenKind::Max,
        "MIN" => TokenKind::Min,
        "SUM" => TokenKind::Sum,
        "COLLECT_LIST" => TokenKind::CollectList,
        "STDDEV_SAMP" => TokenKind::StddevSamp,
        "STDDEV_POP" => TokenKind::StddevPop,
        "PERCENTILE_CONT" => TokenKind::PercentileCont,
        "PERCENTILE_DISC" => TokenKind::PercentileDisc,
        "ABS" => TokenKind::Abs,
        "MOD" => TokenKind::Mod,
        "FLOOR" => TokenKind::Floor,
        "CEIL" => TokenKind::Ceil,
        "CEILING" => TokenKind::Ceiling,
        "SQRT" => TokenKind::Sqrt,
        "POWER" => TokenKind::Power,
        "LOG" => TokenKind::Log,
        "LOG10" => TokenKind::Log10,
        "LN" => TokenKind::Ln,
        "EXP" => TokenKind::Exp,
        "SIN" => TokenKind::Sin,
        "COS" => TokenKind::Cos,
        "TAN" => TokenKind::Tan,
        "COT" => TokenKind::Cot,
        "SINH" => TokenKind::Sinh,
        "COSH" => TokenKind::Cosh,
        "TANH" => TokenKind::Tanh,
        "ASIN" => TokenKind::Asin,
        "ACOS" => TokenKind::Acos,
        "ATAN" => TokenKind::Atan,
        "DEGREES" => TokenKind::Degrees,
        "RADIANS" => TokenKind::Radians,
        "CASE" => TokenKind::Case,
        "COALESCE" => TokenKind::Coalesce,
        "NULLIF" => TokenKind::Nullif,
        "CAST" => TokenKind::Cast,
        "WHEN" => TokenKind::When,
        "THEN" => TokenKind::Then,
        "ELSE" => TokenKind::Else,
        "END" => TokenKind::End,
        "PROPERTY_EXISTS" => TokenKind::PropertyExists,
        "ELEMENT_ID" => TokenKind::ElementId,
        "SAME" => TokenKind::Same,
        "ALL_DIFFERENT" => TokenKind::AllDifferent,
        "OVERLAY" => TokenKind::Overlay,
        "PLACING" => TokenKind::Placing,
        "POSITION" => TokenKind::Position,
        "SUBSTRING" => TokenKind::Substring,
        "LEFT" => TokenKind::Left,
        "RIGHT" => TokenKind::Right,
        "TRIM" => TokenKind::Trim,
        "BTRIM" => TokenKind::Btrim,
        "LTRIM" => TokenKind::Ltrim,
        "RTRIM" => TokenKind::Rtrim,
        "UPPER" => TokenKind::Upper,
        "LOWER" => TokenKind::Lower,
        "NORMALIZE" => TokenKind::Normalize,
        "CHAR_LENGTH" => TokenKind::CharLength,
        "CHARACTER_LENGTH" => TokenKind::CharacterLength,
        "BYTE_LENGTH" => TokenKind::ByteLength,
        "OCTET_LENGTH" => TokenKind::OctetLength,
        "PATH_LENGTH" => TokenKind::PathLength,
        "LEADING" => TokenKind::Leading,
        "TRAILING" => TokenKind::Trailing,
        "BOTH" => TokenKind::Both,
        "SOURCE" => TokenKind::Source,
        "DESTINATION" => TokenKind::Destination,
        "OF" => TokenKind::Of,
        "NORMALIZED" => TokenKind::Normalized,
        "DIRECTED" => TokenKind::Directed,
        "UNDIRECTED" => TokenKind::Undirected,
        "LABELED" => TokenKind::Labeled,
        "LABEL" => TokenKind::Label,
        "LABELS" => TokenKind::Labels,
        "COMMIT" => TokenKind::Commit,
        "ROLLBACK" => TokenKind::Rollback,
        "REPLACE" => TokenKind::Replace,
        "LIKE" => TokenKind::Like,
        "ESCAPE" => TokenKind::Escape,
        "COPY" => TokenKind::Copy,
        "CURRENT" => TokenKind::Current,
        "CURRENT_GRAPH" => TokenKind::CurrentGraph,
        "CURRENT_PROPERTY_GRAPH" => TokenKind::CurrentPropertyGraph,
        "CURRENT_SCHEMA" => TokenKind::CurrentSchema,
        "HOME_GRAPH" => TokenKind::HomeGraph,
        "HOME_PROPERTY_GRAPH" => TokenKind::HomePropertyGraph,
        "HOME_SCHEMA" => TokenKind::HomeSchema,
        "AND" => TokenKind::And,
        "OR" => TokenKind::Or,
        "XOR" => TokenKind::Xor,
        "IS" => TokenKind::Is,
        "TYPED" => TokenKind::Typed,
        "NULL" => TokenKind::Null,
        "TRUE" => TokenKind::True,
        "FALSE" => TokenKind::False,
        "UNKNOWN" => TokenKind::Unknown,
        "VALUE" => TokenKind::Value,
        "VARIABLE" => TokenKind::Variable,
        "UNION" => TokenKind::Union,
        "EXCEPT" => TokenKind::Except,
        "INTERSECT" => TokenKind::Intersect,
        "OTHERWISE" => TokenKind::Otherwise,
        "ORDINALITY" => TokenKind::Ordinality,
        "FINISH" => TokenKind::Finish,
        "NO" => TokenKind::No,
        "BINDING" => TokenKind::Binding,
        "BINDINGS" => TokenKind::Bindings,
        "TABLE" => TokenKind::Table,
        "TEMP" => TokenKind::Temp,
        "DIFFERENT" => TokenKind::Different,
        "ELEMENT" => TokenKind::Element,
        "ELEMENTS" => TokenKind::Elements,
        "EDGES" => TokenKind::Edges,
        "ANY" => TokenKind::Any,
        "SHORTEST" => TokenKind::Shortest,
        "WALK" => TokenKind::Walk,
        "TRAIL" => TokenKind::Trail,
        "SIMPLE" => TokenKind::Simple,
        "ACYCLIC" => TokenKind::Acyclic,
        "PATH" => TokenKind::Path,
        "PATHS" => TokenKind::Paths,
        _ => TokenKind::Identifier,
    }
}
