package parser

import (
	"encoding/hex"
	"fmt"
	"strings"
)

// Node is the interface for all AST nodes
type Node interface {
	// String returns a string representation of the node
	String() string
	// Position returns the position of the node
	Position() Position
}

// Statement is the interface for all CQL statements
type Statement interface {
	Node
	statementNode()
}

// Expression is the interface for all expressions
type Expression interface {
	Node
	expressionNode()
}

// Literal is the interface for all literal values
type Literal interface {
	Expression
	literalNode()
}

type OrderByClause struct {
	Token     Position
	Column    string
	Direction string // ASC or DESC
}

func (o *OrderByClause) String() string {
	if o.Direction != "" {
		return fmt.Sprintf("%s %s", o.Column, o.Direction)
	}
	return o.Column
}

// QueryOptions represents common query options
type QueryOptions struct {
	Limit             Expression
	PerPartitionLimit Expression
	Offset            Expression
	OrderBy           []*OrderByClause
	AllowFiltering    bool
}

// SelectStatement represents a SELECT statement
type SelectStatement struct {
	Token    Position
	JSON     bool
	Distinct bool
	Columns  []Expression
	From     *TableName
	Where    Expression
	GroupBy  []Expression
	Having   Expression
	Options  QueryOptions
	// IndexHint is an internal hint for SQL translation (not part of CQL syntax).
	IndexHint string
}

func (s *SelectStatement) String() string {
	var distinct string
	if s.Distinct {
		distinct = "DISTINCT "
	}
	return fmt.Sprintf("SELECT %s%s FROM %s", distinct, s.Columns, s.From)
}

func (s *SelectStatement) statementNode()     {}
func (s *SelectStatement) Position() Position { return s.Token }

// InsertStatement represents an INSERT statement
type InsertStatement struct {
	Token       Position
	Table       *TableName
	Columns     []string
	Values      [][]Expression
	JSON        bool
	JSONValue   Expression
	IfNotExists bool
	TTL         Expression
	Timestamp   Expression
	// OnDuplicateIncrementColumns is an internal hint for SQL translation.
	// When present, listed columns should use additive ON DUPLICATE semantics.
	OnDuplicateIncrementColumns map[string]struct{}
}

func (i *InsertStatement) String() string {
	return fmt.Sprintf("INSERT INTO %s VALUES ...", i.Table)
}

func (i *InsertStatement) statementNode()     {}
func (i *InsertStatement) Position() Position { return i.Token }

// UpdateStatement represents an UPDATE statement
type UpdateStatement struct {
	Token       Position
	Table       *TableName
	Assigments  []*Assignment
	Where       Expression
	IfExists    bool
	IfCondition Expression
	TTL         Expression
	Timestamp   Expression
}

func (u *UpdateStatement) String() string {
	return fmt.Sprintf("UPDATE %s SET ...", u.Table)
}

func (u *UpdateStatement) statementNode()     {}
func (u *UpdateStatement) Position() Position { return u.Token }

// DeleteStatement represents a DELETE statement
type DeleteStatement struct {
	Token       Position
	Columns     []string
	Targets     []Expression
	From        *TableName
	Where       Expression
	IfExists    bool
	IfCondition Expression
	Timestamp   Expression
}

func (d *DeleteStatement) String() string {
	return fmt.Sprintf("DELETE FROM %s WHERE ...", d.From)
}

func (d *DeleteStatement) statementNode()     {}
func (d *DeleteStatement) Position() Position { return d.Token }

// CreateKeyspaceStatement represents CREATE KEYSPACE
type CreateKeyspaceStatement struct {
	Token       Position
	IfNotExists bool
	Name        string
	Replication map[string]interface{}
}

func (c *CreateKeyspaceStatement) String() string {
	return fmt.Sprintf("CREATE KEYSPACE %s", c.Name)
}

func (c *CreateKeyspaceStatement) statementNode()     {}
func (c *CreateKeyspaceStatement) Position() Position { return c.Token }

