# shellcheck shell=bash
# lib-primitives.sh — shell-primitive copy + Rust workspace scoped build +
# .installed state helpers + --list printer.
#
# Requires: primitive_field from lib-profile.sh.
# Requires: say / warn / err from lib-log.sh.
# Reads globals: $AGENTS_DIR, $KIT_DIR, $INSTALLED_FILE, $MANIFEST.

# --- .installed state helpers --------------------------------------------
read_installed() {
  [ -f "$INSTALLED_FILE" ] && cat "$INSTALLED_FILE" || true
}

write_installed() {
  # stdin = newline-separated names; writes sorted-unique to INSTALLED_FILE.
  mkdir -p "$(dirname "$INSTALLED_FILE")"
  sort -u > "$INSTALLED_FILE"
}

# --- per-primitive install/remove ----------------------------------------
copy_shell_primitive() {
  local name="$1" file src dst
  file="$(primitive_field "$name" file)"
  [ -n "$file" ] || { err "no 'file' for shell primitive $name"; return 1; }
  src="$KIT_DIR/_primitives/$file"
  dst="$AGENTS_DIR/_primitives/$file"
  [ -f "$src" ] || { err "source missing: $src"; return 1; }
  mkdir -p "$AGENTS_DIR/_primitives"
  cp -f "$src" "$dst"
  chmod +x "$dst"
  say "  + shell: $name ($file)"
}

remove_shell_primitive() {
  local name="$1" file
  file="$(primitive_field "$name" file)"
  [ -n "$file" ] || return 0
  rm -f "$AGENTS_DIR/_primitives/$file"
  say "  - shell: $name ($file)"
}

copy_rust_primitive() {
  local name="$1" crate src dst_root dst sibling
  crate="$(primitive_field "$name" crate)"
  [ -n "$crate" ] || { err "no 'crate' for rust primitive $name"; return 1; }
  src="$KIT_DIR/_primitives/_rust/$crate"
  [ -d "$src" ] || { err "source missing: $src"; return 1; }
  dst_root="$AGENTS_DIR/_primitives/_rust"
  dst="$dst_root/$crate"
  mkdir -p "$dst/src"
  cp -f "$src/Cargo.toml" "$dst/Cargo.toml"
  [ -d "$src/src" ] && cp -rf "$src/src/"* "$dst/src/" 2>/dev/null || true
  if [ -d "$src/tests" ]; then
    mkdir -p "$dst/tests"
    cp -rf "$src/tests/"* "$dst/tests/" 2>/dev/null || true
  fi
  # v0.21: kei-artifact and future crates reference sibling data dirs via
  # include_str!("../schemas/*.json") etc. Copy known sibling directories
  # when present. Whitelist keeps target/, .git/, build artifacts out.
  for sibling in schemas assets templates fixtures migrations; do
    if [ -d "$src/$sibling" ]; then
      mkdir -p "$dst/$sibling"
      cp -rf "$src/$sibling/"* "$dst/$sibling/" 2>/dev/null || true
    fi
  done
  say "  + rust:  $name (crate $crate)"
}

remove_rust_primitive() {
  local name="$1" crate
  crate="$(primitive_field "$name" crate)"
  [ -n "$crate" ] || return 0
  rm -rf "$AGENTS_DIR/_primitives/_rust/$crate"
  say "  - rust:  $name (crate $crate)"
}

# --- rust enumeration / manifest / build all live in install/lib-rust.sh
#     (Constructor-Pattern split — keeps this cube under 200 LOC).

# --- install / remove orchestrators --------------------------------------
# Install primitives from a name list (newline-separated on stdin).
install_primitives() {
  local names existing combined kind p any_rust=0
  names="$(cat)"
  existing="$(read_installed)"
  combined="$(printf '%s\n%s\n' "$existing" "$names" | grep -v '^$' || true)"
  while IFS= read -r p; do
    [ -z "$p" ] && continue
    kind="$(primitive_field "$p" kind)"
    case "$kind" in
      shell) copy_shell_primitive "$p" ;;
      rust)  copy_rust_primitive "$p"; any_rust=1 ;;
      *)     warn "unknown primitive: $p (skipping)"; continue ;;
    esac
  done <<< "$names"
  printf '%s\n' "$combined" | write_installed
  if [ "$any_rust" = "1" ]; then
    regenerate_rust_workspace
  fi
}

# Remove a single primitive by name.
remove_primitive() {
  local name="$1" kind existing
  kind="$(primitive_field "$name" kind)"
  case "$kind" in
    shell) remove_shell_primitive "$name" ;;
    rust)  remove_rust_primitive  "$name" ;;
    *)     err "unknown primitive: $name"; return 1 ;;
  esac
  existing="$(read_installed)"
  printf '%s\n' "$existing" | grep -vFx "$name" | grep -v '^$' | write_installed || true
  if [ "$kind" = "rust" ]; then
    regenerate_rust_workspace
  fi
}

# --- --list implementation -----------------------------------------------
cmd_list() {
  echo
  printf '%-22s %-6s %-10s %s\n' "NAME" "KIND" "STATUS" "DESCRIPTION"
  printf '%-22s %-6s %-10s %s\n' "----" "----" "------" "-----------"
  local installed name kind desc status count
  installed="$(read_installed)"
  while IFS= read -r name; do
    [ -z "$name" ] && continue
    kind="$(primitive_field "$name" kind)"
    desc="$(primitive_field "$name" desc)"
    if printf '%s\n' "$installed" | grep -qFx "$name"; then
      status="INSTALLED"
    else
      status="-"
    fi
    printf '%-22s %-6s %-10s %s\n' "$name" "$kind" "$status" "$desc"
  done < <(all_primitive_names)
  echo
  count="$(printf '%s\n' "$installed" | grep -c . || true)"
  printf '%s primitives installed (state: %s)\n' "${count:-0}" "$INSTALLED_FILE"
  echo
}
