#!/usr/bin/env nu
# domains/provisioning/commands.nu — Provisioning domain CLI for ontoref.
# Dispatched by the ontoref bash wrapper when repo_kind in {DevWorkspace, Mixed}:
#   ore provisioning <command> [args]
#
# Works for both DevWorkspace (workspace-level) and Mixed (platform-level) projects.
# Commands that require project-specific files (card.ncl, reflection/backlog.ncl)
# degrade gracefully when those files are absent.

def project-root [] {
    $env.ONTOREF_PROJECT_ROOT? | default (pwd | path expand)
}

# ─── Loaders ──────────────────────────────────────────────────────────────────

def load-state       [] { ^nickel export $"(project-root)/.ontology/state.ncl"       | from json }
def load-core        [] { ^nickel export $"(project-root)/.ontology/core.ncl"         | from json }
def load-gate        [] { ^nickel export $"(project-root)/.ontology/gate.ncl"         | from json }
def load-connections [] { ^nickel export $"(project-root)/.ontology/connections.ncl"  | from json }
def load-manifest    [] { ^nickel export $"(project-root)/.ontology/manifest.ncl"     | from json }

def load-card [] {
    let path = $"(project-root)/card.ncl"
    if ($path | path exists) { ^nickel export $path | from json } else { null }
}

def load-backlog [] {
    let path = $"(project-root)/reflection/backlog.ncl"
    if ($path | path exists) { ^nickel export $path | from json } else { { items: [] } }
}

# ─── state / next / validate ──────────────────────────────────────────────────

export def "state" [] {
    load-state | get dimensions | each { |dim|
        { dimension: $dim.id, current: $dim.current_state, desired: $dim.desired_state, horizon: $dim.horizon }
    }
}

export def "next" [] {
    load-state | get dimensions | each { |dim|
        let active = $dim.transitions | where from == $dim.current_state
        if ($active | is-empty) {
            { dimension: $dim.id, from: $dim.current_state, to: "–", condition: "no active transition", blocker: "–", catalyst: "–" }
        } else {
            let tr = $active | first
            { dimension: $dim.id, from: $tr.from, to: $tr.to, condition: $tr.condition, blocker: $tr.blocker, catalyst: $tr.catalyst }
        }
    }
}

export def "validate" [decision: string] {
    let core  = load-core
    let words = ($decision | str downcase | split row " " | where { |w| ($w | str length) > 3 })
    let affected = ($core.nodes | each { |n|
        let text = $"($n.id) ($n.name) ($n.description)" | str downcase
        if ($words | any { |w| $text =~ $w }) { $n } else { null }
    } | compact)
    {
        decision:           $decision,
        invariants_at_risk: ($affected | where invariant == true | select id level name),
        tensions_touched:   ($affected | where level == "Tension" | select id name),
        practices_touched:  ($affected | where level == "Practice" | select id name),
        verdict:            "manual review required — if any invariant is contradicted, justification is required",
    }
}

# ─── connections / gates ──────────────────────────────────────────────────────

export def "connections" [] {
    let c = load-connections
    if ($c.upstream? | default [] | is-not-empty) {
        print ""
        print "UPSTREAM"
        $c.upstream | each { |u|
            print $"  ($u.project)  kind=($u.kind)  via=($u.via)"
            if ($u.node? | default "" | is-not-empty) { print $"    node: ($u.node)" }
            print $"    ($u.note)"
        }
    }
    if ($c.downstream? | default [] | is-not-empty) {
        print ""
        print "DOWNSTREAM"
        $c.downstream | each { |d|
            print $"  ($d.project)  kind=($d.kind)  via=($d.via)"
            if ($d.node? | default "" | is-not-empty) { print $"    node: ($d.node)" }
            print $"    ($d.note)"
        }
    }
    if ($c.peers? | default [] | is-not-empty) {
        print ""
        print "PEERS"
        $c.peers | each { |p| print $"  ($p.project)  kind=($p.kind)  via=($p.via)" }
    }
}

export def "gates" [] {
    load-gate | get membranes | each { |m|
        {
            membrane:    $m.id,
            name:        $m.name,
            active:      $m.active,
            permeability: $m.permeability,
            condition:   ($m.opening_condition.description? | default ""),
        }
    }
}