// CreateTableStatement represents CREATE TABLE
type CreateTableStatement struct {
	Token           Position
	IfNotExists     bool
	Name            *TableName
	Columns         []*ColumnDefinition
	PrimaryKey      *PrimaryKey
	ClusteringOrder map[string]string
	Options         map[string]interface{}
}

func (c *CreateTableStatement) String() string {
	return fmt.Sprintf("CREATE TABLE %s", c.Name)
}

func (c *CreateTableStatement) statementNode()     {}
func (c *CreateTableStatement) Position() Position { return c.Token }

// CreateTableLikeStatement represents CREATE TABLE ... LIKE ...
type CreateTableLikeStatement struct {
	Token           Position
	IfNotExists     bool
	Name            *TableName
	Source          *TableName
	ClusteringOrder map[string]string
	Options         map[string]interface{}
	WithIndexes     bool
}

func (c *CreateTableLikeStatement) String() string {
	return fmt.Sprintf("CREATE TABLE %s LIKE %s", c.Name, c.Source)
}

func (c *CreateTableLikeStatement) statementNode()     {}
func (c *CreateTableLikeStatement) Position() Position { return c.Token }

// DropTableStatement represents DROP TABLE
type DropTableStatement struct {
	Token    Position
	IfExists bool
	Name     *TableName
}

func (d *DropTableStatement) String() string {
	return fmt.Sprintf("DROP TABLE %s", d.Name)
}

func (d *DropTableStatement) statementNode()     {}
func (d *DropTableStatement) Position() Position { return d.Token }

// CreateIndexStatement represents CREATE INDEX
type CreateIndexStatement struct {
	Token       Position
	Name        string
	Table       *TableName
	Columns     []string
	IfNotExists bool
	Custom      bool
	UsingClass  string
	Options     map[string]interface{}
}

func (c *CreateIndexStatement) String() string {
	columns := ""
	if len(c.Columns) > 0 {
		columns = " (" + strings.Join(c.Columns, ", ") + ")"
	}
	return fmt.Sprintf("CREATE INDEX %s ON %s%s", c.Name, c.Table, columns)
}

func (c *CreateIndexStatement) statementNode()     {}
func (c *CreateIndexStatement) Position() Position { return c.Token }

// DropIndexStatement represents DROP INDEX
type DropIndexStatement struct {
	Token    Position
	IfExists bool
	Name     string
}

func (d *DropIndexStatement) String() string {
	return fmt.Sprintf("DROP INDEX %s", d.Name)
}

func (d *DropIndexStatement) statementNode()     {}
func (d *DropIndexStatement) Position() Position { return d.Token }

// DropKeyspaceStatement represents DROP KEYSPACE
type DropKeyspaceStatement struct {
	Token    Position
	IfExists bool
	Name     string
}

func (d *DropKeyspaceStatement) String() string {
	return fmt.Sprintf("DROP KEYSPACE %s", d.Name)
}

func (d *DropKeyspaceStatement) statementNode()     {}
func (d *DropKeyspaceStatement) Position() Position { return d.Token }

// CreateUserStatement represents CREATE USER.
type CreateUserStatement struct {
	Token       Position
	IfNotExists bool
	Name        string
	Password    string
	HasPassword bool
	Superuser   *bool
}

func (c *CreateUserStatement) String() string {
	return fmt.Sprintf("CREATE USER %s", c.Name)
}

func (c *CreateUserStatement) statementNode()     {}
func (c *CreateUserStatement) Position() Position { return c.Token }

// AlterUserStatement represents ALTER USER.
type AlterUserStatement struct {
	Token     Position
	IfExists  bool
	Name      string
	Password  *string
	Superuser *bool
}

func (a *AlterUserStatement) String() string {
	return fmt.Sprintf("ALTER USER %s", a.Name)
}

func (a *AlterUserStatement) statementNode()     {}
func (a *AlterUserStatement) Position() Position { return a.Token }

// DropUserStatement represents DROP USER.
type DropUserStatement struct {
	Token    Position
	IfExists bool
	Name     string
}

func (d *DropUserStatement) String() string {
	return fmt.Sprintf("DROP USER %s", d.Name)
}

