#!/usr/bin/env bash
#
# stack-health.sh — Check health of all configured Mosaic stack services
#
# Usage: stack-health.sh [-f format] [-s service] [-q]
#
# Checks connectivity to all services configured in credentials.json.
# For each service, makes a lightweight API call and reports status.
#
# Options:
#   -f format    Output format: table (default), json
#   -s service   Check only a specific service
#   -q           Quiet — exit code only (0=all healthy, 1=any unhealthy)
#   -h           Show this help
set -euo pipefail

MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
source "$MOSAIC_HOME/tools/_lib/credentials.sh"

FORMAT="table"
SINGLE_SERVICE=""
QUIET=false
CRED_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/.config/mosaic/credentials.json}"

while getopts "f:s:qh" opt; do
  case $opt in
    f) FORMAT="$OPTARG" ;;
    s) SINGLE_SERVICE="$OPTARG" ;;
    q) QUIET=true ;;
    h) head -15 "$0" | grep "^#" | sed 's/^# \?//'; exit 0 ;;
    *) echo "Usage: $0 [-f format] [-s service] [-q]" >&2; exit 1 ;;
  esac
done

if [[ ! -f "$CRED_FILE" ]]; then
  echo "Error: Credentials file not found: $CRED_FILE" >&2
  exit 1
fi

# Colors (disabled if not a terminal or quiet mode)
if [[ -t 1 ]] && [[ "$QUIET" == "false" ]]; then
  GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' RESET='\033[0m'
else
  GREEN='' RED='' YELLOW='' RESET=''
fi

TOTAL=0
HEALTHY=0
RESULTS="[]"

check_service() {
  local name="$1"
  local display_name="$2"
  local url="$3"
  local endpoint="$4"
  local auth_header="$5"
  local insecure="${6:-false}"

  TOTAL=$((TOTAL + 1))

  local curl_args=(-s -o /dev/null -w "%{http_code} %{time_total}" --connect-timeout 5 --max-time 10)
  [[ -n "$auth_header" ]] && curl_args+=(-H "$auth_header")
  [[ "$insecure" == "true" ]] && curl_args+=(-k)

  local result
  result=$(curl "${curl_args[@]}" "${url}${endpoint}" 2>/dev/null) || result="000 0.000"

  local http_code response_time status_text
  http_code=$(echo "$result" | awk '{print $1}')
  response_time=$(echo "$result" | awk '{print $2}')

  if [[ "$http_code" -ge 200 && "$http_code" -lt 400 ]]; then
    status_text="UP"
    HEALTHY=$((HEALTHY + 1))
  elif [[ "$http_code" == "000" ]]; then
    status_text="DOWN"
  elif [[ "$http_code" == "401" || "$http_code" == "403" ]]; then
    # Auth error but service is reachable
    status_text="AUTH_ERR"
    HEALTHY=$((HEALTHY + 1))  # Service is up, just auth issue
  else
    status_text="ERROR"
  fi

  # Append to JSON results
  RESULTS=$(echo "$RESULTS" | jq --arg n "$name" --arg d "$display_name" \
    --arg u "$url" --arg s "$status_text" --arg c "$http_code" --arg t "$response_time" \
    '. + [{name: $n, display_name: $d, url: $u, status: $s, http_code: ($c | tonumber), response_time: $t}]')

  if [[ "$QUIET" == "false" && "$FORMAT" == "table" ]]; then
    local color="$GREEN"
    [[ "$status_text" == "DOWN" || "$status_text" == "ERROR" ]] && color="$RED"
    [[ "$status_text" == "AUTH_ERR" ]] && color="$YELLOW"
    printf "  %-22s  %-35s  ${color}%-8s${RESET}  %ss\n" \
      "$display_name" "$url" "$status_text" "$response_time"
  fi
}

# Discover and check services
[[ "$QUIET" == "false" && "$FORMAT" == "table" ]] && {
  echo ""
  echo "  SERVICE                 URL                                  STATUS    RESPONSE"
  echo "  ----------------------  -----------------------------------  --------  --------"
}

# Portainer
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "portainer" ]]; then
  portainer_url=$(jq -r '.portainer.url // empty' "$CRED_FILE")
  portainer_key=$(jq -r '.portainer.api_key // empty' "$CRED_FILE")
  if [[ -n "$portainer_url" ]]; then
    check_service "portainer" "Portainer" "$portainer_url" "/api/system/status" \
      "X-API-Key: $portainer_key" "true"
  fi
