#!/usr/bin/env bash
# ACP smoke test for sandbox execution verification.
#
# Tests the ACP JSON-RPC contract (task/create, event/send, task/cancel)
# against a running agent pod. Works with any sandbox executor.
#
# Extracted from PR #241 (sandbox-sidecar-mvp).
#
# Usage:
#   AGENT_API_KEY=<key> ./run_acp_smoke.sh
#
# Environment:
#   AGENT_API_KEY       - Required. API key for x-agent-api-key header.
#   KUBE_CONTEXT        - Kubernetes context (default: minikube)
#   NAMESPACE           - Namespace to find agent pod (default: platform-ns-test)
#   POD_NAME            - Specific pod name (default: auto-detect)
#   LOCAL_PORT          - Local port for port-forward (default: 18080)
#   RUN_AUTH_FAILURE_CHECK - Test invalid auth (default: true)
#   ALLOW_NON_MINIKUBE  - Allow non-minikube contexts (default: false)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

KUBE_CONTEXT="${KUBE_CONTEXT:-minikube}"
ALLOW_NON_MINIKUBE="${ALLOW_NON_MINIKUBE:-false}"
NAMESPACE="${NAMESPACE:-platform-ns-test}"
POD_NAME="${POD_NAME:-}"
AGENT_API_KEY="${AGENT_API_KEY:-}"
EVENT_TEXT="${EVENT_TEXT:-acp smoke test probe}"
LOCAL_PORT="${LOCAL_PORT:-18080}"
RUN_AUTH_FAILURE_CHECK="${RUN_AUTH_FAILURE_CHECK:-true}"

# Validate dependencies
for cmd in kubectl curl python3; do
  if ! command -v "${cmd}" >/dev/null 2>&1; then
    echo "ERROR: ${cmd} is required"
    exit 1
  fi
done

if [[ -z "${AGENT_API_KEY}" ]]; then
  echo "ERROR: AGENT_API_KEY is required"
  exit 1
fi

# Validate context
CURRENT_CONTEXT="$(kubectl config current-context 2>/dev/null || echo "")"
if [[ "${CURRENT_CONTEXT}" != "${KUBE_CONTEXT}" ]]; then
  echo "ERROR: current context is '${CURRENT_CONTEXT:-none}', expected '${KUBE_CONTEXT}'."
  exit 1
fi

if [[ "${KUBE_CONTEXT}" != "minikube" && "${ALLOW_NON_MINIKUBE}" != "true" ]]; then
  echo "ERROR: refusing non-minikube context '${KUBE_CONTEXT}' without ALLOW_NON_MINIKUBE=true."
  exit 1
fi

# Auto-detect pod if not specified
if [[ -z "${POD_NAME}" ]]; then
  mapfile -t CANDIDATE_PODS < <(
    kubectl --context="${KUBE_CONTEXT}" -n "${NAMESPACE}" \
      get pods -l terminaluse.com/managed-by=nucleus \
      -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | sed '/^$/d'
  )
  if [[ "${#CANDIDATE_PODS[@]}" -eq 1 ]]; then
    POD_NAME="${CANDIDATE_PODS[0]}"
    echo "==> Auto-detected pod: ${POD_NAME}"
  elif [[ "${#CANDIDATE_PODS[@]}" -gt 1 ]]; then
    echo "ERROR: Multiple managed pods found. Set POD_NAME explicitly."
    printf 'Candidates:\n%s\n' "${CANDIDATE_PODS[@]}"
    exit 1
  else
    echo "ERROR: No managed pods found in namespace '${NAMESPACE}'."
    exit 1
  fi
fi

# Verify pod is ready
READY="$(kubectl --context="${KUBE_CONTEXT}" -n "${NAMESPACE}" get pod "${POD_NAME}" \
  -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "False")"
if [[ "${READY}" != "True" ]]; then
  echo "ERROR: Pod '${POD_NAME}' is not ready."
  exit 1
fi