func (d *DropUserStatement) statementNode()     {}
func (d *DropUserStatement) Position() Position { return d.Token }

// ListUsersStatement represents LIST USERS.
type ListUsersStatement struct {
	Token Position
}

func (l *ListUsersStatement) String() string {
	return "LIST USERS"
}

func (l *ListUsersStatement) statementNode()     {}
func (l *ListUsersStatement) Position() Position { return l.Token }

// GrantStatement represents GRANT <permission> ON KEYSPACE <keyspace> TO <role>.
type GrantStatement struct {
	Token       Position
	Permissions []string
	Resource    string
	Keyspace    string
	Role        string
}

func (g *GrantStatement) String() string {
	return fmt.Sprintf("GRANT %s ON %s %s TO %s", strings.Join(g.Permissions, ", "), g.Resource, g.Keyspace, g.Role)
}

func (g *GrantStatement) statementNode()     {}
func (g *GrantStatement) Position() Position { return g.Token }

// UseStatement represents USE <keyspace>
type UseStatement struct {
	Token    Position
	Keyspace string
}

func (u *UseStatement) String() string {
	return fmt.Sprintf("USE %s", u.Keyspace)
}

func (u *UseStatement) statementNode()     {}
func (u *UseStatement) Position() Position { return u.Token }

// DescribeTarget indicates what a DESCRIBE statement is targeting.
type DescribeTarget string

const (
	DescribeTargetKeyspaces DescribeTarget = "KEYSPACES"
	DescribeTargetKeyspace  DescribeTarget = "KEYSPACE"
	DescribeTargetTables    DescribeTarget = "TABLES"
	DescribeTargetTable     DescribeTarget = "TABLE"
)

// DescribeStatement represents DESCRIBE/DESC commands mapped to system_schema.
type DescribeStatement struct {
	Token    Position
	Target   DescribeTarget
	Keyspace string
	Table    *TableName
}

func (d *DescribeStatement) String() string {
	switch d.Target {
	case DescribeTargetKeyspaces:
		return "DESCRIBE KEYSPACES"
	case DescribeTargetKeyspace:
		if d.Keyspace != "" {
			return fmt.Sprintf("DESCRIBE KEYSPACE %s", d.Keyspace)
		}
		return "DESCRIBE KEYSPACE"
	case DescribeTargetTables:
		if d.Keyspace != "" {
			return fmt.Sprintf("DESCRIBE TABLES IN %s", d.Keyspace)
		}
		return "DESCRIBE TABLES"
	case DescribeTargetTable:
		if d.Table != nil {
			return fmt.Sprintf("DESCRIBE TABLE %s", d.Table)
		}
		return "DESCRIBE TABLE"
	default:
		return "DESCRIBE"
	}
}

func (d *DescribeStatement) statementNode()     {}
func (d *DescribeStatement) Position() Position { return d.Token }

// AlterTableStatement represents ALTER TABLE
type AlterTableStatement struct {
	Token          Position
	Table          *TableName
	Operation      string
	IfExists       bool
	ColumnIfExists bool
	IfNotExists    bool
	Column         string
	Type           Type
	Renames        []RenamePair
	Options        map[string]interface{}
}

func (a *AlterTableStatement) String() string {
	return fmt.Sprintf("ALTER TABLE %s", a.Table)
}

func (a *AlterTableStatement) statementNode()     {}
func (a *AlterTableStatement) Position() Position { return a.Token }

// AlterKeyspaceStatement represents ALTER KEYSPACE
type AlterKeyspaceStatement struct {
	Token   Position
	Name    string
	Options map[string]interface{}
}

func (a *AlterKeyspaceStatement) String() string {
	return fmt.Sprintf("ALTER KEYSPACE %s", a.Name)
}

func (a *AlterKeyspaceStatement) statementNode()     {}
func (a *AlterKeyspaceStatement) Position() Position { return a.Token }

// CreateTypeStatement represents CREATE TYPE
type CreateTypeStatement struct {
	Token       Position
	IfNotExists bool
	Name        *TableName
	Fields      []*TypeField
}

