# reflection/nulib/dashboard.nu — overview, status, health commands.

use ./fmt.nu *
use ./shared.nu [project-root, load-dimensions, load-gates, adrs-brief]

export def run-overview [fmt_resolved: string] {
  let root = project-root
  let name = ($root | path basename)

  let cargo_toml = $"($root)/Cargo.toml"
  let has_workspace = ($cargo_toml | path exists) and ((open $cargo_toml | get -o workspace | is-not-empty) == true)

  let crates = if ($cargo_toml | path exists) {
    let cargo = (open $cargo_toml)
    let members = ($cargo | get -o workspace.members | default [])
    if ($members | is-empty) {
      let pkg_name = ($cargo | get -o package.name | default $name)
      let deps = ($cargo | get -o dependencies | default {} | columns)
      let features = ($cargo | get -o features | default {} | columns)
      [{ name: $pkg_name, deps: ($deps | length), features: $features }]
    } else {
      mut result = []
      for member in $members {
        let expanded = (glob $"($root)/($member)/Cargo.toml")
        for ct in $expanded {
          let c = (open $ct)
          let cname = ($c | get -o package.name | default ($ct | path dirname | path basename))
          let deps = ($c | get -o dependencies | default {} | columns)
          let features = ($c | get -o features | default {} | columns)
          $result = ($result | append { name: $cname, deps: ($deps | length), features: $features })
        }
      }
      $result
    }
  } else { [] }

  let total_deps = ($crates | get deps | math sum)

  let systems = [
    (if ($"($root)/.ontology/core.ncl" | path exists) { "ontology" } else { null }),
    (if ((glob $"($root)/adrs/adr-*.ncl" | length) > 0) { "ADRs" } else { null }),
    (if ($"($root)/reflection" | path exists) { "reflection" } else { null }),
    (if ($"($root)/.ontology/manifest.ncl" | path exists) { "manifest" } else { null }),
    (if ($"($root)/.coder" | path exists) { ".coder" } else { null }),
    (if ($"($root)/.claude/CLAUDE.md" | path exists) { ".claude" } else { null }),
    (if ($"($root)/justfile" | path exists) { "justfile" } else { null }),
  ] | compact

  let report = (sync audit --quick --fmt silent)
  let health = ($report.health? | default 0.0)
  let nodes = ($report.nodes? | default {})

  let dims = (load-dimensions $root)
  let reached = ($dims | where reached == true | length)
  let total_dims = ($dims | length)

  let brief = adrs-brief

  let modes_count = ((glob $"($env.ONTOREF_ROOT)/reflection/modes/*.ncl" | length) + (if $root != $env.ONTOREF_ROOT { glob $"($root)/reflection/modes/*.ncl" | length } else { 0 }))
  let just_count = if ($"($root)/justfiles" | path exists) { glob $"($root)/justfiles/*.just" | length } else { 0 }

  let overview_data = {
    project: $name,
    root: $root,
    workspace: $has_workspace,
    crates: ($crates | each { |c| { name: $c.name, deps: $c.deps, features: ($c.features | str join ", ") } }),
    total_crates: ($crates | length),
    total_deps: $total_deps,
    systems: $systems,
    health: $health,
    nodes: $nodes,
    dimensions: { reached: $reached, total: $total_dims },
    adrs: $brief,
    modes: $modes_count,
    just_modules: $just_count,
  }

  match $fmt_resolved {
    "json" => { print ($overview_data | to json); return },
    "yaml" => { print ($overview_data | to yaml); return },
    "table" => { print ($overview_data | table --expand); return },
    "toml" => {
      print ($overview_data | to json)
      return
    },
    _ => {},
  }

  let h_color = if $health >= 90.0 { (ansi green_bold) } else if $health >= 70.0 { (ansi yellow_bold) } else { (ansi red_bold) }
  let bar_len = (($health / 5.0) | math round | into int)
  let bar_fill = ("█" | fill -c "█" -w $bar_len)
  let bar_empty = ("░" | fill -c "░" -w (20 - $bar_len))

  print ""
  fmt-header $name
  fmt-sep

  let ws_label = if $has_workspace { $"(ansi cyan)workspace(ansi reset)" } else { $"(ansi dark_gray)single crate(ansi reset)" }
  print $"  ($ws_label)  (ansi dark_gray)($systems | str join ' · ')(ansi reset)"
  print ""

  print $"  ($h_color)($bar_fill)(ansi dark_gray)($bar_empty)(ansi reset)  ($h_color)($health)%(ansi reset)"
  print ""

  if ($crates | is-not-empty) {
    let crate_label = $"(ansi white_bold)Crates(ansi reset) ($crates | length)  (ansi dark_gray)total deps: ($total_deps)(ansi reset)"
    print $"  ($crate_label)"
    for c in $crates {
      let feat_str = if ($c.features | is-not-empty) { $"  (ansi dark_gray)features: ($c.features | str join ', ')(ansi reset)" } else { "" }
      let dep_count = $c.deps
      print $"    (ansi green)($c.name)(ansi reset) (ansi dark_gray)($dep_count) deps(ansi reset)($feat_str)"
    }
    print ""
  }

  let ok = ($nodes.ok? | default 0)
  let issues = (($nodes.missing? | default 0) + ($nodes.stale? | default 0) + ($nodes.drift? | default 0))
  let issues_str = if $issues > 0 { $"(ansi yellow)($issues)(ansi reset)" } else { $"(ansi dark_gray)0(ansi reset)" }
  let adr_label = $"($brief.accepted)A/($brief.superseded)S/($brief.proposed)P"
  let dim_label = if $total_dims > 0 { $"($reached)/($total_dims)" } else { "—" }

  print $"  (ansi white_bold)Nodes(ansi reset) (ansi green)($ok)(ansi reset) ok ($issues_str) issues  (ansi white_bold)ADRs(ansi reset) (ansi cyan)($adr_label)(ansi reset)  (ansi white_bold)Dims(ansi reset) (ansi cyan)($dim_label)(ansi reset)  (ansi white_bold)Modes(ansi reset) ($modes_count)  (ansi white_bold)Just(ansi reset) ($just_count)"

  let active_dims = ($dims | where reached == false)
  if ($active_dims | is-not-empty) {
    print ""
    for d in $active_dims {
      print $"    (ansi dark_gray)($d.id): ($d.current_state) → ($d.desired_state)(ansi reset)"
    }
  }

  print ""
}

