#!/usr/bin/env nu
# domains/rustelo/commands.nu — CLI dispatch for RusteloApp projects.
# Delegates to ontoref --project-root <rustelo> for domain-level operations.
# publish-contract / probe deliver the content-publisher consumption contract
# (ADR-046 view discipline, ADR-056 verification) to any onboarded RusteloApp.

# Locate the site workspace (dir containing site/content) under a project root.
def site-workspace [root: string]: nothing -> string {
  if ([$root, "site", "content"] | path join | path exists) { $root } else if ([$root, "code", "site", "content"] | path join | path exists) { $"($root)/code" } else { "" }
}

def main [cmd?: string, ...rest: string] {
  let domain_root = (^ontoref project root rustelo | str trim)
  match ($cmd | default "") {
    "layers"  => { with-env { ONTOREF_PROJECT_ROOT: $domain_root } { ^ontoref describe features } },
    "plugins" => { print "  (rustelo plugin registry — not yet implemented)" },
    "routes"  => { print "  (rustelo route manifest — not yet implemented)" },
    "wasm"    => { print "  (rustelo WASM targets — not yet implemented)" },
    "publish-contract" => { publish-contract $domain_root },
    "probe"            => { probe },
    _ => {
      print "  rustelo: layers | plugins | routes | wasm | publish-contract | probe"
      print "    publish-contract  the 6-answer content-publisher contract (+ oracle), from the producer"
      print "    probe             run the end-to-end publish->activate->index oracle in THIS project"
    },
  }
}

# Print the producer-declared content-publisher contract. Resolved from the
# rustelo project root — works from any RusteloApp, no copy.
def publish-contract [domain_root: string] {
  let ncl = $"($domain_root)/domains/rustelo/ontology/publishing-contract.ncl"
  if not ($ncl | path exists) {
    print $"  ✗ contract not found at ($ncl)"
    return
  }
  let res = (do { ^nickel export --import-path ($ncl | path dirname) $ncl } | complete)
  if $res.exit_code != 0 {
    print "  ✗ contract export failed:"
    print $res.stderr
    return
  }
  let c = ($res.stdout | from json)
  print ""
  print $"  (ansi cyan_bold)Rustelo content-publisher contract(ansi reset)  [profile: ($c.profile)]"
  print $"  (ansi green)activate(ansi reset)  ($c.activate_cmd)"
  print $"  (ansi green)serve(ansi reset)     ($c.serve_cmd)"
  print $"  (ansi green)index(ansi reset)     ($c.content_root)"
  for q in $c.questions {
    let tag = if $q.side == "ContentOnly" { $"(ansi green)content-only(ansi reset)" } else { $"(ansi yellow)recompile(ansi reset)" }
    print ""
    print $"  (ansi white_bold)◆ ($q.id)(ansi reset)  [($tag)]"
    print $"    (ansi default_dimmed)Q(ansi reset) ($q.question)"
    print $"    (ansi default_dimmed)A(ansi reset) ($q.answer)"
    print $"    (ansi magenta)oracle(ansi reset) ($q.oracle)"
  }
  let gaps = ($c.known_gaps? | default [])
  if ($gaps | length) > 0 {
    print ""
    print $"  (ansi yellow_bold)Known gaps(ansi reset)  — declared producer-side limitations, plan around them"
    for g in $gaps {
      print $"  (ansi yellow)▲ ($g.id)(ansi reset)  [($g.side)/($g.status)]"
      print $"    (ansi default_dimmed)area(ansi reset)    ($g.area)"
      print $"    (ansi default_dimmed)symptom(ansi reset) ($g.symptom)"
      print $"    (ansi magenta)oracle(ansi reset)  ($g.oracle)"
    }
  }
  print ""
}

# Run the end-to-end binding oracle in the CURRENT RusteloApp: publish a trivial
# item, activate (content_processor), assert it entered the index, clean up.
# Witnessed verification (ADR-056) — proves the contract before generating pages.
def probe [] {
  let root = ($env.ONTOREF_PROJECT_ROOT? | default (pwd | path expand))
  let ws = (site-workspace $root)
  if ($ws | is-empty) {
    print $"  ✗ no site/content found under ($root) (looked at site/ and code/site/) — not a content-only RusteloApp"
    return
  }
  if (which content_processor | is-empty) {
    print "  ✗ content_processor not on PATH — install the rustelo content tooling"
    return
  }
  let probe_md  = $"($ws)/site/content/blog/en/getting-started/_ontoref-probe.md"
  let probe_dir = ($probe_md | path dirname)
  mkdir $probe_dir
  "---\nid: \"_ontoref-probe\"\ntitle: \"Ontoref Probe\"\nslug: \"_ontoref-probe\"\nexcerpt: \"Auto-generated contract probe.\"\nauthor: \"ontoref\"\ndate: \"2026-01-01\"\npublished: true\ncategory: \"getting-started\"\ntags: [\"probe\"]\n---\n\n# Ontoref Probe\n\nWitnessed publish->activate->index oracle.\n" | save -f $probe_md

  cd $ws
  let act = (do { ^content_processor --content-type blog --language en } | complete)
  let html = $"($ws)/site/r/blog/en/getting-started/_ontoref-probe.html"
  let idx  = $"($ws)/site/r/blog/en/getting-started/index.json"
  let html_ok = ($html | path exists)
  let idx_ok = if ($idx | path exists) { (open --raw $idx | str contains "_ontoref-probe") } else { false }

  # Clean up the probe artifacts and re-index to drop it from the index.
  rm -f $probe_md $html $"($ws)/site/r/blog/en/getting-started/_ontoref-probe.json"
  do { ^content_processor --content-type blog --language en } | complete | ignore

  print ""
  if ($act.exit_code == 0) and $html_ok and $idx_ok {
    print $"  (ansi green_bold)GREEN(ansi reset)  publish->activate->index oracle passed"
    print $"    item indexed at site/r/blog/en/getting-started/ and present in index.json"
    print $"    next: serve \(rustelo-htmx-server\) and GET /blog/getting-started/<slug> -> expect HTTP 200"
  } else {
    print $"  (ansi red_bold)RED(ansi reset)  oracle failed — activate exit=($act.exit_code), html=($html_ok), in_index=($idx_ok)"
    if $act.exit_code != 0 { print $act.stderr }
  }
  print ""
}
