;; lib/mod/link.sx — report linking + deduplication.
;;
;; Reports about the same subject form a cluster; identical reports (same
;; reporter + subject + reason) are duplicates. Linking is Prolog-backed: all
;; report facts are loaded and related ids are found by unification — the same
;; relational substrate the policy engine uses, here for retrieval rather than
;; decision. Dedup is pure SX over a normalized link key.

(define
  mod/link-key
  (fn
    (r)
    (str
      (mod/report-by r)
      "|"
      (mod/report-about r)
      "|"
      (downcase (mod/report-reason r)))))

(define
  mod/dedup-reports
  (fn
    (reports)
    (reduce
      (fn
        (acc r)
        (if
          (mod/any? (fn (x) (= (mod/link-key x) (mod/link-key r))) acc)
          acc
          (append acc (list r))))
      (list)
      reports)))

(define
  mod/duplicate-count
  (fn (reports) (- (len reports) (len (mod/dedup-reports reports)))))

;; ── Prolog-backed relational retrieval ──

(define
  mod/report-rel-facts
  (fn
    (reports)
    (mod/join-with
      "\n"
      (map
        (fn
          (r)
          (str
            "report("
            (mod/report-id r)
            ", "
            (mod/pl-quote (mod/report-by r))
            ", "
            (mod/pl-quote (mod/report-about r))
            ")."))
        reports))))

(define
  mod/related-ids
  (fn
    (subject reports)
    (let
      ((db (pl-load (mod/report-rel-facts reports))))
      (map
        (fn (sol) (dict-get sol "Id"))
        (pl-query-all db (str "report(Id, _, " (mod/pl-quote subject) ")"))))))

(define
  mod/reporters-of
  (fn
    (subject reports)
    (let
      ((db (pl-load (mod/report-rel-facts reports))))
      (map
        (fn (sol) (dict-get sol "By"))
        (pl-query-all db (str "report(_, By, " (mod/pl-quote subject) ")"))))))

(define
  mod/distinct
  (fn
    (items)
    (reduce
      (fn
        (acc x)
        (if (mod/any? (fn (y) (= y x)) acc) acc (append acc (list x))))
      (list)
      items)))

(define
  mod/distinct-reporters-of
  (fn (subject reports) (mod/distinct (mod/reporters-of subject reports))))
