(ns wanijo.infrastructure.repl
  (:require [buddy.hashers :as hashers]
            [wanijo.infrastructure.neo4j :as neo4j]
            [wanijo.main :as main]))

(neo4j/defquery create-user
  "CREATE (n:user)
      SET n.ident = {ident}
      SET n.pw = {pw}
      SET n.uuid = {uuid}")

(defn create-user! [ident pw]
  (neo4j/exec-query!
   create-user
   {:ident ident
    :pw (hashers/derive pw)
    :uuid (neo4j/uuid)}))

(neo4j/defquery merge-config
  "MERGE (c:dbconfig)
      ON CREATE SET
         c.installed_at = {now},
         c.db_version = 0,
         c.last_migration = ''
      ON MATCH SET
         c.last_migration = {now},
         c.db_version = {version}")

(neo4j/defquery config
  "MATCH (c:dbconfig) RETURN c")

(neo4j/defquery ver-0-schema-uuid
  "CREATE CONSTRAINT ON (n:schema)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-0-attribute-uuid
  "CREATE CONSTRAINT ON (n:attribute)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-0-instance-uuid
  "CREATE CONSTRAINT ON (n:instance)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-0-property-uuid
  "CREATE CONSTRAINT ON (n:property)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-0-user-uuid
  "CREATE CONSTRAINT ON (n:user)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-0-link-uuid
  "CREATE CONSTRAINT ON (n:link)
   ASSERT n.uuid IS UNIQUE")

(neo4j/defquery ver-1-tag-name
  "CREATE CONSTRAINT ON (n:tag)
   ASSERT n.name IS UNIQUE")

(neo4j/defquery ver-1-tag-uuid
  "CREATE CONSTRAINT ON (n:tag)
   ASSERT n.uuid IS UNIQUE")

(defn init-version-0 []
  (neo4j/exec-query! ver-0-schema-uuid {})
  (neo4j/exec-query! ver-0-attribute-uuid {})
  (neo4j/exec-query! ver-0-instance-uuid {})
  (neo4j/exec-query! ver-0-property-uuid {})
  (neo4j/exec-query! ver-0-user-uuid {})
  (neo4j/exec-query! ver-0-link-uuid {}))

(defn init-version-1 []
  (neo4j/exec-query! ver-1-tag-name {})
  (neo4j/exec-query! ver-1-tag-uuid {}))

(neo4j/defquery migrate-links
  "MATCH (i1:instance)-[:link_from]-(l:link)-[:link_to]-(i2:instance),
         (l)-[cb:created_by]->(:user)
   MERGE (i1)-[newl:link]->(i2)
   ON CREATE SET
      newl.name = l.name,
      newl.created_at = l.created_at,
      newl.uuid = l.uuid
   DELETE cb, lf, lt, l")

(defn init-version-2 []
  (neo4j/exec-query! migrate-links {}))

(def migrations
  [init-version-0
   init-version-1
   init-version-2])

(defn run-migrations! []
  (neo4j/exec-query! merge-config {:now (neo4j/now-str)
                                   :version (count migrations)})
  (let [version (-> (neo4j/exec-query! config {})
                   first
                   :c
                   :db_version)]
    (println "got version" version "from db," (count migrations) "available")
    (when-let [to-run (nthrest migrations version)]
      (println "running" (count to-run) "migrations")
      (doseq [mig to-run]
        (println "running" mig)
        (mig))))
  (neo4j/exec-query! merge-config {:now (neo4j/now-str)
                                   :version (count migrations)})
  nil)

(defn dev-server! []
  (main/stop-server!)
  (main/start-server-dev!)
  (println "Startet server at http://localhost:8080"))
