# cli-ux.sh — shared recipe CLI UX helpers for mm-harness porcelain wrappers.
# Sourced, not executed.

recipe_color_enabled() {
  [ -n "${NO_COLOR:-}" ] && [ "${NO_COLOR:-}" != "0" ] && return 1
  [ "${RECIPE_NO_COLOR:-}" = "1" ] && return 1
  [ "${RECIPE_COLOR:-}" = "1" ] || [ "${FORCE_COLOR:-}" = "1" ] || [ -t 2 ]
}

recipe_color() {
  local style="$1" text="$2"
  if ! recipe_color_enabled; then
    printf '%s' "$text"
    return 0
  fi
  case "$style" in
    bold) printf '\033[1m%s\033[0m' "$text" ;;
    dim|comment|path) printf '\033[2m%s\033[0m' "$text" ;;
    label) printf '\033[1;36m%s\033[0m' "$text" ;;
    cmd) printf '\033[1m%s\033[0m' "$text" ;;
    ok) printf '\033[1;32m%s\033[0m' "$text" ;;
    warn) printf '\033[1;33m%s\033[0m' "$text" ;;
    err) printf '\033[1;31m%s\033[0m' "$text" ;;
    *) printf '%s' "$text" ;;
  esac
}

recipe_progress_script() {
  if [ -n "${RECIPE_PROGRESS_SCRIPT:-}" ]; then
    printf '%s' "$RECIPE_PROGRESS_SCRIPT"
    return 0
  fi
  local root="${RECIPE_RUNNER_ROOT:?}"
  if [ -f "$root/dist/progress.js" ]; then
    printf '%s' "$root/dist/progress.js"
  else
    printf '%s' "$root/src/progress.ts"
  fi
}

recipe_log_tui_script() {
  printf '%s' "${RECIPE_LOG_TUI_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/adapters/shared/log-tui.mjs}"
}

recipe_version_script() {
  if [ -n "${RECIPE_VERSION_SCRIPT:-}" ]; then
    printf '%s' "$RECIPE_VERSION_SCRIPT"
    return 0
  fi
  local root="${RECIPE_RUNNER_ROOT:?}"
  if [ -f "$root/dist/cli-version.js" ]; then
    printf '%s' "$root/dist/cli-version.js"
  else
    printf '%s' "$root/src/cli-version.ts"
  fi
}

recipe_log_ui_mode() {
  printf '%s' "${RECIPE_LOG_UI:-compact}"
}

recipe_log_events_limit() {
  printf '%s' "${RECIPE_LOG_EVENTS:-10}"
}

recipe_watch_build_log() {
  local log_path="$1" label="${2:-build}" success_pattern="${3:-}"
  local args=(
    watch --log "$log_path"
    --events "$(recipe_log_events_limit)"
    --mode "$(recipe_log_ui_mode)"
    --label "$label"
  )
  [ -n "$success_pattern" ] && args+=(--success-pattern "$success_pattern")
  node "$(recipe_log_tui_script)" "${args[@]}"
}

recipe_watch_rebuild_log() {
  local log_path="$1"
  recipe_watch_build_log "$log_path" "runtime rebuild" \
    'PASS runtime-launch|Extension harness verify pass|runtime rebuild complete'
}

recipe_instant_hint() {
  local message="$1"
  [ "${RECIPE_PROGRESS_JSON:-}" = "1" ] && return 0
  [ -t 2 ] || return 0
  local prefix="${RECIPE_CLI_PREFIX:-mm-harness}"
  printf '%s: %s\n' \
    "$(recipe_color label "$prefix")" \
    "$(recipe_color dim "$message")" >&2
}

recipe_progress() {
  local verb="$1" phase="$2" message="$3" elapsed="${4:-}"
  local args=(emit --command "$verb" --phase "$phase" --message "$message")
  [ -n "$elapsed" ] && args+=(--elapsed-ms "$elapsed")
  [ "${RECIPE_PROGRESS_JSON:-}" = "1" ] && args+=(--json)
  node "$(recipe_progress_script)" "${args[@]}" || true
}

recipe_done() {
  local verb="$1" status="$2" message="$3" elapsed="${4:-}"
  local args=(done --command "$verb" --status "$status" --message "$message")
  [ -n "$elapsed" ] && args+=(--elapsed-ms "$elapsed")
  [ "${RECIPE_PROGRESS_JSON:-}" = "1" ] && args+=(--json)
  node "$(recipe_progress_script)" "${args[@]}" || true
}

recipe_failure_playbook() {
  local verb="$1" reason="$2"
  shift 2
  local log_path="" artifact="" prefix="${RECIPE_CLI_PREFIX:-mm-harness}"
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --log) log_path="$2"; shift 2 ;;
      --artifact) artifact="$2"; shift 2 ;;
      --prefix) prefix="$2"; shift 2 ;;
      *) shift ;;
    esac
  done
  printf '%s: %s %s - %s\n' \
    "$(recipe_color label "$prefix")" \
    "$(recipe_color cmd "$verb")" \
    "$(recipe_color err failed)" \
    "$(recipe_color warn "$reason")" >&2
  printf '%s\n' "$(recipe_color label "next:")" >&2
  case "$verb" in
    rebuild|up|watch)
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs --full")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness doctor")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness install")" >&2
      ;;
    refresh)
      printf '  %s\n' "$(recipe_color cmd "mm-harness launch")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness launch --build")" >&2
      ;;
    metro|ios|android|setup-wallet)
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs --full")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness launch")" >&2
      ;;
    *)
      printf '  %s\n' "$(recipe_color cmd "mm-harness doctor")" >&2
      printf '  %s\n' "$(recipe_color cmd "mm-harness logs")" >&2
      ;;
  esac
  [ -n "$log_path" ] && printf '%s\n' "$(recipe_color path "log: $log_path")" >&2
  [ -n "$artifact" ] && printf '%s\n' "$(recipe_color path "artifact: $artifact")" >&2
  return 0
}

