#!/usr/bin/env bash
set -euo pipefail

INSTALL_DIR=""

usage() {
  cat <<'USAGE'
Usage:
  bash healthcheck.sh [--install-dir /opt/tg-sales-archive]
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --install-dir)
      INSTALL_DIR="${2:-}"
      shift 2
      ;;
    --install-dir=*)
      INSTALL_DIR="${1#*=}"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      usage
      exit 1
      ;;
  esac
done

if [[ -z "$INSTALL_DIR" ]]; then
  if [[ -f ./docker-compose.prod.yml ]]; then
    INSTALL_DIR="$(pwd)"
  else
    INSTALL_DIR="/opt/tg-sales-archive"
  fi
fi

cd "$INSTALL_DIR"

COMPOSE=(docker compose -f "$INSTALL_DIR/docker-compose.prod.yml")
FAILURES=0

ok() {
  echo "[OK] $1"
}

warn() {
  echo "[WARN] $1"
}

fail() {
  echo "[FAIL] $1"
  FAILURES=$((FAILURES + 1))
}

if docker info >/dev/null 2>&1; then
  ok "Docker is running"
else
  fail "Docker is not running"
fi

if docker compose version >/dev/null 2>&1; then
  ok "Docker Compose is available"
else
  fail "Docker Compose plugin is unavailable"
fi

"${COMPOSE[@]}" ps || fail "docker compose ps failed"

health_status() {
  local service="$1"
  local container_id
  container_id="$("${COMPOSE[@]}" ps -q "$service" || true)"
  if [[ -z "$container_id" ]]; then
    fail "$service container not found"
    return
  fi

  local status
  status="$(docker inspect --format '{{ if .State.Health }}{{ .State.Health.Status }}{{ else }}none{{ end }}' "$container_id" 2>/dev/null || true)"
  if [[ "$status" == "healthy" ]]; then
    ok "$service healthy"
  else
    fail "$service health status: ${status:-unknown}"
  fi
}

running_status() {
  local service="$1"
  local container_id
  container_id="$("${COMPOSE[@]}" ps -q "$service" || true)"
  if [[ -z "$container_id" ]]; then
    fail "$service container not found"
    return
  fi

  local running
  running="$(docker inspect --format '{{ .State.Running }}' "$container_id" 2>/dev/null || true)"
  if [[ "$running" == "true" ]]; then
    ok "$service is running"
  else
    fail "$service is not running"
  fi
}

health_status mysql
health_status redis
running_status backend
running_status backend-scheduler

check_http() {
  local name="$1"
  local url="$2"
  local expected="$3"
  local response_file code
  response_file="$(mktemp)"
  code="$(curl -sS -o "$response_file" -w '%{http_code}' "$url" || true)"

  if [[ "$expected" == "json" && "$code" == "200" ]]; then
    local phase
    phase="$(grep -o '"phase":"[^"]*"' "$response_file" | head -n 1 | cut -d: -f2 | tr -d '"' || true)"
    ok "$name: ${phase:-HTTP 200}"
  elif [[ "$expected" == "login" && ( "$code" == "200" || "$code" == "302" ) ]]; then
    ok "$name: HTTP $code"
  else
    fail "$name returned HTTP ${code:-000}"
  fi

  rm -f "$response_file"
}

check_http "Backend health" "http://127.0.0.1:8080/api/health" json
check_http "Internal health" "http://127.0.0.1:8080/internal/health" json
check_http "Login page" "http://127.0.0.1:8080/login" login

if "${COMPOSE[@]}" logs --tail=100 backend 2>/dev/null | grep -Eiq '\b(ERROR|CRITICAL|PDOException|QueryException)\b'; then
  warn "Backend logs contain ERROR/CRITICAL markers in recent 100 lines. Review with: docker compose -f docker-compose.prod.yml logs --tail=100 backend"
else
  ok "Backend recent logs have no obvious ERROR markers"
fi

if [[ "$FAILURES" -eq 0 ]]; then
  ok "Deployment looks healthy"
else
  echo "[FAIL] Deployment healthcheck failed with $FAILURES issue(s)."
  exit 1
fi
