#!/usr/bin/env bash
# SessionStart hook for ha-nova plugin
# Auto-loads the ha-nova context skill into every Claude Code session.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

# Read context skill content
context_skill_content=$(cat "${PLUGIN_ROOT}/skills/ha-nova/SKILL.md" 2>&1 || echo "Error reading ha-nova context skill")

# Escape string for JSON embedding
escape_for_json() {
    local s="$1"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//$'\n'/\\n}"
    s="${s//$'\r'/\\r}"
    s="${s//$'\t'/\\t}"
    s="${s//$'\b'/\\b}"
    s="${s//$'\f'/\\f}"
    printf '%s' "$s"
}

context_escaped=$(escape_for_json "$context_skill_content")

# Build sub-skill list dynamically from skills/ directories (exclude ha-nova context skill itself)
sub_skills=""
for skill_dir in "${PLUGIN_ROOT}"/skills/*/SKILL.md; do
  skill_name=$(basename "$(dirname "$skill_dir")")
  [[ "$skill_name" == "ha-nova" ]] && continue
  [[ -n "$sub_skills" ]] && sub_skills="${sub_skills}, "
  sub_skills="${sub_skills}ha-nova:${skill_name}"
done

session_context="HA NOVA context skill auto-loaded. Sub-skills (${sub_skills}) are discovered independently by description.\\n\\n${context_escaped}"

# ---------------------------------------------------------------------------
# Relay version check
# ---------------------------------------------------------------------------

# NOTE: duplicate of semver_lt in scripts/onboarding/lib/relay.sh (can't source across contexts)
semver_lt() {
  # shellcheck disable=SC2206
  local IFS='.'; local -a a=($1) b=($2)
  for i in 0 1 2; do
    local ai="${a[$i]:-0}" bi="${b[$i]:-0}"
    (( ai < bi )) && return 0; (( ai > bi )) && return 1
  done
  return 1
}

extract_json_string() {
  local key="$1" json="$2"
  local match
  match=$(echo "$json" | grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" 2>/dev/null | head -1) || true
  [[ -z "$match" ]] && return 0
  echo "$match" | sed 's/.*"\([^"]*\)"$/\1/'
}

version_warning=""
update_notice=""
version_file="${PLUGIN_ROOT}/version.json"
if [[ -f "$version_file" ]]; then
  version_json=$(cat "$version_file")
  SKILL_VERSION=$(extract_json_string "skill_version" "$version_json")
  MIN_RELAY_VERSION=$(extract_json_string "min_relay_version" "$version_json")

  # --- Relay version check ---
  if command -v ha-nova >/dev/null 2>&1; then
    # `relay health` accepts curl-compatible --connect-timeout/--max-time
    # (seconds); keep this probe tight so a dead relay never blocks session start.
    health_json="$(ha-nova relay health --connect-timeout 1 --max-time 2 2>/dev/null || true)"
    if [[ -z "$health_json" ]]; then
      version_warning="[ha-nova] WARNING: Relay unreachable. Check relay status or run: ha-nova doctor\\n"
    elif [[ -n "$MIN_RELAY_VERSION" ]]; then
      relay_version=$(extract_json_string "version" "$health_json")
      if [[ -n "$relay_version" && "$relay_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && semver_lt "$relay_version" "$MIN_RELAY_VERSION"; then
        version_warning="[ha-nova] WARNING: Relay version ${relay_version} is below minimum ${MIN_RELAY_VERSION}. Update: HA Settings > Apps > NOVA Relay > Update\\n"
      fi
    fi
  fi
  # No relay CLI = not onboarded yet, skip silently

  # --- Cached release update check (stale-while-revalidate via CLI) ---
  # This TTL only throttles how often we spawn the background CLI refresh; the
  # CLI owns real freshness (short floor + conditional revalidation). Keep it
  # <= the CLI's updateCacheTTLSeconds (cli/paths.go), otherwise a new release
  # stays hidden from the session banner until this longer window expires.
  update_cache_dir="${HOME}/.cache/ha-nova"
  update_cache_file="${update_cache_dir}/latest-release.json"
  update_ttl=3600

  needs_refresh="1"
  if [[ -f "$update_cache_file" ]]; then
    # Read cached latest version (stale is OK — show it now, refresh in background)
    cached_json=$(cat "$update_cache_file" 2>/dev/null || true)
    latest_skill_version=$(extract_json_string "version" "$cached_json")
    if [[ -n "$latest_skill_version" && "$latest_skill_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ && -n "$SKILL_VERSION" ]] && semver_lt "$SKILL_VERSION" "$latest_skill_version"; then
      if command -v ha-nova >/dev/null 2>&1; then
        # A locally dev-synced build (`ha-nova version` reports "local DEV build")
        # must not be nudged to update — that would overwrite the dev tree. The
        # release path is unaffected: released binaries omit the marker.
        if ! ha-nova version 2>/dev/null | grep -q "local DEV build"; then
          update_notice="[ha-nova] UPDATE AVAILABLE: v${SKILL_VERSION} -> v${latest_skill_version}. Ask the user if they want you to run: ha-nova update (new session required after update)\\n"
        fi
      else
        update_notice="[ha-nova] UPDATE AVAILABLE: v${SKILL_VERSION} -> v${latest_skill_version}. Repo-dev fallback only: update the local checkout manually, then re-run setup. (new session required after update)\\n"
      fi
    fi

    # Check if cache is still fresh
    if [[ "$(uname)" == "Darwin" ]]; then
      cache_mtime=$(stat -f %m "$update_cache_file" 2>/dev/null || echo 0)
    else
      cache_mtime=$(stat -c %Y "$update_cache_file" 2>/dev/null || echo 0)
    fi
    now=$(date +%s)
    if (( now - cache_mtime < update_ttl )); then
      needs_refresh="0"
    fi
  fi

  # Background refresh: fire-and-forget through the shared CLI contract.
  if [[ "$needs_refresh" == "1" ]] && command -v ha-nova >/dev/null 2>&1; then
    mkdir -p "$update_cache_dir" 2>/dev/null || true
    (ha-nova check-update --quiet --json >/dev/null 2>&1 || true) &
    disown 2>/dev/null || true
  fi
fi

# Background auto-repair: silently reattach drifted clients (e.g., a Claude
# Code update wiped the marketplace registration). Fire-and-forget so this
# session starts immediately; the repair lands in time for the next session.
if command -v ha-nova >/dev/null 2>&1; then
  (ha-nova doctor --auto-repair --quiet >/dev/null 2>&1 || true) &
  disown 2>/dev/null || true
fi

if [[ -n "$update_notice" ]]; then
  session_context="${update_notice}\\n${session_context}"
fi

if [[ -n "$version_warning" ]]; then
  session_context="${version_warning}\\n${session_context}"
fi

if [[ -n "${SKILL_VERSION:-}" ]]; then
  session_context="HA NOVA Skills v${SKILL_VERSION}\\n${session_context}"
fi

cat <<EOF
{
  "additional_context": "${session_context}",
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "${session_context}"
  }
}
EOF

exit 0