MAIN_CONTAINER="$(kubectl --context="${KUBE_CONTEXT}" -n "${NAMESPACE}" get pod "${POD_NAME}" \
  -o jsonpath='{.spec.containers[0].name}')"
START_TIME="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"

# Port-forward setup
PF_LOG="/tmp/acp-smoke-pf-${POD_NAME}.log"
rm -f "${PF_LOG}"

cleanup() {
  if [[ -n "${PF_PID:-}" ]] && kill -0 "${PF_PID}" >/dev/null 2>&1; then
    kill "${PF_PID}" >/dev/null 2>&1 || true
    wait "${PF_PID}" 2>/dev/null || true
  fi
}
trap cleanup EXIT

kubectl --context="${KUBE_CONTEXT}" -n "${NAMESPACE}" port-forward "pod/${POD_NAME}" "${LOCAL_PORT}:8000" >"${PF_LOG}" 2>&1 &
PF_PID=$!

echo "==> Waiting for ACP healthz on localhost:${LOCAL_PORT}"
for _ in $(seq 1 40); do
  if curl -fsS "http://127.0.0.1:${LOCAL_PORT}/healthz" >/dev/null 2>&1; then
    break
  fi
  sleep 0.5
done

if ! curl -fsS "http://127.0.0.1:${LOCAL_PORT}/healthz" >/dev/null 2>&1; then
  echo "ERROR: Failed to reach ACP endpoint through port-forward."
  echo "port-forward logs:"
  cat "${PF_LOG}" || true
  exit 1
fi
echo "==> ACP endpoint reachable"

# Auth failure check
if [[ "${RUN_AUTH_FAILURE_CHECK}" == "true" ]]; then
  echo "==> Running auth failure check (invalid API key)"
  set +e
  python3 "${SCRIPT_DIR}/acp_probe.py" \
    --acp-url "http://127.0.0.1:${LOCAL_PORT}/api" \
    --agent-api-key "${AGENT_API_KEY}-invalid" \
    --event-text "${EVENT_TEXT}" >/dev/null 2>&1
  AUTH_STATUS=$?
  set -e
  if [[ "${AUTH_STATUS}" -eq 0 ]]; then
    echo "ERROR: Auth failure check passed unexpectedly (should have failed)."
    exit 1
  fi
  echo "==> Auth failure check passed (invalid key rejected)"
fi

# Main ACP probe
echo "==> Running ACP probe (task/create -> event/send -> task/cancel)"
PROBE_OUTPUT="$(python3 "${SCRIPT_DIR}/acp_probe.py" \
  --acp-url "http://127.0.0.1:${LOCAL_PORT}/api" \
  --agent-api-key "${AGENT_API_KEY}" \
  --event-text "${EVENT_TEXT}")"

echo "${PROBE_OUTPUT}"

TASK_ID="$(sed -n 's/^PROBE_TASK_ID=//p' <<<"${PROBE_OUTPUT}" | tail -n1)"
if [[ -z "${TASK_ID}" ]]; then
  echo "ERROR: Failed to parse PROBE_TASK_ID from probe output."
  exit 1
fi

# Check for handler failures in logs
echo "==> Checking agent logs for handler failures"
sleep 2  # Allow async handlers to complete

MAIN_LOGS="$(kubectl --context="${KUBE_CONTEXT}" -n "${NAMESPACE}" logs "${POD_NAME}" \
  -c "${MAIN_CONTAINER}" --since-time="${START_TIME}" 2>/dev/null || true)"

if grep -q "Sandboxed handler failed" <<<"${MAIN_LOGS}"; then
  echo "ERROR: Detected 'Sandboxed handler failed' in agent logs."
  echo "--- Relevant logs ---"
  grep -A5 "Sandboxed handler failed" <<<"${MAIN_LOGS}" || true
  exit 1
fi

echo "==> ACP smoke test passed"
echo "    Task ID: ${TASK_ID}"
echo "    Pod: ${POD_NAME}"
echo "    Namespace: ${NAMESPACE}"