fi

# Coolify
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "coolify" ]]; then
  coolify_url=$(jq -r '.coolify.url // empty' "$CRED_FILE")
  coolify_token=$(jq -r '.coolify.app_token // empty' "$CRED_FILE")
  if [[ -n "$coolify_url" ]]; then
    check_service "coolify" "Coolify" "$coolify_url" "/api/v1/teams" \
      "Authorization: Bearer $coolify_token" "false"
  fi
fi

# Authentik
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "authentik" ]]; then
  authentik_url=$(jq -r '.authentik.url // empty' "$CRED_FILE")
  if [[ -n "$authentik_url" ]]; then
    check_service "authentik" "Authentik" "$authentik_url" "/-/health/ready/" "" "true"
  fi
fi

# GLPI
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "glpi" ]]; then
  glpi_url=$(jq -r '.glpi.url // empty' "$CRED_FILE")
  if [[ -n "$glpi_url" ]]; then
    check_service "glpi" "GLPI" "$glpi_url" "/" "" "true"
  fi
fi

# Gitea instances
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "gitea" ]]; then
  for instance in mosaicstack usc; do
    gitea_url=$(jq -r ".gitea.${instance}.url // empty" "$CRED_FILE")
    if [[ -n "$gitea_url" ]]; then
      display="Gitea (${instance})"
      check_service "gitea-${instance}" "$display" "$gitea_url" "/api/v1/version" "" "true"
    fi
  done
fi

# GitHub
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "github" ]]; then
  github_token=$(jq -r '.github.token // empty' "$CRED_FILE")
  if [[ -n "$github_token" ]]; then
    check_service "github" "GitHub" "https://api.github.com" "/rate_limit" \
      "Authorization: Bearer $github_token" "false"
  fi
fi

# Woodpecker
if [[ -z "$SINGLE_SERVICE" || "$SINGLE_SERVICE" == "woodpecker" ]]; then
  woodpecker_url=$(jq -r '.woodpecker.url // empty' "$CRED_FILE")
  woodpecker_token=$(jq -r '.woodpecker.token // empty' "$CRED_FILE")
  if [[ -n "$woodpecker_url" && -n "$woodpecker_token" ]]; then
    check_service "woodpecker" "Woodpecker CI" "$woodpecker_url" "/api/user" \
      "Authorization: Bearer $woodpecker_token" "true"
  elif [[ "$QUIET" == "false" && "$FORMAT" == "table" ]]; then
    printf "  %-22s  %-35s  ${YELLOW}%-8s${RESET}  %s\n" \
      "Woodpecker CI" "—" "NOTOKEN" "—"
  fi
fi

# Output
if [[ "$FORMAT" == "json" ]]; then
  jq -n --argjson results "$RESULTS" --argjson total "$TOTAL" --argjson healthy "$HEALTHY" \
    '{total: $total, healthy: $healthy, results: $results}'
  exit 0
fi

if [[ "$QUIET" == "false" && "$FORMAT" == "table" ]]; then
  echo ""
  UNHEALTHY=$((TOTAL - HEALTHY))
  if [[ "$UNHEALTHY" -eq 0 ]]; then
    echo -e "  ${GREEN}All $TOTAL services healthy${RESET}"
  else
    echo -e "  ${RED}$UNHEALTHY/$TOTAL services unhealthy${RESET}"
  fi
  echo ""
fi

# Exit code: 0 if all healthy, 1 if any unhealthy
[[ "$HEALTHY" -eq "$TOTAL" ]]