func (c *CreateTypeStatement) String() string {
	return fmt.Sprintf("CREATE TYPE %s", c.Name)
}

func (c *CreateTypeStatement) statementNode()     {}
func (c *CreateTypeStatement) Position() Position { return c.Token }

// AlterTypeStatement represents ALTER TYPE
type AlterTypeStatement struct {
	Token         Position
	IfExists      bool
	Name          *TableName
	Operation     string
	IfNotExists   bool
	FieldIfExists bool
	Field         string
	Type          Type
	Renames       []RenamePair
}

func (a *AlterTypeStatement) String() string {
	return fmt.Sprintf("ALTER TYPE %s", a.Name)
}

func (a *AlterTypeStatement) statementNode()     {}
func (a *AlterTypeStatement) Position() Position { return a.Token }

// DropTypeStatement represents DROP TYPE
type DropTypeStatement struct {
	Token    Position
	IfExists bool
	Name     *TableName
}

func (d *DropTypeStatement) String() string {
	return fmt.Sprintf("DROP TYPE %s", d.Name)
}

func (d *DropTypeStatement) statementNode()     {}
func (d *DropTypeStatement) Position() Position { return d.Token }

// CreateMaterializedViewStatement represents CREATE MATERIALIZED VIEW
type CreateMaterializedViewStatement struct {
	Token           Position
	IfNotExists     bool
	Name            *TableName
	Select          *SelectStatement
	PrimaryKey      *PrimaryKey
	ClusteringOrder map[string]string
	Options         map[string]interface{}
}

func (c *CreateMaterializedViewStatement) String() string {
	return fmt.Sprintf("CREATE MATERIALIZED VIEW %s", c.Name)
}

func (c *CreateMaterializedViewStatement) statementNode()     {}
func (c *CreateMaterializedViewStatement) Position() Position { return c.Token }

// AlterMaterializedViewStatement represents ALTER MATERIALIZED VIEW
type AlterMaterializedViewStatement struct {
	Token   Position
	Name    *TableName
	Options map[string]interface{}
}

func (a *AlterMaterializedViewStatement) String() string {
	return fmt.Sprintf("ALTER MATERIALIZED VIEW %s", a.Name)
}

func (a *AlterMaterializedViewStatement) statementNode()     {}
func (a *AlterMaterializedViewStatement) Position() Position { return a.Token }

// DropMaterializedViewStatement represents DROP MATERIALIZED VIEW
type DropMaterializedViewStatement struct {
	Token    Position
	IfExists bool
	Name     *TableName
}

func (d *DropMaterializedViewStatement) String() string {
	return fmt.Sprintf("DROP MATERIALIZED VIEW %s", d.Name)
}

func (d *DropMaterializedViewStatement) statementNode()     {}
func (d *DropMaterializedViewStatement) Position() Position { return d.Token }

// CreateTriggerStatement represents CREATE TRIGGER
type CreateTriggerStatement struct {
	Token Position
	Name  string
	Table *TableName
	Using string
}

func (c *CreateTriggerStatement) String() string {
	return fmt.Sprintf("CREATE TRIGGER %s ON %s", c.Name, c.Table)
}

func (c *CreateTriggerStatement) statementNode()     {}
func (c *CreateTriggerStatement) Position() Position { return c.Token }

// DropTriggerStatement represents DROP TRIGGER
type DropTriggerStatement struct {
	Token Position
	Name  string
	Table *TableName
}

func (d *DropTriggerStatement) String() string {
	return fmt.Sprintf("DROP TRIGGER %s ON %s", d.Name, d.Table)
}

func (d *DropTriggerStatement) statementNode()     {}
func (d *DropTriggerStatement) Position() Position { return d.Token }

// CreateFunctionStatement represents CREATE FUNCTION
type CreateFunctionStatement struct {
	Token        Position
	OrReplace    bool
	IfNotExists  bool
	Name         *TableName
	Args         []FunctionArg
	CalledOnNull bool
	ReturnType   Type
	Language     string
	Body         string
}

