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

set -euo pipefail

plugin_version=""
json_output="no"
BROWSER_HELPER_OPT_IN_ACTION="set SPEC_FIRST_BROWSER_HELPER_REQUIRED=1 and rerun spec-mcp-setup install"
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
}

linux_package_install_command() {
  local apt_pkg="$1"
  local dnf_pkg="$2"
  local yum_pkg="$3"
  local pacman_pkg="$4"
  local apk_pkg="$5"

  if command -v apt-get >/dev/null 2>&1; then
    echo "sudo apt-get update && sudo apt-get install -y $apt_pkg"
  elif command -v dnf >/dev/null 2>&1; then
    echo "if sudo dnf upgrade -y $dnf_pkg; then true; else sudo dnf install -y $dnf_pkg; fi"
  elif command -v yum >/dev/null 2>&1; then
    echo "if sudo yum update -y $yum_pkg; then true; else sudo yum install -y $yum_pkg; fi"
  elif command -v pacman >/dev/null 2>&1; then
    echo "sudo pacman -Syu --needed $pacman_pkg"
  elif command -v apk >/dev/null 2>&1; then
    echo "sudo apk update && sudo apk add --upgrade $apk_pkg"
  else
    echo ""
  fi
}

brew_latest_install_command() {
  local pkg="$1"
  echo "brew update && if brew list --formula $pkg >/dev/null 2>&1; then brew upgrade -q $pkg; else brew install -q $pkg; fi"
}

winget_latest_install_command() {
  local package_id="$1"
  echo "if winget upgrade --id $package_id -e --silent --accept-package-agreements --accept-source-agreements; then true; else winget install --id $package_id -e --silent --accept-package-agreements --accept-source-agreements; fi"
}

build_install_command() {
  local name="$1"
  local os="$2"
  local linux_cmd

  case "$name" in
    agent-browser)
      echo "$BROWSER_HELPER_OPT_IN_ACTION"
      ;;
    gh)
      if [ "$os" = "windows" ]; then
        winget_latest_install_command "GitHub.cli"
      elif [ "$os" = "linux" ]; then
        linux_cmd="$(linux_package_install_command gh gh gh github-cli github-cli)"
        echo "${linux_cmd:-Install gh from https://cli.github.com}"
      else
        brew_latest_install_command "gh"
      fi
      ;;
    jq)
      if [ "$os" = "windows" ]; then
        winget_latest_install_command "jqlang.jq"
      elif [ "$os" = "linux" ]; then
        linux_cmd="$(linux_package_install_command jq jq jq jq jq)"
        echo "${linux_cmd:-Install jq from https://jqlang.github.io/jq/}"
      else
        brew_latest_install_command "jq"
      fi
      ;;
    vhs)
      if [ "$os" = "linux" ] || [ "$os" = "windows" ]; then
        if command -v go >/dev/null 2>&1; then
          echo "go install github.com/charmbracelet/vhs@latest"
        else
          echo "Install vhs from https://github.com/charmbracelet/vhs"
        fi
      else
        brew_latest_install_command "vhs"
      fi
      ;;
    silicon)
      if [ "$os" = "linux" ] || [ "$os" = "windows" ]; then
        if command -v cargo >/dev/null 2>&1; then
          echo "cargo install silicon --force"
        else
          echo "Install silicon from https://github.com/Aloxaf/silicon"
        fi
      else
        brew_latest_install_command "silicon"
      fi
      ;;
    ffmpeg)
      if [ "$os" = "windows" ]; then
        winget_latest_install_command "Gyan.FFmpeg"
      elif [ "$os" = "linux" ]; then
        linux_cmd="$(linux_package_install_command ffmpeg ffmpeg ffmpeg ffmpeg ffmpeg)"
        echo "${linux_cmd:-Install ffmpeg from https://ffmpeg.org/download.html}"
      else
        brew_latest_install_command "ffmpeg"
      fi
      ;;
    ast-grep)
      if [ "$os" = "windows" ]; then
        echo "npm install -g @ast-grep/cli@latest"
      elif [ "$os" = "linux" ]; then
        if command -v cargo >/dev/null 2>&1; then
          echo "cargo install ast-grep --locked --force"
        elif command -v npm >/dev/null 2>&1; then
          echo "npm install -g @ast-grep/cli@latest"
        else
          echo "Install ast-grep from https://ast-grep.github.io"
        fi
      else
        brew_latest_install_command "ast-grep"
      fi
      ;;
    ast-grep-skill)
      echo "npx -y skills@latest add ast-grep/agent-skill -g -y"
      ;;
    *)
      echo ""
      ;;
  esac
}

