(ns wanijo.visualisation.db
  (:require [clojure.spec.alpha :as spec]
            [wanijo.infrastructure.neo4j :as neo4j]
            [wanijo.instance.db :as db-instance]
            [wanijo.instance.domain :as domain-instance]))

(spec/def ::link-name
  (spec/or :not-give nil?
           :given string?))
(spec/def ::links-out
  (spec/coll-of
    (spec/merge ::domain-instance/instance
                (spec/keys :req-un [::link-name]))))
(spec/def ::with-enriched-out-links
  (spec/merge ::domain-instance/instance
              (spec/keys :req-un [::links-out])))

(neo4j/defquery all-instance-connections
  "MATCH
     (source:instance)-[:of]->(schema:schema)
   OPTIONAL MATCH
     (source)-[link:link]->(target:instance),
     (target)-[:of]->(target_schema:schema)
   RETURN source, schema, link, target, target_schema")
(defn all-instance-connections! []
  (neo4j/exec-query! all-instance-connections {}))

(neo4j/defquery search
  "MATCH (i:instance)
   WHERE i.name =~ {term}
   RETURN i
   LIMIT 10")
(defn enrich-links [instance]
  (update instance
          :links-out
          (fn [links-in]
            (map #(assoc
                    (db-instance/full-instance-by-uuid!
                      (-> % :target :uuid))
                    :link-name
                    (-> % :label :name))
                 links-in))))
(defn search! [term]
  {:post [(spec/assert (spec/coll-of ::with-enriched-out-links) %)]}
  (->> (neo4j/exec-query! search {:term (str ".*" term ".*")})
       (map #(db-instance/full-instance-by-uuid! (-> % :i :uuid)))
       (map enrich-links)))

(defn instance! [uuid]
  {:post [(spec/assert ::with-enriched-out-links %)]}
  (enrich-links (db-instance/full-instance-by-uuid! uuid)))