func (c *CreateFunctionStatement) String() string {
	return fmt.Sprintf("CREATE FUNCTION %s", c.Name)
}

func (c *CreateFunctionStatement) statementNode()     {}
func (c *CreateFunctionStatement) Position() Position { return c.Token }

// DropFunctionStatement represents DROP FUNCTION
type DropFunctionStatement struct {
	Token    Position
	IfExists bool
	Name     *TableName
	ArgTypes []Type
}

func (d *DropFunctionStatement) String() string {
	return fmt.Sprintf("DROP FUNCTION %s", d.Name)
}

func (d *DropFunctionStatement) statementNode()     {}
func (d *DropFunctionStatement) Position() Position { return d.Token }

// CreateAggregateStatement represents CREATE AGGREGATE
type CreateAggregateStatement struct {
	Token       Position
	OrReplace   bool
	IfNotExists bool
	Name        *TableName
	ArgTypes    []Type
	StateFunc   *TableName
	StateType   Type
	FinalFunc   *TableName
	InitCond    Expression
}

func (c *CreateAggregateStatement) String() string {
	return fmt.Sprintf("CREATE AGGREGATE %s", c.Name)
}

func (c *CreateAggregateStatement) statementNode()     {}
func (c *CreateAggregateStatement) Position() Position { return c.Token }

// DropAggregateStatement represents DROP AGGREGATE
type DropAggregateStatement struct {
	Token    Position
	IfExists bool
	Name     *TableName
	ArgTypes []Type
}

func (d *DropAggregateStatement) String() string {
	return fmt.Sprintf("DROP AGGREGATE %s", d.Name)
}

func (d *DropAggregateStatement) statementNode()     {}
func (d *DropAggregateStatement) Position() Position { return d.Token }

// TruncateStatement represents TRUNCATE
type TruncateStatement struct {
	Token Position
	Table *TableName
}

func (t *TruncateStatement) String() string {
	return fmt.Sprintf("TRUNCATE %s", t.Table)
}

func (t *TruncateStatement) statementNode()     {}
func (t *TruncateStatement) Position() Position { return t.Token }

// BatchStatement represents BEGIN BATCH ... APPLY BATCH
type BatchStatement struct {
	Token     Position
	BatchType string
	Using     Expression
	Entries   []Statement
}

func (b *BatchStatement) String() string {
	return "BEGIN BATCH"
}

func (b *BatchStatement) statementNode()     {}
func (b *BatchStatement) Position() Position { return b.Token }

// TableName represents a table reference
type TableName struct {
	Schema string // Optional keyspace name
	Name   string
	Token  Position
}

func (t *TableName) String() string {
	if t.Schema != "" {
		return fmt.Sprintf("%s.%s", t.Schema, t.Name)
	}
	return t.Name
}

func (t *TableName) Position() Position { return t.Token }

// ColumnDefinition defines a column
type ColumnDefinition struct {
	Name         string
	Type         Type // Will be defined in types.go
	Primary      bool
	Clustering   bool
	Static       bool
	HasDefault   bool
	DefaultExpr  Expression
	HasOnUpdate  bool
	OnUpdateExpr Expression
	Token        Position
}

func (c *ColumnDefinition) String() string {
	parts := []string{fmt.Sprintf("%s %s", c.Name, c.Type)}
	if c.HasDefault && c.DefaultExpr != nil {
		parts = append(parts, fmt.Sprintf("DEFAULT %s", c.DefaultExpr.String()))
	}
	if c.HasOnUpdate && c.OnUpdateExpr != nil {
		parts = append(parts, fmt.Sprintf("ON UPDATE %s", c.OnUpdateExpr.String()))
	}
	if c.Static {
		parts = append(parts, "STATIC")
	}
	if c.Primary {
		parts = append(parts, "PRIMARY KEY")
	}
	return strings.Join(parts, " ")
}

func (c *ColumnDefinition) Position() Position { return c.Token }

// TypeField defines a field in a user-defined type.
type TypeField struct {
	Name  string
	Type  Type
	Token Position
}

