; Phase 1 — dag model + structural content addressing.

; ---- content-id determinism ----

(artdag-test
  "same spec -> same id"
  (equal?
    (artdag/content-id (artdag/node "blur" (list "i1") {:r 3}))
    (artdag/content-id (artdag/node "blur" (list "i1") {:r 3})))
  true)

(artdag-test
  "op affects id"
  (equal?
    (artdag/content-id (artdag/node "blur" (list "i1") {}))
    (artdag/content-id (artdag/node "sharpen" (list "i1") {})))
  false)

(artdag-test
  "params affect id"
  (equal?
    (artdag/content-id (artdag/node "blur" (list "i1") {:r 3}))
    (artdag/content-id (artdag/node "blur" (list "i1") {:r 5})))
  false)

(artdag-test
  "inputs affect id"
  (equal?
    (artdag/content-id (artdag/node "add" (list "i1") {}))
    (artdag/content-id (artdag/node "add" (list "i2") {})))
  false)

(artdag-test
  "param key order does not affect id"
  (equal?
    (artdag/content-id (artdag/node "op" (list) {:a 1 :b 2}))
    (artdag/content-id (artdag/node "op" (list) {:a 1 :b 2})))
  true)

; ---- commutativity ----

(artdag-test
  "commutative op: input order ignored"
  (equal?
    (artdag/content-id (artdag/cnode "add" (list "i1" "i2") {}))
    (artdag/content-id (artdag/cnode "add" (list "i2" "i1") {})))
  true)

(artdag-test
  "non-commutative op: input order matters"
  (equal?
    (artdag/content-id (artdag/node "sub" (list "i1" "i2") {}))
    (artdag/content-id (artdag/node "sub" (list "i2" "i1") {})))
  false)

; ---- build: success ----

(artdag-test
  "build ok for valid dag"
  (get
    (artdag/build
      (list
        (list "a" "load" (list) {})
        (list "b" "load" (list) {:s 1})
        (list "c" "add" (list "a" "b") {})))
    :ok)
  true)

(artdag-test
  "node-count counts distinct nodes"
  (artdag/node-count
    (artdag/build
      (list
        (list "a" "load" (list) {})
        (list "b" "load" (list) {:s 1})
        (list "c" "add" (list "a" "b") {}))))
  3)

; ---- subgraph sharing ----

(artdag-test
  "identical leaves dedup to one node"
  (artdag/node-count
    (artdag/build
      (list
        (list "a" "load" (list) {:s 1})
        (list "b" "load" (list) {:s 1})
        (list "c" "add" (list "a" "b") {}))))
  2)

(artdag-test
  "duplicate names map to same id"
  (let
    ((d (artdag/build (list (list "a" "load" (list) {:s 1}) (list "b" "load" (list) {:s 1})))))
    (equal? (artdag/dag-id d "a") (artdag/dag-id d "b")))
  true)

(artdag-test
  "identical subgraph shares id across dags"
  (let
    ((d1 (artdag/build (list (list "x" "load" (list) {:s 7}) (list "y" "neg" (list "x") {}))))
      (d2
        (artdag/build
          (list
            (list "p" "load" (list) {:s 7})
            (list "q" "neg" (list "p") {})))))
    (equal? (artdag/dag-id d1 "y") (artdag/dag-id d2 "q")))
  true)

; ---- validation ----

(artdag-test
  "cycle rejected"
  (get
    (artdag/build
      (list
        (list "a" "f" (list "b") {})
        (list "b" "g" (list "a") {})))
    :error)
  "cycle")

(artdag-test
  "self-cycle rejected"
  (get (artdag/build (list (list "a" "f" (list "a") {}))) :error)
  "cycle")

(artdag-test
  "dangling input rejected"
  (get
    (artdag/build (list (list "a" "f" (list "ghost") {})))
    :error)
  "dangling")

(artdag-test
  "dangling refs reported"
  (get
    (artdag/build (list (list "a" "f" (list "ghost") {})))
    :refs)
  (list "ghost"))

; ---- topological order ----

(artdag-test
  "topo order: deps before dependents"
  (let
    ((d (artdag/build (list (list "c" "add" (list "a" "b") {}) (list "a" "load" (list) {:s 1}) (list "b" "load" (list) {:s 2})))))
    (artdag/dag-order d))
  (let
    ((d (artdag/build (list (list "c" "add" (list "a" "b") {}) (list "a" "load" (list) {:s 1}) (list "b" "load" (list) {:s 2})))))
    (list (artdag/dag-id d "a") (artdag/dag-id d "b") (artdag/dag-id d "c"))))

(artdag-test
  "topo order: deep chain"
  (let
    ((d (artdag/build (list (list "d" "f" (list "c") {}) (list "c" "f" (list "b") {}) (list "b" "f" (list "a") {}) (list "a" "load" (list) {})))))
    (artdag/dag-order d))
  (let
    ((d (artdag/build (list (list "d" "f" (list "c") {}) (list "c" "f" (list "b") {}) (list "b" "f" (list "a") {}) (list "a" "load" (list) {})))))
    (list
      (artdag/dag-id d "a")
      (artdag/dag-id d "b")
      (artdag/dag-id d "c")
      (artdag/dag-id d "d"))))

; ---- accessors ----

(artdag-test
  "dag-node-by-name returns node spec"
  (artdag/node-op
    (artdag/dag-node-by-name
      (artdag/build (list (list "a" "load" (list) {})))
      "a"))
  "load")

(artdag-test
  "resolved inputs are content-ids"
  (let
    ((d (artdag/build (list (list "a" "load" (list) {}) (list "b" "neg" (list "a") {})))))
    (artdag/node-inputs (artdag/dag-node-by-name d "b")))
  (let
    ((d (artdag/build (list (list "a" "load" (list) {}) (list "b" "neg" (list "a") {})))))
    (list (artdag/dag-id d "a"))))
