#!/usr/bin/env nu
# install/gen-projects.nu — validate and regenerate ~/.config/ontoref/projects.ncl.
#
# Manages LOCAL projects only. Remote projects live in remote-projects.ncl.
#
# Reads projects.ncl as text, extracts import paths, verifies each .ontoref/project.ncl
# exists on disk, removes missing ones (with warning), and rewrites projects.ncl with
# only valid imports. Must run before `nickel export config.ncl`.
#
# Usage:
#   nu install/gen-projects.nu                             # validate + regenerate
#   nu install/gen-projects.nu --add /path/to/project     # register new local project
#   nu install/gen-projects.nu --remove /path/to/project  # unregister local project
#   nu install/gen-projects.nu --dry-run                  # print result without writing

def main [
  --add: string,         # path to local project root to register
  --remove: string,      # path to local project root to unregister
  --dry-run,             # print result without writing
  --config-dir: string = "",
] {
  let cfg_dir = if ($config_dir | is-empty) {
    $"($env.HOME)/.config/ontoref"
  } else {
    $config_dir
  }
  let projects_file = $"($cfg_dir)/projects.ncl"

  if not ($projects_file | path exists) {
    "[]" | save -f $projects_file
  }

  # ── Extract existing import paths as plain text (never call nickel here) ────
  # open --raw: .ncl is unknown to Nushell; without --raw it may parse `[]` as
  # an empty list instead of a string, which would silently lose all existing entries.
  let content = open --raw $projects_file
  let existing_paths = (
    $content
    | lines
    | each { |l| $l | str trim }
    | where { |l| ($l | str contains "import \"") }
    | each { |l|
        let parsed = ($l | parse --regex 'import\s+"(?P<path>[^"]+)"')
        if ($parsed | is-empty) { null } else { $parsed | get path | first }
      }
    | compact
    | flatten
  )

  # ── Handle --remove ──────────────────────────────────────────────────────────
  let after_remove = if ($remove | is-not-empty) {
    let abs = ($remove | path expand)
    let ncl_path = $"($abs)/.ontoref/project.ncl"
    let filtered = ($existing_paths | where { |p| $p != $ncl_path })
    if ($filtered | length) == ($existing_paths | length) {
      print --stderr $"  (ansi yellow)not registered(ansi reset): ($ncl_path)"
    } else {
      print --stderr $"  (ansi green)removed(ansi reset): ($ncl_path)"
    }
    $filtered
  } else {
    $existing_paths
  }

  # ── Handle --add ─────────────────────────────────────────────────────────────
  let after_add = if ($add | is-not-empty) {
    let abs = ($add | path expand)
    let ncl_path = $"($abs)/.ontoref/project.ncl"
    if not ($ncl_path | path exists) {
      error make { msg: $"project.ncl not found: ($ncl_path)\nCopy templates/project.ncl to ($add)/.ontoref/project.ncl and fill in the fields." }
    }
    if ($after_remove | any { |p| $p == $ncl_path }) {
      print --stderr $"  (ansi yellow)already registered(ansi reset): ($ncl_path)"
      $after_remove
    } else {
      $after_remove | append $ncl_path
    }
  } else {
    $after_remove
  }

  # ── Validate: check local paths still exist ──────────────────────────────────
  let valid_paths = (
    $after_add | each { |p|
      if not ($p | path exists) {
        let project_root = ($p | str replace --regex '(/\.ontoref/project\.ncl)$' '')
        if not ($project_root | path exists) {
          print --stderr $"  (ansi yellow)WARN(ansi reset) removing missing project \(root deleted\): ($project_root)"
        } else {
          print --stderr $"  (ansi yellow)WARN(ansi reset) removing invalid project \(project.ncl missing\): ($p)"
        }
        null
      } else {
        $p
      }
    }
    | compact
  )

  let removed = ($after_add | length) - ($valid_paths | length)
  if $removed > 0 {
    print --stderr $"  (ansi yellow)($removed) project\(s\) removed — path\(s\) no longer exist(ansi reset)"
  }

  # ── Generate projects.ncl ─────────────────────────────────────────────────────
  let import_lines = (
    $valid_paths
    | each { |p| $"    [import \"($p)\"]," }
    | str join "\n"
  )

  let output = if ($valid_paths | is-empty) {
    "# AUTO-GENERATED by ontoref project-add / ontoref-daemon-boot. Do not edit by hand.\n# Add a local project: ontoref project-add /path/to/project\n\n[]\n"
  } else {
    "# AUTO-GENERATED by ontoref project-add / ontoref-daemon-boot. Do not edit by hand.\n# Add a local project: ontoref project-add /path/to/project\n\nstd.array.flatten [\n" + $import_lines + "\n]\n"
  }

  if $dry_run {
    print --stderr "── projects.ncl (dry-run) ──────────────────────────────"
    print $output
    print --stderr "────────────────────────────────────────────────────────"
  } else {
    $output | save -f $projects_file
    let n = ($valid_paths | length)
    let label = if $n == 1 { "project" } else { "projects" }
    print --stderr $"  (ansi green)OK(ansi reset) ($n) local ($label) written to ($projects_file)"
  }
}