// FunctionArg defines an argument in a UDF signature.
type FunctionArg struct {
	Name string
	Type Type
}

// PrimaryKey defines the primary key
type PrimaryKey struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

// RenamePair represents a rename from one identifier to another.
type RenamePair struct {
	From string
	To   string
}

// Assignment represents a SET clause assignment
type Assignment struct {
	Target Expression // ColumnExpr or CollectionAccessExpr
	Column string
	Value  Expression
	Op     string // =, +=, -= (for collections)
}

// BinaryExpr represents a binary expression
type BinaryExpr struct {
	Token Position
	Op    string
	Left  Expression
	Right Expression
}

func (b *BinaryExpr) String() string {
	return fmt.Sprintf("(%s %s %s)", b.Left, b.Op, b.Right)
}

func (b *BinaryExpr) expressionNode()    {}
func (b *BinaryExpr) Position() Position { return b.Token }

// UnaryExpr represents a unary expression
type UnaryExpr struct {
	Token Position
	Op    string
	Expr  Expression
}

func (u *UnaryExpr) String() string {
	return fmt.Sprintf("%s%s", u.Op, u.Expr)
}

func (u *UnaryExpr) expressionNode()    {}
func (u *UnaryExpr) Position() Position { return u.Token }

// IsNullExpr represents expr IS NULL / IS NOT NULL.
type IsNullExpr struct {
	Token Position
	Expr  Expression
	Not   bool
}

func (i *IsNullExpr) String() string {
	if i.Not {
		return fmt.Sprintf("%s IS NOT NULL", i.Expr.String())
	}
	return fmt.Sprintf("%s IS NULL", i.Expr.String())
}

func (i *IsNullExpr) expressionNode()    {}
func (i *IsNullExpr) Position() Position { return i.Token }

// ColumnExpr represents a column reference
type ColumnExpr struct {
	Token Position
	Table string // Optional table alias
	Name  string
}

func (c *ColumnExpr) String() string {
	if c.Table != "" {
		return fmt.Sprintf("%s.%s", c.Table, c.Name)
	}
	return c.Name
}

func (c *ColumnExpr) expressionNode()    {}
func (c *ColumnExpr) Position() Position { return c.Token }

// StarExpr represents a wildcard (*)
type StarExpr struct {
	Token Position
	Table string // Optional table name prefix
}

func (s *StarExpr) String() string {
	if s.Table != "" {
		return fmt.Sprintf("%s.*", s.Table)
	}
	return "*"
}

func (s *StarExpr) expressionNode()    {}
func (s *StarExpr) Position() Position { return s.Token }

// BindMarker represents a prepared statement bind marker (?).
type BindMarker struct {
	Token Position
}

func (b *BindMarker) String() string {
	return "?"
}

func (b *BindMarker) expressionNode()    {}
func (b *BindMarker) Position() Position { return b.Token }

// NamedBindMarker represents a named bind marker (:name).
type NamedBindMarker struct {
	Token Position
	Name  string
}

func (n *NamedBindMarker) String() string {
	return ":" + n.Name
}

func (n *NamedBindMarker) expressionNode()    {}
func (n *NamedBindMarker) Position() Position { return n.Token }

// NullLiteral represents a NULL literal.
type NullLiteral struct {
	Token Position
}

func (n *NullLiteral) String() string {
	return "NULL"
}

func (n *NullLiteral) expressionNode()    {}
func (n *NullLiteral) literalNode()       {}
func (n *NullLiteral) Position() Position { return n.Token }

// StringLiteral represents a string literal
type StringLiteral struct {
	Token Position
	Value string
}

func (s *StringLiteral) String() string {
	return fmt.Sprintf("'%s'", s.Value)
}

func (s *StringLiteral) expressionNode()    {}
func (s *StringLiteral) literalNode()       {}
func (s *StringLiteral) Position() Position { return s.Token }

// IntegerLiteral represents an integer literal
type IntegerLiteral struct {
	Token Position
	Value int64
}