recipe_check_harness_stale() {
  local adapter="$1" root="$2" harness_root="$3" runner_root="$4"
  local manifest="" sha=""
  case "$adapter" in
    extension) manifest="$root/$harness_root/extension/manifest.json" ;;
    mobile) manifest="$root/$harness_root/mobile/manifest.json" ;;
    *) return 0 ;;
  esac
  [ -f "$manifest" ] || return 0
  sha="${manifest%/*}/installed-scripts.sha256"
  node "$(recipe_version_script)" check \
    --runner-root "$runner_root" \
    --manifest "$manifest" \
    ${sha:+--installed-sha "$sha"} \
    --json 2>/dev/null | grep -q '"stale"[[:space:]]*:[[:space:]]*true'
}

recipe_warn_harness_stale() {
  local adapter="$1" root="$2" harness_root="$3" runner_root="$4"
  local prefix="${RECIPE_CLI_PREFIX:-mm-harness}"
  if recipe_check_harness_stale "$adapter" "$root" "$harness_root" "$runner_root"; then
    printf '%s: %s - run: %s\n' \
      "$(recipe_color label "$prefix")" \
      "$(recipe_color warn 'harness scripts are stale')" \
      "$(recipe_color cmd "mm-harness install")" >&2
    return 1
  fi
  return 0
}

recipe_infer_farmslot_root() {
  if [ -n "${FARMSLOT_ROOT:-}" ] && [ -d "${FARMSLOT_ROOT}" ]; then
    printf '%s' "${FARMSLOT_ROOT}"
    return 0
  fi
  local candidate=""
  for candidate in "$HOME/dev/farmslot" "$HOME/farmslot"; do
    [ -d "$candidate/scripts" ] || continue
    printf '%s' "$candidate"
    return 0
  done
  return 1
}

recipe_try_farmslot_fixture_sync() {
  local slot_id="$1"
  local farmslot_root=""
  [ -n "$slot_id" ] || return 1
  farmslot_root="$(recipe_infer_farmslot_root || true)"
  [ -n "$farmslot_root" ] || return 1
  [ -f "$farmslot_root/scripts/sync-fixtures.sh" ] || return 1
  bash "$farmslot_root/scripts/sync-fixtures.sh" --slot "$slot_id"
}

recipe_sync_wallet_fixture() {
  local root="$1" runtime_dir="$2" cdp_port="${3:-}" seed_script="${4:-}" farmslot_slot="${5:-}"
  local canonical="$root/$runtime_dir/wallet-fixture.json"
  local candidate resolved prefix="${RECIPE_CLI_PREFIX:-mm-harness}"

  mkdir -p "$root/$runtime_dir"
  if [ -f "$canonical" ]; then
    return 0
  fi

  if [ -n "${RECIPE_WALLET_FIXTURE:-}" ] && [ -f "${RECIPE_WALLET_FIXTURE}" ]; then
    cp "${RECIPE_WALLET_FIXTURE}" "$canonical"
    chmod 600 "$canonical" 2>/dev/null || true
    printf '%s: fixture: linked %s/wallet-fixture.json from RECIPE_WALLET_FIXTURE\n' "$prefix" "$runtime_dir" >&2
    return 0
  fi

  if [ -n "$seed_script" ] && [ -f "$seed_script" ]; then
    resolved="$(cd "$root" && bash "$seed_script" resolve --target "$root" ${cdp_port:+--cdp-port "$cdp_port"} 2>/dev/null || true)"
    if [ -n "$resolved" ] && [ -f "$resolved" ] && [ "$resolved" != "$canonical" ]; then
      cp "$resolved" "$canonical"
      chmod 600 "$canonical" 2>/dev/null || true
      printf '%s: fixture: copied to %s/wallet-fixture.json\n' "$prefix" "$runtime_dir" >&2
      return 0
    fi
  fi

  for candidate in \
    "$root/temp/runtime/wallet-fixture.json" \
    ${cdp_port:+"$root/temp/.recipe-validation-${cdp_port}/wallet-fixture.json"} \
    "$root/temp/.agent-validation/wallet-fixture.json"
  do
    [ -f "$candidate" ] || continue
    cp "$candidate" "$canonical"
    chmod 600 "$canonical" 2>/dev/null || true
    printf '%s: fixture: copied to %s/wallet-fixture.json\n' "$prefix" "$runtime_dir" >&2
    return 0
  done

  if [ -n "$farmslot_slot" ]; then
    printf '%s: fixture: trying farmslot sync-fixtures --slot %s\n' "$prefix" "$farmslot_slot" >&2
    if recipe_try_farmslot_fixture_sync "$farmslot_slot"; then
      [ -f "$canonical" ] && return 0
    fi
  fi

  return 1
}

recipe_speed_ladder() {
  cat >&2 <<'EOF'
Speed ladder:
  FAST (seconds):  mm-harness launch (extension quick relaunch)
  SLOW (minutes):  mm-harness launch --build
  INSPECT:         mm-harness doctor | mm-harness logs | mm-harness logs --full | mm-harness debug
  PROOF:           mm-harness run <recipe.json>
  SYNC CONTEXT:    mm-harness fixtures sync
EOF
}