export def run-health [fmt_resolved: string, full: bool] {
  let report = if $full {
    sync audit --fmt (if $fmt_resolved == "json" { "json" } else { "silent" })
  } else {
    sync audit --quick --fmt (if $fmt_resolved == "json" { "json" } else { "silent" })
  }

  let health_data = {
    health: ($report.health? | default 0.0),
    nodes: ($report.nodes? | default {}),
  }

  match $fmt_resolved {
    "json" => { print ($health_data | to json); return },
    "yaml" => { print ($health_data | to yaml); return },
    "toml" => { print ($health_data | to toml); return },
    "table" => { print ($health_data | table --expand); return },
    _ => {},
  }

  let health = $health_data.health
  let nodes = $health_data.nodes
  let ok = ($nodes.ok? | default 0)
  let missing = ($nodes.missing? | default 0)
  let stale = ($nodes.stale? | default 0)
  let drift = ($nodes.drift? | default 0)
  let broken = ($nodes.broken_edges? | default 0)

  render-health-bar $health
  print $"  (ansi white_bold)Nodes(ansi reset)  (ansi green)($ok) OK(ansi reset)  (ansi dark_gray)($missing)M ($stale)S ($drift)D ($broken)B(ansi reset)"
  print ""
}

export def run-status [fmt_resolved: string] {
  let root = project-root
  let name = ($root | path basename)

  let report = (sync audit --quick --fmt silent)
  let health = ($report.health? | default 0.0)

  let dims = (load-dimensions $root)
  let reached = ($dims | where reached == true | length)
  let total_dims = ($dims | length)

  let brief = adrs-brief
  let adr_label = $"($brief.accepted)A/($brief.superseded)S/($brief.proposed)P"

  let gates = (load-gates $root)

  let nodes = ($report.nodes? | default {})
  let ok = ($nodes.ok? | default 0)
  let issues = (($nodes.missing? | default 0) + ($nodes.stale? | default 0) + ($nodes.drift? | default 0))

  let recent = (coder log --limit 5)

  let git_log = do { ^git -C $root log --oneline -3 } | complete
  let commits = if $git_log.exit_code == 0 {
    $git_log.stdout | lines | where { $in | is-not-empty }
  } else { [] }

  let status_data = {
    project: $name,
    root: $root,
    health: $health,
    nodes: { ok: $ok, issues: $issues },
    dimensions: { reached: $reached, total: $total_dims },
    adrs: $brief,
    gates: ($gates | length),
    recent_coder: ($recent | each { |r| { title: ($r.title? | default ""), kind: ($r.kind? | default ""), ts: ($r.timestamp? | default "") } }),
    recent_commits: $commits,
  }

  match $fmt_resolved {
    "json" => { print ($status_data | to json); return },
    "yaml" => { print ($status_data | to yaml); return },
    "toml" => {
      print ($status_data | to json)
      return
    },
    "table" => { print ($status_data | table --expand); return },
    _ => {},
  }

  let h_color = if $health >= 90.0 { (ansi green_bold) } else if $health >= 70.0 { (ansi yellow_bold) } else { (ansi red_bold) }
  let bar_len = (($health / 5.0) | math round | into int)
  let bar_fill = ("█" | fill -c "█" -w $bar_len)
  let bar_empty = ("░" | fill -c "░" -w (20 - $bar_len))

  print ""
  fmt-header $"($name) — project status"
  fmt-sep
  print $"  (ansi white_bold)Health(ansi reset)  ($h_color)($bar_fill)(ansi dark_gray)($bar_empty)(ansi reset)  ($h_color)($health)%(ansi reset)  (ansi dark_gray)\(quick)(ansi reset)"
  let issues_str = if $issues > 0 { $"(ansi yellow)($issues) issues(ansi reset)" } else { $"(ansi dark_gray)0 issues(ansi reset)" }
  print $"  (ansi white_bold)Nodes(ansi reset)   (ansi green)($ok) OK(ansi reset)  ($issues_str)"
  print $"  (ansi white_bold)ADRs(ansi reset)    (ansi cyan)($adr_label)(ansi reset)"
  print $"  (ansi white_bold)Gates(ansi reset)   (ansi cyan)($gates | length) active(ansi reset)"

  if $total_dims > 0 {
    print $"  (ansi white_bold)State(ansi reset)   (ansi green)($reached)(ansi reset)/(ansi cyan)($total_dims)(ansi reset) dimensions reached"
    let active_dims = ($dims | where reached == false)
    for d in $active_dims {
      print $"          (ansi dark_gray)($d.id): ($d.current_state) → ($d.desired_state)(ansi reset)"
    }
  }

  if ($commits | is-not-empty) {
    print ""
    fmt-section "Recent commits"
    print ""
    for c in $commits {
      print $"  (ansi dark_gray)($c)(ansi reset)"
    }
  }

  if ($recent | is-not-empty) {
    print ""
    fmt-section "Recent activity (.coder/)"
    print ""
    for r in $recent {
      let kind_color = match ($r.kind? | default "") {
        "done" => (ansi green),
        "plan" => (ansi cyan),
        "review" => (ansi magenta),
        "audit" => (ansi yellow),
        _ => (ansi default_dimmed),
      }
      let ts = ($r.timestamp? | default "" | str substring 0..9)
      print $"  ($kind_color)($r.kind? | default "?")(ansi reset)  (ansi dark_gray)($ts)(ansi reset)  ($r.title? | default "")"
    }
  }

  print ""
}