func (i *IntegerLiteral) String() string {
	return fmt.Sprintf("%d", i.Value)
}

func (i *IntegerLiteral) expressionNode()    {}
func (i *IntegerLiteral) literalNode()       {}
func (i *IntegerLiteral) Position() Position { return i.Token }

// FloatLiteral represents a float literal
type FloatLiteral struct {
	Token Position
	Value float64
	Raw   string
}

func (f *FloatLiteral) String() string {
	if f.Raw != "" {
		return f.Raw
	}
	return fmt.Sprintf("%f", f.Value)
}

func (f *FloatLiteral) expressionNode()    {}
func (f *FloatLiteral) literalNode()       {}
func (f *FloatLiteral) Position() Position { return f.Token }

// BooleanLiteral represents a boolean literal
type BooleanLiteral struct {
	Token Position
	Value string // "true" or "false"
}

func (b *BooleanLiteral) String() string {
	return b.Value
}

func (b *BooleanLiteral) expressionNode()    {}
func (b *BooleanLiteral) literalNode()       {}
func (b *BooleanLiteral) Position() Position { return b.Token }

// UUIDLiteral represents a UUID literal
type UUIDLiteral struct {
	Token Position
	Value string
}

func (u *UUIDLiteral) String() string {
	return u.Value
}

func (u *UUIDLiteral) expressionNode()    {}
func (u *UUIDLiteral) literalNode()       {}
func (u *UUIDLiteral) Position() Position { return u.Token }

// BlobLiteral represents a blob literal.
type BlobLiteral struct {
	Token Position
	Value []byte
}

func (b *BlobLiteral) String() string {
	return "0x" + hex.EncodeToString(b.Value)
}

func (b *BlobLiteral) expressionNode()    {}
func (b *BlobLiteral) literalNode()       {}
func (b *BlobLiteral) Position() Position { return b.Token }

// ListLiteral represents a list literal.
type ListLiteral struct {
	Token    Position
	Elements []Expression
}

func (l *ListLiteral) String() string {
	parts := make([]string, len(l.Elements))
	for i, el := range l.Elements {
		parts[i] = el.String()
	}
	return fmt.Sprintf("[%s]", joinStrings(parts, ", "))
}

func (l *ListLiteral) expressionNode()    {}
func (l *ListLiteral) literalNode()       {}
func (l *ListLiteral) Position() Position { return l.Token }

// VectorLiteral represents a vector literal.
type VectorLiteral struct {
	Token    Position
	Elements []Expression
}

func (v *VectorLiteral) String() string {
	parts := make([]string, len(v.Elements))
	for i, el := range v.Elements {
		parts[i] = el.String()
	}
	return fmt.Sprintf("[%s]", joinStrings(parts, ", "))
}

func (v *VectorLiteral) expressionNode()    {}
func (v *VectorLiteral) literalNode()       {}
func (v *VectorLiteral) Position() Position { return v.Token }

// SetLiteral represents a set literal.
type SetLiteral struct {
	Token    Position
	Elements []Expression
}

func (s *SetLiteral) String() string {
	parts := make([]string, len(s.Elements))
	for i, el := range s.Elements {
		parts[i] = el.String()
	}
	return fmt.Sprintf("{%s}", joinStrings(parts, ", "))
}

func (s *SetLiteral) expressionNode()    {}
func (s *SetLiteral) literalNode()       {}
func (s *SetLiteral) Position() Position { return s.Token }

// MapEntry represents a map entry.
type MapEntry struct {
	Key   Expression
	Value Expression
}

// MapLiteral represents a map literal.
type MapLiteral struct {
	Token   Position
	Entries []MapEntry
}

func (m *MapLiteral) String() string {
	parts := make([]string, len(m.Entries))
	for i, entry := range m.Entries {
		parts[i] = fmt.Sprintf("%s: %s", entry.Key.String(), entry.Value.String())
	}
	return fmt.Sprintf("{%s}", joinStrings(parts, ", "))
}