build_project_url() {
  local name="$1"
  case "$name" in
    agent-browser) echo "https://github.com/vercel-labs/agent-browser" ;;
    gh) echo "https://cli.github.com" ;;
    jq) echo "https://jqlang.github.io/jq/" ;;
    vhs) echo "https://github.com/charmbracelet/vhs" ;;
    silicon) echo "https://github.com/Aloxaf/silicon" ;;
    ffmpeg) echo "https://ffmpeg.org/download.html" ;;
    ast-grep|ast-grep-skill) echo "https://ast-grep.github.io" ;;
    *) echo "" ;;
  esac
}

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" ;;
    *) 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=(
  "agent-browser|required"
  "gh|required"
  "jq|required"
  "vhs|required"
  "silicon|required"
  "ffmpeg|required"
  "ast-grep|required"
)

skills=(
  "ast-grep|required"
)

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

for entry in "${deps[@]}"; do
  IFS='|' read -r name tier <<<"$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|$tier|ok|$install_cmd|$url")
    elif command -v agent-browser >/dev/null 2>&1; then
      cli_ok=$((cli_ok + 1))
      results+=("$name|$tier|agent-browser-cli-ready|$install_cmd|$url")
    else
      results+=("$name|$tier|missing|$install_cmd|$url")
    fi
  elif command -v "$name" >/dev/null 2>&1; then
    cli_ok=$((cli_ok + 1))
    results+=("$name|$tier|ok|$install_cmd|$url")
  else
    results+=("$name|$tier|missing|$install_cmd|$url")
  fi
done

has_npx="no"
has_jq="no"
command -v npx >/dev/null 2>&1 && has_npx="yes"
command -v jq >/dev/null 2>&1 && has_jq="yes"

installed_skill_names=""
if [ "$has_npx" = "yes" ] && [ "$has_jq" = "yes" ]; then
  installed_skill_names="$(npx --yes skills list --global --json 2>/dev/null | jq -r '.[].name' 2>/dev/null || true)"
fi

skill_ok=0
skill_total=0
skill_results=()
for entry in "${skills[@]}"; do
  IFS='|' read -r name tier <<<"$entry"
  skill_total=$((skill_total + 1))
  install_cmd="$(build_install_command "${name}-skill" "$os")"
  url="$(build_project_url "${name}-skill")"

  is_installed="no"
  if [ -n "$installed_skill_names" ]; then
    if printf '%s\n' "$installed_skill_names" | grep -qx "$name"; then
      is_installed="yes"
    fi
  fi

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

  if [ "$is_installed" = "yes" ]; then
    skill_ok=$((skill_ok + 1))
    skill_results+=("$name|$tier|ok|$install_cmd|$url")
  else
    skill_results+=("$name|$tier|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 tier status install_cmd url <<<"${results[$index]}"
    required="false"
    if [ "$tier" = "required" ]; then
      required="true"
    fi
    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 [ "$tier" = "required" ]; then
      result_status="action-required"
    fi
    printf '    {"id":"%s","required":%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" \
      "$(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 name tier status install_cmd url <<<"${skill_results[$index]}"
    required="false"
    if [ "$tier" = "required" ]; then
      required="true"
    fi
    dependency_status="missing"
    result_status="pending"
    next_action="$install_cmd"
    if [ "$status" = "ok" ]; then
      dependency_status="ready"
      result_status="ready"
      next_action=""
    elif [ "$tier" = "required" ]; then
      result_status="action-required"
    fi
    printf '    {"id":"%s","required":%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" \
      "$(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 tier status install_cmd url <<<"$result"
  printf "  %-15s %-9s %-10s\n" "$name" "$(required_label "$tier")" "$(status_label "$status")"
  if [ "$status" = "ok" ]; then
    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 name tier status install_cmd url <<<"$result"
    printf "  %-15s %-9s %-10s\n" "$name" "$(required_label "$tier")" "$(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"
  for state in "$legacy_markdown" "$legacy_ce_config" "$repo_cfg" "$repo_cfg_gitignore" "$example_cfg"; do
    case "$state" in
      present|missing|outdated)
        has_project_issues="yes"
        ;;
    esac
  done

  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
      warn "Local config missing (.spec-first/config.local.yaml)"
      issues=$((issues + 1))
    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))
    elif [ "$example_cfg" = "outdated" ]; then
      warn "Example config outdated (.spec-first/config.local.example.yaml)"
      issues=$((issues + 1))
    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 ""
