#!/usr/bin/env bash
# Spec-First environment health check
# Outputs a formatted diagnostic report in one pass.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/lib-helper-registry.sh"

plugin_version=""
json_output="no"
BROWSER_HELPER_OPT_IN_ACTION='set SPEC_FIRST_BROWSER_HELPER_REQUIRED=1 and rerun the host setup workflow (`$spec-mcp-setup` or `/spec:mcp-setup`)'
while [ $# -gt 0 ]; do
  case "$1" in
    --version)
      if [ $# -ge 2 ]; then
        plugin_version="$2"
        shift 2
      else
        shift
      fi
      ;;
    --json)
      json_output="yes"
      shift
      ;;
    *)
      shift
      ;;
  esac
done

detect_os() {
  local os
  os="$(uname -s 2>/dev/null || echo "unknown")"
  case "$os" in
    Darwin) echo "macos" ;;
    Linux) echo "linux" ;;
    MINGW*|MSYS*|CYGWIN*) echo "windows" ;;
    *) echo "unknown" ;;
  esac
}

build_install_command() {
  local name="$1"
  local os="$2"
  # agent-browser 在 check-health 视角是 opt-in 提示(非真实安装命令);其余 helper
  # 委派到 lib-helper-registry.sh 的共享展示生成器,消除与 install-helpers.sh 的双份维护漂移。
  if [ "$name" = "agent-browser" ]; then
    echo "$BROWSER_HELPER_OPT_IN_ACTION"
    return 0
  fi
  helper_registry_install_command_display "$name" "$os"
}

build_project_url() {
  local name="$1"
  helper_registry_source_repo "$name"
}

ok()      { echo "  🟢  $1"; }
warn()    { echo "  🟡  $1"; }
detail()  { echo "       $1"; }
section() { echo ""; echo " $1"; }
required_label() {
  case "$1" in
    required) echo "yes" ;;
    *) echo "no" ;;
  esac
}
status_label() {
  case "$1" in
    ok) echo "installed" ;;
    agent-browser-cli-ready|skipped) echo "skipped" ;;
    degraded) echo "degraded" ;;
    *) echo "missing" ;;
  esac
}
json_escape() {
  local value="$1"
  value="${value//\\/\\\\}"
  value="${value//\"/\\\"}"
  value="${value//$'\n'/\\n}"
  printf '%s' "$value"
}
global_skill_installed() {
  local skill_name="$1"
  [ -f "$HOME/.agents/skills/$skill_name/SKILL.md" ] || [ -f "$HOME/.codex/skills/$skill_name/SKILL.md" ] || [ -f "$HOME/.claude/skills/$skill_name/SKILL.md" ]
}
agent_browser_ready() {
  command -v agent-browser >/dev/null 2>&1 || return 1
  [ -f "$HOME/.agent-browser/spec-first-install.json" ] || return 1
  global_skill_installed agent-browser || return 1
}

os="$(detect_os)"
has_brew="$(command -v brew >/dev/null 2>&1 && echo "yes" || echo "no")"
in_repo="$(git rev-parse --is-inside-work-tree >/dev/null 2>&1 && echo "yes" || echo "no")"

deps=()
while IFS= read -r helper_id; do
  deps+=("$helper_id|$(helper_registry_baseline_blocking "$helper_id")")
done < <(helper_registry_cli_ids)

skills=()
while IFS= read -r helper_id; do
  skills+=("$helper_id|$(helper_registry_skill_name "$helper_id")|$(helper_registry_baseline_blocking "$helper_id")")
done < <(helper_registry_skill_ids)

cli_ok=0
cli_total=0
issues=0
results=()

for entry in "${deps[@]}"; do
  IFS='|' read -r name baseline_blocking <<<"$entry"
  cli_total=$((cli_total + 1))
  install_cmd="$(build_install_command "$name" "$os")"
  url="$(build_project_url "$name")"

  if [ "$name" = "agent-browser" ]; then
    if agent_browser_ready; then
      cli_ok=$((cli_ok + 1))
      results+=("$name|$baseline_blocking|ok|$install_cmd|$url")
    elif command -v agent-browser >/dev/null 2>&1; then
      cli_ok=$((cli_ok + 1))
      results+=("$name|$baseline_blocking|agent-browser-cli-ready|$install_cmd|$url")
    else
      results+=("$name|$baseline_blocking|skipped|$install_cmd|$url")
    fi
  elif command -v "$name" >/dev/null 2>&1; then
    cli_ok=$((cli_ok + 1))
    results+=("$name|$baseline_blocking|ok|$install_cmd|$url")
  else
    if [ "$name" = "ast-grep" ] && command -v rg >/dev/null 2>&1; then
      results+=("$name|$baseline_blocking|degraded|$install_cmd|$url")
    else
      results+=("$name|$baseline_blocking|missing|$install_cmd|$url")
    fi
  fi
done