func (m *MapLiteral) expressionNode()    {}
func (m *MapLiteral) literalNode()       {}
func (m *MapLiteral) Position() Position { return m.Token }

// TupleLiteral represents a tuple literal.
type TupleLiteral struct {
	Token    Position
	Elements []Expression
}

func (t *TupleLiteral) String() string {
	parts := make([]string, len(t.Elements))
	for i, el := range t.Elements {
		parts[i] = el.String()
	}
	return fmt.Sprintf("(%s)", joinStrings(parts, ", "))
}

func (t *TupleLiteral) expressionNode()    {}
func (t *TupleLiteral) literalNode()       {}
func (t *TupleLiteral) Position() Position { return t.Token }

// CollectionAccessExpr represents access to a collection element or slice.
type CollectionAccessExpr struct {
	Token  Position
	Target Expression
	Start  Expression
	End    Expression
	Slice  bool
}

func (c *CollectionAccessExpr) String() string {
	if c.Slice {
		start := ""
		end := ""
		if c.Start != nil {
			start = c.Start.String()
		}
		if c.End != nil {
			end = c.End.String()
		}
		return fmt.Sprintf("%s[%s:%s]", c.Target.String(), start, end)
	}
	return fmt.Sprintf("%s[%s]", c.Target.String(), c.Start.String())
}

func (c *CollectionAccessExpr) expressionNode()    {}
func (c *CollectionAccessExpr) Position() Position { return c.Token }

// AliasedExpr represents an expression with an alias.
type AliasedExpr struct {
	Token Position
	Expr  Expression
	Alias string
}

func (a *AliasedExpr) String() string {
	return fmt.Sprintf("%s AS %s", a.Expr.String(), a.Alias)
}

func (a *AliasedExpr) expressionNode()    {}
func (a *AliasedExpr) Position() Position { return a.Token }

// CastExpr represents CAST(expr AS type).
type CastExpr struct {
	Token Position
	Expr  Expression
	Type  Type
}

func (c *CastExpr) String() string {
	return fmt.Sprintf("CAST(%s AS %s)", c.Expr.String(), c.Type.TypeString())
}

func (c *CastExpr) expressionNode()    {}
func (c *CastExpr) Position() Position { return c.Token }

// TypeHintExpr represents term::type.
type TypeHintExpr struct {
	Token Position
	Expr  Expression
	Type  Type
}

func (t *TypeHintExpr) String() string {
	return fmt.Sprintf("%s::%s", t.Expr.String(), t.Type.TypeString())
}

func (t *TypeHintExpr) expressionNode()    {}
func (t *TypeHintExpr) Position() Position { return t.Token }

// Type interface for CQL types
type Type interface {
	TypeString() string
}

// SimpleType represents a simple CQL type
type SimpleType struct {
	Name string
}

func (s *SimpleType) TypeString() string {
	return s.Name
}

// CollectionType represents a collection type
type CollectionType struct {
	Kind      string // list, set, map
	Type      Type   // element type for list/set, key type for map
	ValueType Type   // value type for map
}

func (c *CollectionType) TypeString() string {
	switch c.Kind {
	case "list":
		return fmt.Sprintf("list<%s>", c.Type.TypeString())
	case "set":
		return fmt.Sprintf("set<%s>", c.Type.TypeString())
	case "map":
		return fmt.Sprintf("map<%s, %s>", c.Type.TypeString(), c.ValueType.TypeString())
	}
	return c.Kind
}

// TupleType represents a tuple type
type TupleType struct {
	Types []Type
}

func (t *TupleType) TypeString() string {
	parts := make([]string, len(t.Types))
	for i, typ := range t.Types {
		parts[i] = typ.TypeString()
	}
	return fmt.Sprintf("tuple<%s>", joinStrings(parts, ", "))
}

// VectorType represents a vector type.
type VectorType struct {
	ElemType Type
	Size     int
}

func (v *VectorType) TypeString() string {
	if v == nil || v.ElemType == nil {
		return "vector<text, 0>"
	}
	return fmt.Sprintf("vector<%s, %d>", v.ElemType.TypeString(), v.Size)
}
