## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)

## ----connect-convenience------------------------------------------------------
# library(AstraeaDB)
# 
# client <- astraea_connect()
# # Equivalent to: astraea_connect(host = "127.0.0.1", port = 7687L)

## ----connect-explicit---------------------------------------------------------
# library(AstraeaDB)
# 
# client <- AstraeaClient$new(
#   host       = "127.0.0.1",
#   port       = 7687L,
#   auth_token = "my-secret-token"
# )
# client$connect()

## ----ping---------------------------------------------------------------------
# info <- client$ping()
# info

## ----create-nodes-------------------------------------------------------------
# # Basic node
# alice_id <- client$create_node(
#   labels     = c("Person"),
#   properties = list(name = "Alice", age = 30, city = "San Francisco")
# )
# 
# # Node with multiple labels
# bob_id <- client$create_node(
#   labels     = c("Person", "Engineer"),
#   properties = list(name = "Bob", age = 25, city = "New York")
# )
# 
# # Node with an embedding vector
# carol_id <- client$create_node(
#   labels     = c("Person"),
#   properties = list(name = "Carol", age = 35),
#   embedding  = c(0.12, 0.87, 0.45, 0.33)
# )

## ----get-node-----------------------------------------------------------------
# node <- client$get_node(alice_id)
# 
# node$labels
# #> [1] "Person"
# 
# node$properties$name
# #> [1] "Alice"
# 
# node$properties$age
# #> [1] 30

## ----update-node--------------------------------------------------------------
# # Add a new property; existing name, age, city are kept
# client$update_node(alice_id, list(department = "Research"))
# 
# # Verify
# updated <- client$get_node(alice_id)
# updated$properties$department
# #> [1] "Research"
# 
# updated$properties$city
# #> [1] "San Francisco"

## ----delete-node--------------------------------------------------------------
# temp_id <- client$create_node(
#   labels     = c("Temp"),
#   properties = list(note = "will be deleted")
# )
# client$delete_node(temp_id)

## ----create-edges-------------------------------------------------------------
# # Simple edge
# edge1 <- client$create_edge(
#   source    = alice_id,
#   target    = bob_id,
#   edge_type = "KNOWS",
#   properties = list(context = "work")
# )
# 
# # Weighted edge
# edge2 <- client$create_edge(
#   source    = bob_id,
#   target    = carol_id,
#   edge_type = "FOLLOWS",
#   weight    = 0.7
# )
# 
# # Temporal edge with validity window (milliseconds since epoch)
# # Valid from 2023-01-01 to 2024-01-01
# edge3 <- client$create_edge(
#   source     = alice_id,
#   target     = carol_id,
#   edge_type  = "MENTORS",
#   properties = list(topic = "graph databases"),
#   weight     = 1.0,
#   valid_from = 1672531200000,
#   valid_to   = 1704067200000
# )

## ----edge-read-update---------------------------------------------------------
# # Read
# edge <- client$get_edge(edge1)
# edge$edge_type
# #> [1] "KNOWS"
# edge$properties$context
# #> [1] "work"
# 
# # Update (merge semantics, same as nodes)
# client$update_edge(edge1, list(strength = "strong"))

## ----delete-edge--------------------------------------------------------------
# client$delete_edge(edge2)

## ----neighbors----------------------------------------------------------------
# # Outgoing neighbors (default)
# out <- client$neighbors(alice_id, direction = "outgoing")
# 
# # Incoming neighbors
# inc <- client$neighbors(bob_id, direction = "incoming")
# 
# # Both directions, filtered by edge type
# knows <- client$neighbors(alice_id, direction = "both", edge_type = "KNOWS")

## ----bfs----------------------------------------------------------------------
# bfs_result <- client$bfs(alice_id, max_depth = 2L)
# 
# # Each entry has node_id and depth
# for (entry in bfs_result) {
#   cat(sprintf("Node %d at depth %d\n", entry$node_id, entry$depth))
# }

## ----shortest-path------------------------------------------------------------
# # Unweighted (hop count)
# sp <- client$shortest_path(alice_id, carol_id)
# sp$path    # integer vector of node IDs
# sp$length  # number of hops
# 
# # Weighted (minimizes total edge weight)
# sp_w <- client$shortest_path(alice_id, carol_id, weighted = TRUE)
# sp_w$path
# sp_w$cost  # total weight