# 全局 skill 安装检测改用确定性文件存在性（~/.agents|.codex|.claude/skills/<name>/SKILL.md），
# 不再调用 `npx --yes skills list`：后者冷解析约 1.9s 且其结果与文件落点一一等价、本就被
# global_skill_installed 作为权威兜底，属冗余慢操作。
skill_ok=0
skill_total=0
skill_results=()
for entry in "${skills[@]}"; do
  IFS='|' read -r helper_id name baseline_blocking <<<"$entry"
  skill_total=$((skill_total + 1))
  install_cmd="$(build_install_command "$helper_id" "$os")"
  url="$(build_project_url "$helper_id")"

  is_installed="no"
  if global_skill_installed "$name"; then
    is_installed="yes"
  fi

  if [ "$is_installed" = "yes" ]; then
    skill_ok=$((skill_ok + 1))
    skill_results+=("$helper_id|$name|$baseline_blocking|ok|$install_cmd|$url")
  else
    skill_results+=("$helper_id|$name|$baseline_blocking|missing|$install_cmd|$url")
  fi
done

legacy_markdown="skip"
legacy_ce_config="skip"
repo_cfg="skip"
repo_cfg_gitignore="skip"
example_cfg="skip"

if [ "$in_repo" = "yes" ]; then
  repo_root="$(git rev-parse --show-toplevel 2>/dev/null)"
  legacy_markdown="missing"
  if [ -f "$repo_root/compound-engineering.local.md" ]; then
    legacy_markdown="present"
  fi

  legacy_ce_config="missing"
  if [ -f "$repo_root/.compound-engineering/config.local.yaml" ]; then
    legacy_ce_config="present"
  fi

  repo_cfg="missing"
  if [ -f "$repo_root/.spec-first/config.local.yaml" ]; then
    repo_cfg="ok"
  fi

  if [ "$repo_cfg" = "ok" ]; then
    if git check-ignore -q "$repo_root/.spec-first/config.local.yaml" 2>/dev/null; then
      repo_cfg_gitignore="ok"
    else
      repo_cfg_gitignore="missing"
    fi
  fi

  script_dir="$(cd "$(dirname "$0")" && pwd)"
  template="$script_dir/../references/config-template.yaml"
  example="$repo_root/.spec-first/config.local.example.yaml"
  if [ ! -f "$example" ]; then
    example_cfg="missing"
  elif [ -f "$template" ] && ! diff -q "$template" "$example" >/dev/null 2>&1; then
    example_cfg="outdated"
  else
    example_cfg="ok"
  fi
fi