# ─── card (DevWorkspace only) ─────────────────────────────────────────────────

export def "card" [] {
    let c = load-card
    if ($c | is-empty) {
        print "No card.ncl found — this command is only available for DevWorkspace projects."
        return
    }
    print $"id:       ($c.id)"
    print $"name:     ($c.name)"
    print $"tagline:  ($c.tagline)"
    print $"status:   ($c.status)"
    print $"version:  ($c.version)"
    print $"started:  ($c.started_at)"
    if ($c.tags? | default [] | is-not-empty)  { print $"tags:     ($c.tags | str join ', ')" }
    if ($c.tools? | default [] | is-not-empty) { print $"tools:    ($c.tools | str join ', ')" }
    if ($c.features? | default [] | is-not-empty) {
        print ""
        print "features:"
        $c.features | each { |f| print $"  - ($f)" }
    }
}

# ─── capabilities (manifest.capabilities) ────────────────────────────────────

export def "capabilities" [] {
    let caps = load-manifest | get capabilities? | default []
    if ($caps | is-empty) { print "No capabilities declared in manifest."; return }
    $caps | select id name summary
}

# ─── backlog (platform only) ──────────────────────────────────────────────────

export def "backlog" [--priority: string = ""] {
    let items = load-backlog | get items
    if ($items | is-empty) {
        print "No backlog.ncl found — this command is only available for platform projects."
        return
    }
    let filtered = if ($priority | is-empty) { $items } else { $items | where priority == $priority }
    $filtered | each { |i|
        {
            id:         $i.id,
            priority:   $i.priority,
            blocked_by: ($i.blocked_by | str join ", "),
        }
    }
}

export def "backlog show" [id: string] {
    let items = load-backlog | get items
    if ($items | is-empty) { error make { msg: "No backlog.ncl found for this project." } }
    let item = $items | where id == $id
    if ($item | is-empty) { error make { msg: $"Backlog item not found: ($id)" } }
    let r = $item | first
    print $"id:       ($r.id)"
    print $"priority: ($r.priority)"
    print ""
    print "description:"
    print $"  ($r.description)"
    if ($r.blocked_by? | default [] | is-not-empty) {
        print ""
        print $"blocked_by:  ($r.blocked_by | str join ', ')"
    }
    if ($r.related_nodes? | default [] | is-not-empty) {
        print $"nodes:       ($r.related_nodes | str join ', ')"
    }
}

# ─── help + main ──────────────────────────────────────────────────────────────

def show-help [] {
    print "Provisioning — ontoref domain extension"
    print ""
    print "USAGE"
    print "  ore provisioning <command> [args]"
    print ""
    print "COMMANDS  (all repo_kinds)"
    print "  state                         Current FSM position across all dimensions"
    print "  next                          Next valid transitions with blockers/catalysts"
    print "  validate <decision>           Check against ontological invariants"
    print "  connections                   Upstream/downstream project dependency graph"
    print "  gates                         Membrane status and opening conditions"
    print "  capabilities                  Platform capabilities from manifest"
    print ""
    print "COMMANDS  (DevWorkspace only)"
    print "  card                          Workspace card: identity, clusters, status"
    print ""
    print "COMMANDS  (Mixed/platform only)"
    print "  backlog [--priority]          Backlog items filtered by High|Medium|Low"
    print "  backlog show <id>             Full detail of a backlog item"
}

def main [
    ...args: string
    --priority: string = ""
] {
    if ($args | is-empty) or ($args | first) == "help" { show-help; return }
    let sub = ($args | str join " ")
    match $sub {
        "state"        => { state }
        "next"         => { next }
        "connections"  => { connections }
        "gates"        => { gates }
        "card"         => { card }
        "capabilities" => { capabilities }
        "backlog"      => { backlog --priority $priority }
        _ if ($sub | str starts-with "backlog show ")  => { backlog show ($args | get 2) }
        _ if ($sub | str starts-with "validate ")      => { validate ($args | skip 1 | str join " ") }
        _              => { print $"Unknown command: ($sub)"; show-help }
    }
}
