## BaraQL AST — Abstract Syntax Tree nodes
import ../core/types

type
  NodeKind* = enum
    # Statements
    nkSelect
    nkInsert
    nkUpdate
    nkDelete
    nkMerge
    nkCreateType
    nkDropType
    nkAlterType
    nkCreateTable
    nkDropTable
    nkAlterTable
    nkCreateIndex
    nkDropIndex
    nkBeginTxn
    nkCommitTxn
    nkRollbackTxn
    nkExplainStmt
    nkRecoverToTimestamp
    nkCreateView
    nkDropView
    nkCreateTrigger
    nkDropTrigger
    nkCreateMigration
    nkApplyMigration
    nkMigrationStatus
    nkMigrationUp
    nkMigrationDown
    nkImportFrom
    nkExportTo
    nkMigrationDryRun
    nkCreateUser
    nkDropUser
    nkCreatePolicy
    nkDropPolicy
    nkEnableRLS
    nkDisableRLS
    nkGrant
    nkRevoke
    nkSetVar
    nkCreateGraph
    nkDropGraph
    nkCreateDatabase
    nkDropDatabase
    nkUseDatabase
    nkShowDatabases
    nkShowTables

    # Clauses
    nkFrom
    nkWhere
    nkOrderBy
    nkGroupBy
    nkHaving
    nkLimit
    nkOffset
    nkReturning
    nkWith

    # Expressions
    nkBinOp
    nkUnaryOp
    nkJsonPath      # column->'key' or column->>'key'
    nkFuncCall
    nkTypeCast
    nkPath
    nkIdent
    nkIntLit
    nkFloatLit
    nkStringLit
    nkBoolLit
    nkNullLit
    nkArrayLit
    nkVectorLit
    nkObjectLit
    nkIfElse
    nkCase
    nkSubquery
    nkExists
    nkInExpr
    nkBetweenExpr
    nkLikeExpr
    nkIsExpr
    nkStar
    nkPlaceholder
    nkCurrentUser
    nkCurrentRole

    # Graph-specific
    nkGraphTraversal
    nkBfsQuery
    nkDfsQuery
    nkShortestPath
    nkPatternMatch

    # Vector-specific
    nkVectorSimilar
    nkVectorNearest

    # Pivot
    nkPivot
    nkUnpivot

    # Set operations
    nkSetOp

    # Join
    nkJoin

    # Type definitions / DDL
    nkPropertyDef
    nkLinkDef
    nkIndexDef
    nkColumnDef
    nkConstraintDef

    # Window functions
    nkWindowExpr
    nkOverClause
    nkFrameSpec
    nkFrameBoundary

    # Top-level
    nkStatementList

  BinOpKind* = enum
    bkAdd = "+"
    bkSub = "-"
    bkMul = "*"
    bkDiv = "/"
    bkMod = "%"
    bkPow = "**"
    bkFloorDiv = "//"
    bkEq = "="
    bkNotEq = "!="
    bkLt = "<"
    bkLtEq = "<="
    bkGt = ">"
    bkGtEq = ">="
    bkAnd = "AND"
    bkOr = "OR"
    bkIn = "IN"
    bkNotIn = "NOT IN"
    bkLike = "LIKE"
    bkILike = "ILIKE"
    bkConcat = "++"
    bkCoalesce = "??"
    bkAssign = ":="
    bkArrow = "=>"
    bkJsonPath = "->"
    bkJsonPathText = "->>"
    bkFtsMatch = "@@"
    bkDistance = "<->"
    bkJsonContains = "@>"
    bkJsonContainedBy = "<@"
    bkJsonHasAny = "?|"
    bkJsonHasAll = "?&"

  UnaryOpKind* = enum
    ukNeg = "-"
    ukNot = "NOT"
    ukIsNull = "IS NULL"
    ukIsNotNull = "IS NOT NULL"

  JoinKind* = enum
    jkInner
    jkLeft
    jkRight
    jkFull
    jkCross

  SetOpKind* = enum
    sdkUnion
    sdkIntersect
    sdkExcept

  GroupingSetsKind* = enum
    gskNone
    gskGroupingSets
    gskRollup
    gskCube

  SortDir* = enum
    sdAsc
    sdDesc

  Node* = ref object
    line*: int
    col*: int
    exprAlias*: string
    case kind*: NodeKind
    of nkSelect:
      selDistinct*: bool
      selWith*: seq[(string, Node, bool)]
      selResult*: seq[Node]
      selFrom*: Node
      selJoins*: seq[Node]
      selWhere*: Node
      selGroupBy*: seq[Node]
      selGroupingSetsKind*: GroupingSetsKind
      selGroupingSets*: seq[seq[Node]]
      selHaving*: Node
      selOrderBy*: seq[Node]
      selLimit*: Node
      selOffset*: Node
    of nkInsert:
      insTarget*: string
      insFields*: seq[Node]
      insValues*: seq[Node]
      insReturning*: seq[Node]
      insConflict*: Node
    of nkUpdate:
      updTarget*: string
      updAlias*: string
      updSet*: seq[Node]
      updWhere*: Node
      updReturning*: seq[Node]
    of nkDelete:
      delTarget*: string
      delAlias*: string
      delWhere*: Node
      delReturning*: seq[Node]
    of nkMerge:
      mergeTarget*: string
      mergeTargetAlias*: string
      mergeSource*: Node
      mergeSourceAlias*: string
      mergeOn*: Node
      mergeMatchedUpdate*: seq[Node]  # SET assignments, empty if no UPDATE
      mergeMatchedDelete*: bool       # WHEN MATCHED THEN DELETE
      mergeMatchedCondition*: Node    # optional AND <condition> after MATCHED
      mergeNotMatchedInsert*: seq[Node]  # column list for INSERT
      mergeNotMatchedValues*: seq[Node]  # value expressions for INSERT
      mergeNotMatchedNothing*: bool   # WHEN NOT MATCHED THEN DO NOTHING
    of nkCreateType:
      ctName*: string
      ctBases*: seq[string]
      ctProperties*: seq[Node]
      ctLinks*: seq[Node]
    of nkDropType:
      dtName*: string
    of nkAlterType:
      atName*: string
      atOps*: seq[Node]
    of nkCreateTable:
      crtName*: string
      crtColumns*: seq[Node]
      crtConstraints*: seq[Node]
      crtIfNotExists*: bool
    of nkDropTable:
      drtName*: string
      drtIfExists*: bool
    of nkAlterTable:
      altName*: string
      altOps*: seq[Node]
    of nkColumnDef:
      cdName*: string
      cdType*: string
      cdConstraints*: seq[Node]
      cdAutoIncrement*: bool
    of nkConstraintDef:
      cstName*: string
      cstType*: string
      cstExpr*: Node
      cstColumns*: seq[string]
      cstRefTable*: string
      cstRefColumns*: seq[string]
      cstOnDelete*: string
      cstOnUpdate*: string
      cstCheck*: Node
      cstDefault*: Node
    of nkBeginTxn:
      btxnMode*: string
    of nkCommitTxn:
      ctxnChain*: bool
    of nkRollbackTxn:
      rtxnChain*: bool
    of nkExplainStmt:
      expStmt*: Node
      expAnalyze*: bool
    of nkRecoverToTimestamp:
      recoverTimestamp*: string
    of nkCreateView:
      cvName*: string
      cvQuery*: Node
      cvOrReplace*: bool
    of nkDropView:
      dvName*: string
      dvIfExists*: bool
    of nkCreateTrigger:
      trigName*: string
      trigTable*: string
      trigTiming*: string  # BEFORE, AFTER, INSTEAD OF
      trigEvent*: string   # INSERT, UPDATE, DELETE
      trigAction*: Node    # SQL statement to execute
    of nkDropTrigger:
      trigDropName*: string
      trigDropIfExists*: bool
    of nkCreateMigration:
      cmName*: string
      cmBody*: string      # UP migration body (SQL string)
      cmDownBody*: string  # DOWN migration body (SQL string)
      cmChecksum*: string  # SHA256 of cmBody
      cmAuthor*: string
      cmTimestamp*: int64
    of nkCreateUser:
      cuName*: string
      cuPassword*: string
      cuSuperuser*: bool
    of nkDropUser:
      duName*: string
      duIfExists*: bool
    of nkCreatePolicy:
      cpName*: string
      cpTable*: string
      cpCommand*: string   # ALL, SELECT, INSERT, UPDATE, DELETE
      cpUsing*: Node       # USING expression
      cpWithCheck*: Node   # WITH CHECK expression
    of nkDropPolicy:
      dpName*: string
      dpTable*: string
      dpIfExists*: bool
    of nkEnableRLS:
      erlsTable*: string
    of nkDisableRLS:
      drlsTable*: string
    of nkGrant:
      grPrivilege*: string  # SELECT, INSERT, UPDATE, DELETE, ALL
      grTable*: string
      grGrantee*: string    # user, role, or PUBLIC
    of nkRevoke:
      rvPrivilege*: string
      rvTable*: string
      rvGrantee*: string
    of nkSetVar:
      svName*: string
      svValue*: string
    of nkCreateGraph:
      cgName*: string
      cgIfNotExists*: bool
    of nkDropGraph:
      dgName*: string
      dgIfExists*: bool
    of nkCreateDatabase:
      cdDbName*: string
      cdIfNotExists*: bool
    of nkDropDatabase:
      ddDbName*: string
      ddIfExists*: bool
    of nkUseDatabase:
      udDbName*: string
    of nkShowDatabases:
      discard
    of nkShowTables:
      stTableName*: string  # empty = list tables; non-empty = describe table
    of nkApplyMigration:
      amName*: string
    of nkMigrationStatus:
      discard  # no fields needed
    of nkMigrationUp:
      muCount*: int  # 0 = all, N = apply N pending migrations
    of nkMigrationDown:
      mdCount*: int  # 0 = 1, N = rollback N migrations
    of nkMigrationDryRun:
      mdrName*: string  # migration name to dry-run
    of nkImportFrom:
      impPath*: string
      impTable*: string
      impFormat*: string  # "csv", "json", "ndjson"
      impDelimiter*: char
      impHasHeader*: bool
      impBatchSize*: int
    of nkExportTo:
      expPath*: string
      expTable*: string
      expFormat*: string
      expDelimiter*: char
      expIncludeHeader*: bool
    of nkCreateIndex:
      ciTarget*: string
      ciName*: string
      ciColumns*: seq[string]
      ciExpr*: Node
      ciKind*: IndexKind
    of nkDropIndex:
      diName*: string
    of nkFrom:
      fromTable*: string
      fromAlias*: string
      fromSubquery*: Node
    of nkWhere:
      whereExpr*: Node
    of nkOrderBy:
      orderByExpr*: Node
      orderByDir*: SortDir
    of nkGroupBy:
      groupExprs*: seq[Node]
    of nkHaving:
      havingExpr*: Node
    of nkLimit:
      limitExpr*: Node
    of nkOffset:
      offsetExpr*: Node
    of nkReturning:
      retExprs*: seq[Node]
    of nkWith:
      withBindings*: seq[(string, Node, bool)]
    of nkBinOp:
      binOp*: BinOpKind
      binLeft*: Node
      binRight*: Node
    of nkUnaryOp:
      unOp*: UnaryOpKind
      unOperand*: Node
    of nkJsonPath:
      jpLeft*: Node
      jpKey*: string
      jpAsText*: bool   # true for ->>, false for ->
    of nkFuncCall:
      funcName*: string
      funcArgs*: seq[Node]
      funcFilter*: Node
      funcDistinct*: bool
    of nkTypeCast:
      castType*: string
      castExpr*: Node
    of nkPath:
      pathParts*: seq[string]
    of nkIdent:
      identName*: string
    of nkIntLit:
      intVal*: int64
    of nkFloatLit:
      floatVal*: float64
    of nkStringLit:
      strVal*: string
    of nkBoolLit:
      boolVal*: bool
    of nkNullLit:
      discard
    of nkArrayLit:
      arrayElems*: seq[Node]
    of nkVectorLit:
      vecElems*: seq[Node]
    of nkObjectLit:
      objFields*: seq[(string, Node)]
    of nkIfElse:
      ifCond*: Node
      ifThen*: Node
      ifElse*: Node
    of nkCase:
      caseExpr*: Node
      caseWhens*: seq[(Node, Node)]
      caseElse*: Node
    of nkSubquery:
      subQuery*: Node
    of nkExists:
      existsExpr*: Node
    of nkInExpr:
      inLeft*: Node
      inRight*: Node
      inNegated*: bool
    of nkBetweenExpr:
      betweenExpr*: Node
      betweenLow*: Node
      betweenHigh*: Node
      betweenNegated*: bool
    of nkLikeExpr:
      likeExpr*: Node
      likePattern*: Node
      likeCaseInsensitive*: bool
      likeNegated*: bool
    of nkIsExpr:
      isExpr*: Node
      isType*: string
      isNegated*: bool
    of nkGraphTraversal:
      gtGraphName*: string
      gtStart*: Node
      gtEdge*: string
      gtDirection*: string
      gtEnd*: Node
      gtMaxDepth*: int
      gtReturnCols*: seq[string]
      gtAlgo*: string
    of nkBfsQuery:
      bfsStart*: Node
      bfsTarget*: Node
      bfsEdge*: string
      bfsMaxDepth*: int
      bfsFilter*: Node
    of nkDfsQuery:
      dfsStart*: Node
      dfsTarget*: Node
      dfsEdge*: string
      dfsMaxDepth*: int
      dfsFilter*: Node
    of nkShortestPath:
      spStart*: Node
      spEnd*: Node
      spEdge*: string
      spMaxDepth*: int
    of nkPatternMatch:
      pmPattern*: Node
      pmWhere*: Node
    of nkVectorSimilar:
      vsField*: string
      vsVector*: Node
      vsLimit*: int
      vsMetric*: string
    of nkVectorNearest:
      vnField*: string
      vnVector*: Node
      vnLimit*: int
      vnMetric*: string
    of nkPivot:
      pivotSource*: Node
      pivotAgg*: Node
      pivotForCol*: string
      pivotInValues*: seq[string]
    of nkUnpivot:
      unpivotSource*: Node
      unpivotValueCol*: string
      unpivotForCol*: string
      unpivotInCols*: seq[string]
    of nkJoin:
      joinKind*: JoinKind
      joinTarget*: Node
      joinOn*: Node
      joinAlias*: string
      joinLateral*: bool
    of nkSetOp:
      setOpKind*: SetOpKind
      setOpAll*: bool
      setOpLeft*: Node
      setOpRight*: Node
    of nkStar:
      discard
    of nkPlaceholder:
      discard
    of nkCurrentUser:
      discard
    of nkCurrentRole:
      discard
    of nkPropertyDef:
      pdName*: string
      pdType*: string
      pdRequired*: bool
      pdDefault*: Node
      pdComputed*: bool
      pdExpr*: Node
    of nkLinkDef:
      ldName*: string
      ldTarget*: string
      ldCardinality*: Cardinality
      ldRequired*: bool
    of nkIndexDef:
      idName*: string
      idExpr*: Node
      idKind*: IndexKind
    of nkWindowExpr:
      winFunc*: string
      winArgs*: seq[Node]
      winOver*: Node
    of nkOverClause:
      overPartition*: seq[Node]
      overOrderBy*: seq[Node]
      overFrame*: Node
    of nkFrameSpec:
      frameMode*: string        # "ROWS" or "RANGE"
      frameStartType*: string   # "UNBOUNDED PRECEDING", "CURRENT ROW", "EXPR PRECEDING", "EXPR FOLLOWING"
      frameStartExpr*: Node
      frameEndType*: string
      frameEndExpr*: Node
      frameExclude*: string     # "NO OTHERS", "CURRENT ROW", "GROUP", "TIES"
    of nkFrameBoundary:
      fbType*: string           # "UNBOUNDED PRECEDING", "CURRENT ROW", "EXPR PRECEDING", "EXPR FOLLOWING", "UNBOUNDED FOLLOWING"
      fbExpr*: Node
    of nkStatementList:
      stmts*: seq[Node]

proc newNode*(kind: NodeKind, line: int = 0, col: int = 0): Node =
  result = Node(kind: kind, line: line, col: col)
  case kind
  of nkSelect: result.selResult = @[]
  of nkInsert: result.insFields = @[]; result.insValues = @[]
  of nkUpdate: result.updSet = @[]
  of nkDelete: discard
  of nkCreateTable: result.crtColumns = @[]; result.crtConstraints = @[]
  of nkAlterTable: result.altOps = @[]
  of nkColumnDef: result.cdConstraints = @[]
  of nkConstraintDef: result.cstColumns = @[]; result.cstRefColumns = @[]
  of nkWindowExpr: result.winArgs = @[]
  of nkOverClause: result.overPartition = @[]; result.overOrderBy = @[]
  of nkMerge:
    result.mergeMatchedUpdate = @[]
    result.mergeNotMatchedInsert = @[]
    result.mergeNotMatchedValues = @[]
  of nkStatementList: result.stmts = @[]
  else: discard