if [ "$json_output" = "yes" ]; then
  printf '{\n'
  printf '  "schema_version": "spec-mcp-setup-preflight.v2",\n'
  printf '  "tools": [\n'
  for index in "${!results[@]}"; do
    IFS='|' read -r name baseline_blocking status install_cmd url <<<"${results[$index]}"
    required="true"
    dependency_status="missing"
    result_status="pending"
    next_action="$install_cmd"
    if [ "$status" = "ok" ]; then
      dependency_status="ready"
      result_status="ready"
      next_action=""
    elif [ "$name" = "agent-browser" ]; then
      if [ "$status" = "agent-browser-cli-ready" ]; then
        dependency_status="ready"
      fi
      result_status="skipped"
      next_action="$BROWSER_HELPER_OPT_IN_ACTION"
    elif [ "$status" = "degraded" ]; then
      dependency_status="missing"
      result_status="degraded"
      next_action="ast-grep missing; falling back to rg"
    elif [ "$baseline_blocking" = "true" ]; then
      result_status="action-required"
    else
      result_status="degraded"
    fi
    printf '    {"id":"%s","required":%s,"baseline_blocking":%s,"dependency_status":"%s","host_config_status":"not-applicable","project_status":"not-applicable","result":"%s","next_action":"%s","install_command":"%s","url":"%s"}' \
      "$(json_escape "$name")" \
      "$required" \
      "$baseline_blocking" \
      "$(json_escape "$dependency_status")" \
      "$(json_escape "$result_status")" \
      "$(json_escape "$next_action")" \
      "$(json_escape "$install_cmd")" \
      "$(json_escape "$url")"
    if [ "$index" -lt $((${#results[@]} - 1)) ]; then
      printf ','
    fi
    printf '\n'
  done
  printf '  ],\n'
  printf '  "skills": [\n'
  for index in "${!skill_results[@]}"; do
    IFS='|' read -r helper_id name baseline_blocking status install_cmd url <<<"${skill_results[$index]}"
    required="true"
    dependency_status="missing"
    result_status="pending"
    next_action="$install_cmd"
    if [ "$status" = "ok" ]; then
      dependency_status="ready"
      result_status="ready"
      next_action=""
    elif [ "$baseline_blocking" = "true" ]; then
      result_status="action-required"
    else
      result_status="degraded"
    fi
    printf '    {"id":"%s","skill_name":"%s","required":%s,"baseline_blocking":%s,"dependency_status":"%s","host_config_status":"not-applicable","project_status":"not-applicable","result":"%s","next_action":"%s","install_command":"%s","url":"%s"}' \
      "$(json_escape "$helper_id")" \
      "$(json_escape "$name")" \
      "$required" \
      "$baseline_blocking" \
      "$(json_escape "$dependency_status")" \
      "$(json_escape "$result_status")" \
      "$(json_escape "$next_action")" \
      "$(json_escape "$install_cmd")" \
      "$(json_escape "$url")"
    if [ "$index" -lt $((${#skill_results[@]} - 1)) ]; then
      printf ','
    fi
    printf '\n'
  done
  printf '  ],\n'
  printf '  "project": {"inside_git_repo":%s,"local_config_status":"%s","local_config_gitignore_status":"%s","example_config_status":"%s"},\n' \
    "$([ "$in_repo" = "yes" ] && echo true || echo false)" \
    "$(json_escape "$repo_cfg")" \
    "$(json_escape "$repo_cfg_gitignore")" \
    "$(json_escape "$example_cfg")"
  printf '  "legacy": {"compound_engineering_markdown_status":"%s","compound_engineering_config_status":"%s"}\n' \
    "$(json_escape "$legacy_markdown")" \
    "$(json_escape "$legacy_ce_config")"
  printf '}\n'
  exit 0
fi

echo ""
if [ -n "$plugin_version" ]; then
  ok "Spec-First version v${plugin_version}"
fi

section "Tool install status  ${cli_ok}/${cli_total}"
printf "  %-15s %-9s %-10s\n" "Tool" "Required" "Status"
printf "  %-15s %-9s %-10s\n" "----" "--------" "------"

for result in "${results[@]}"; do
  IFS='|' read -r name baseline_blocking status install_cmd url <<<"$result"
  printf "  %-15s %-9s %-10s\n" "$name" "$(required_label required)" "$(status_label "$status")"
  if [ "$status" = "ok" ]; then
    continue
  elif [ "$name" = "agent-browser" ]; then
    if [ -n "$install_cmd" ]; then
      detail "$install_cmd"
    fi
    if [ -n "$url" ]; then
      detail "$url"
    fi
    continue
  else
    issues=$((issues + 1))
    if [ -n "$install_cmd" ]; then
      if [[ "$install_cmd" == *"brew install"* ]] && [ "$has_brew" != "yes" ]; then
        detail "$url"
      else
        detail "$install_cmd"
      fi
    fi
    if [ -n "$url" ]; then
      detail "$url"
    fi
  fi
done

if [ "${#skills[@]}" -gt 0 ]; then
  section "Skill install status  ${skill_ok}/${skill_total}"
  printf "  %-15s %-9s %-10s\n" "Skill" "Required" "Status"
  printf "  %-15s %-9s %-10s\n" "-----" "--------" "------"

  for result in "${skill_results[@]}"; do
    IFS='|' read -r helper_id name baseline_blocking status install_cmd url <<<"$result"
    printf "  %-15s %-9s %-10s\n" "$name" "$(required_label required)" "$(status_label "$status")"
    if [ "$status" = "ok" ]; then
      continue
    fi
    issues=$((issues + 1))
    detail "$install_cmd"
    detail "$url"
  done
fi

if [ "$in_repo" = "yes" ]; then
  has_project_issues="no"
  [ "$legacy_markdown" = "present" ] && has_project_issues="yes"
  [ "$legacy_ce_config" = "present" ] && has_project_issues="yes"
  [ "$repo_cfg_gitignore" = "missing" ] && has_project_issues="yes"
  case "$example_cfg" in
    missing|outdated)
      has_project_issues="yes"
      ;;
  esac

  if [ "$has_project_issues" = "yes" ]; then
    section "Project"

    if [ "$legacy_markdown" = "present" ]; then
      warn "Outdated Compound Engineering config in this repo"
      issues=$((issues + 1))
    fi

    if [ "$legacy_ce_config" = "present" ]; then
      warn "Legacy Compound Engineering local config detected (.compound-engineering/config.local.yaml)"
      issues=$((issues + 1))
    fi

    if [ "$repo_cfg" = "missing" ]; then
      detail "Optional local config not created (.spec-first/config.local.yaml)"
    fi

    if [ "$repo_cfg_gitignore" = "missing" ]; then
      warn "Local config not safely gitignored"
      issues=$((issues + 1))
    fi

    if [ "$example_cfg" = "missing" ]; then
      warn "Example config missing (.spec-first/config.local.example.yaml)"
      issues=$((issues + 1))
      detail "bash \"$script_dir/bootstrap-project-config.sh\" --repo \"$repo_root\" --refresh-example"
    elif [ "$example_cfg" = "outdated" ]; then
      warn "Example config outdated (.spec-first/config.local.example.yaml)"
      issues=$((issues + 1))
      detail "bash \"$script_dir/bootstrap-project-config.sh\" --repo \"$repo_root\" --refresh-example"
    fi
  fi
fi

echo ""
if [ "$issues" -eq 0 ]; then
  echo " ✅  All clear  ${cli_ok}/${cli_total} tools  ${skill_ok}/${skill_total} skills"
else
  echo " ⚠️   ${issues} issue(s) found  ${cli_ok}/${cli_total} tools  ${skill_ok}/${skill_total} skills"
fi

echo ""