## ----gql----------------------------------------------------------------------
# # Find all Person nodes
# result <- client$query("MATCH (p:Person) RETURN p.name, p.age")
# 
# # Filter with WHERE
# result <- client$query(
#   "MATCH (p:Person) WHERE p.age > 25 RETURN p.name, p.city"
# )
# 
# # Edges in the pattern
# result <- client$query(
#   "MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name"
# )
# 
# # Ordering and limiting
# result <- client$query(
#   "MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age LIMIT 10"
# )

## ----batch-create-------------------------------------------------------------
# # Create multiple nodes
# node_ids <- client$create_nodes(list(
#   list(labels = c("City"), properties = list(name = "San Francisco", state = "CA")),
#   list(labels = c("City"), properties = list(name = "New York", state = "NY")),
#   list(labels = c("City"), properties = list(name = "Austin", state = "TX"))
# ))
# 
# # Create multiple edges
# edge_ids <- client$create_edges(list(
#   list(source = alice_id, target = node_ids[1], edge_type = "LIVES_IN"),
#   list(source = bob_id,   target = node_ids[2], edge_type = "LIVES_IN"),
#   list(source = carol_id, target = node_ids[3], edge_type = "LIVES_IN",
#        weight = 0.8)
# ))

## ----batch-delete-------------------------------------------------------------
# # Delete multiple nodes (also removes their edges)
# deleted_count <- client$delete_nodes(node_ids)
# cat(deleted_count, "nodes deleted\n")
# 
# # Delete multiple edges
# deleted_edges <- client$delete_edges(edge_ids)

## ----import-nodes-df----------------------------------------------------------
# people_df <- data.frame(
#   label = c("Person", "Person", "Person"),
#   name  = c("Dave", "Eve", "Frank"),
#   age   = c(40, 28, 55),
#   city  = c("Chicago", "Boston", "Denver"),
#   stringsAsFactors = FALSE
# )
# 
# new_ids <- client$import_nodes_df(people_df, label_col = "label")
# new_ids
# #> [1] 10 11 12

## ----import-nodes-embedding---------------------------------------------------
# embed_df <- data.frame(
#   label = c("Document", "Document"),
#   title = c("Doc A", "Doc B"),
#   e1    = c(0.1, 0.4),
#   e2    = c(0.9, 0.5),
#   e3    = c(0.3, 0.8),
#   stringsAsFactors = FALSE
# )
# 
# doc_ids <- client$import_nodes_df(
#   embed_df,
#   label_col      = "label",
#   embedding_cols = c("e1", "e2", "e3")
# )

## ----import-edges-df----------------------------------------------------------
# edges_df <- data.frame(
#   source = new_ids[c(1, 2)],
#   target = new_ids[c(2, 3)],
#   type   = c("KNOWS", "MENTORS"),
#   since  = c(2018, 2021),
#   stringsAsFactors = FALSE
# )
# 
# edge_ids <- client$import_edges_df(
#   edges_df,
#   source_col = "source",
#   target_col = "target",
#   type_col   = "type"
# )

## ----export-nodes-df----------------------------------------------------------
# df <- client$export_nodes_df(new_ids)
# df
# #>   node_id labels   name age    city
# #> 1      10 Person   Dave  40 Chicago
# #> 2      11 Person    Eve  28  Boston
# #> 3      12 Person  Frank  55  Denver

## ----export-bfs-df------------------------------------------------------------
# bfs_df <- client$export_bfs_df(alice_id, max_depth = 2L)
# bfs_df
# #>   node_id depth labels   name age          city
# #> 1       1     0 Person  Alice  30 San Francisco
# #> 2       2     1 Person    Bob  25      New York
# #> 3       3     2 Person  Carol  35          <NA>

## ----disconnect---------------------------------------------------------------
# client$disconnect()

## ----on-exit------------------------------------------------------------------
# client <- astraea_connect()
# on.exit(client$disconnect(), add = TRUE)
# 
# # ... do work ...

## ----error-handling-----------------------------------------------------------
# tryCatch(
#   {
#     node <- client$get_node(999999L)
#   },
#   error = function(e) {
#     message("Operation failed: ", conditionMessage(e))
#   }
# )

## ----check-available----------------------------------------------------------
# if (astraea_server_available()) {
#   client <- astraea_connect()
#   # ... work ...
#   client$disconnect()
# } else {
#   message("AstraeaDB server is not available.")
# }

