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

# Direct SuperAgent Open API stream test.
# Purpose: bypass TH Hotel backend Debug EML / OSS / SourceMessage and test
# whether SuperAgent Open API itself times out or returns usable SSE events.
#
# Usage on test server:
#   cd /home/th-hotel-simple
#   bash ./superagent-direct-stream-test.sh
#
# You can either edit the variables below, or override them before running:
#   ENV_FILE=/home/th-hotel-simple/th-hotel-server.env bash ./superagent-direct-stream-test.sh

#######################################
# Editable parameters
#######################################

# Your test server env file. It can be plain key=value format.
ENV_FILE="${ENV_FILE:-/home/th-hotel-simple/th-hotel-server.env}"

# Output directory for generated request bodies, response headers, and SSE body.
OUTPUT_DIR="${OUTPUT_DIR:-/tmp/th-hotel-superagent-direct}"

# Curl timeout. This is total curl max time, not SuperAgent's own timeout.
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-1900}"
CONNECT_TIMEOUT_SECONDS="${CONNECT_TIMEOUT_SECONDS:-30}"

# Optional hard overrides. Leave empty to read from ENV_FILE variables.
BASE_URL="${BASE_URL:-}"
API_KEY="${API_KEY:-}"
EXTERNAL_SUBJECT_ID="${EXTERNAL_SUBJECT_ID:-}"

# The direct test message. Keep it simple first; switch MESSAGE_PAYLOAD_FILE to
# a larger JSON later if you want to mimic Debug EML more closely. If you only
# have an .eml file, set EML_FILE and the script will embed the raw EML text in
# the message payload JSON.
MESSAGE_SUBJECT="${MESSAGE_SUBJECT:-timeout test}"
MESSAGE_TEXT="${MESSAGE_TEXT:-This is a direct curl timeout test. Please return a JSON result.}"
MESSAGE_PAYLOAD_FILE="${MESSAGE_PAYLOAD_FILE:-}"
EML_FILE="${EML_FILE:-}"
MESSAGE_PREFIX="${MESSAGE_PREFIX:-请基于以下 Debug 邮件 JSON 输出结构化任务抽取结果，只返回 JSON，不要创建订单或任务：}"

#######################################
# Helpers
#######################################

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "Missing required command: $1" >&2
    exit 1
  fi
}

mask_secret() {
  local value="${1:-}"
  if [ -z "$value" ]; then
    echo ""
    return
  fi
  if [ "${#value}" -le 8 ]; then
    echo "****"
    return
  fi
  echo "${value:0:4}****${value: -4}"
}

load_env_file() {
  if [ ! -f "$ENV_FILE" ]; then
    echo "ENV_FILE not found: $ENV_FILE" >&2
    echo "Edit ENV_FILE at the top of this script, or pass ENV_FILE=/path/to/file." >&2
    exit 1
  fi

  # shellcheck disable=SC1090
  set -a
  source "$ENV_FILE"
  set +a
}

normalize_config() {
  BASE_URL="${BASE_URL:-${DEERFLOW_TEST_BASE_URL:-${DEERFLOW_BASE_URL:-}}}"
  API_KEY="${API_KEY:-${DEERFLOW_TEST_OPEN_API_KEY:-${DEERFLOW_OPEN_API_KEY:-}}}"
  if [ -z "$EXTERNAL_SUBJECT_ID" ]; then
    EXTERNAL_SUBJECT_ID="${SUPERAGENT_TEST_DEBUG_EML_EXTERNAL_SUBJECT_ID:-${SUPERAGENT_DEBUG_EML_EXTERNAL_SUBJECT_ID:-th-hotel-debug-eml-upload}}"
  fi

  if [ -z "$BASE_URL" ]; then
    echo "BASE_URL is empty. Set DEERFLOW_TEST_BASE_URL / DEERFLOW_BASE_URL or edit BASE_URL." >&2
    exit 1
  fi
  if [ -z "$API_KEY" ]; then
    echo "API_KEY is empty. Set DEERFLOW_TEST_OPEN_API_KEY / DEERFLOW_OPEN_API_KEY or edit API_KEY." >&2
    exit 1
  fi
  if [ -z "$EXTERNAL_SUBJECT_ID" ]; then
    echo "EXTERNAL_SUBJECT_ID is empty. Set SUPERAGENT_TEST_DEBUG_EML_EXTERNAL_SUBJECT_ID or edit it." >&2
    exit 1
  fi
  if [ -n "$MESSAGE_PAYLOAD_FILE" ] && [ ! -f "$MESSAGE_PAYLOAD_FILE" ]; then
    echo "MESSAGE_PAYLOAD_FILE not found: $MESSAGE_PAYLOAD_FILE" >&2
    exit 1
  fi
  if [ -n "$EML_FILE" ] && [ ! -f "$EML_FILE" ]; then
    echo "EML_FILE not found: $EML_FILE" >&2
    exit 1
  fi

  BASE_URL="${BASE_URL%/}"
}

print_config() {
  echo "=== Direct SuperAgent stream test ==="
  echo "ENV_FILE=$ENV_FILE"
  echo "OUTPUT_DIR=$OUTPUT_DIR"
  echo "BASE_URL=$BASE_URL"
  echo "EXTERNAL_SUBJECT_ID=$EXTERNAL_SUBJECT_ID"
  echo "API_KEY=$(mask_secret "$API_KEY")"
  echo "TIMEOUT_SECONDS=$TIMEOUT_SECONDS"
  echo "CONNECT_TIMEOUT_SECONDS=$CONNECT_TIMEOUT_SECONDS"
  echo "MESSAGE_SUBJECT=$MESSAGE_SUBJECT"
  if [ -n "$MESSAGE_PAYLOAD_FILE" ]; then
    echo "MESSAGE_PAYLOAD_FILE=$MESSAGE_PAYLOAD_FILE"
  fi
  if [ -n "$EML_FILE" ]; then
    echo "EML_FILE=$EML_FILE"
  fi
  echo
}

write_create_body() {
  python3 - <<'PY' > "$CREATE_BODY"
import json
import os

run_id = os.environ["RUN_ID"]
subject = os.environ["EXTERNAL_SUBJECT_ID"]

print(json.dumps({
    "external_subject_id": subject,
    "idempotency_key": f"{run_id}-session",
    "metadata": {
        "source": "direct-curl",
        "debug_run_id": run_id
    }
}, ensure_ascii=False))
PY
}

write_stream_body() {
  python3 - <<'PY' > "$STREAM_BODY"
import json
import os
from pathlib import Path

run_id = os.environ["RUN_ID"]
payload_file = os.environ.get("MESSAGE_PAYLOAD_FILE", "").strip()
eml_file = os.environ.get("EML_FILE", "").strip()
prefix = os.environ["MESSAGE_PREFIX"]

if payload_file:
    payload_text = Path(payload_file).read_text(encoding="utf-8")
elif eml_file:
    eml_path = Path(eml_file)
    raw_eml = eml_path.read_text(encoding="utf-8", errors="replace")
    payload_text = json.dumps({
        "source": "direct-curl",
        "schema_version": "direct-raw-eml-v1",
        "raw_eml_file_name": eml_path.name,
        "raw_eml_size_bytes": eml_path.stat().st_size,
        "raw_eml": raw_eml,
    }, ensure_ascii=False)
else:
    payload_text = json.dumps({
        "source": "direct-curl",
        "subject": os.environ["MESSAGE_SUBJECT"],
        "text": os.environ["MESSAGE_TEXT"],
    }, ensure_ascii=False)

message = prefix + "\n" + payload_text

print(json.dumps({
    "message": message,
    "idempotency_key": f"{run_id}-message",
    "metadata": {
        "source": "direct-curl",
        "debug_run_id": run_id,
        "source_message_id": "direct-curl",
        "hotel_id": "DIRECT"
    }
}, ensure_ascii=False))
PY
}

extract_session_id() {
  python3 - "$CREATE_RESPONSE" <<'PY'
import json
import sys

path = sys.argv[1]
try:
    with open(path, "r", encoding="utf-8") as f:
        data = json.load(f)
except Exception:
    print("")
    raise SystemExit(0)

print(data.get("session_id") or data.get("id") or "")
PY
}

curl_create_session() {
  local csrf="$RUN_ID-create"
  echo "=== Creating SuperAgent session ==="

  set +e
  CREATE_HTTP_CODE="$(
    curl -sS \
      --connect-timeout "$CONNECT_TIMEOUT_SECONDS" \
      --max-time "$TIMEOUT_SECONDS" \
      -w "%{http_code}" \
      -D "$CREATE_HEADERS" \
      -o "$CREATE_RESPONSE" \
      -X POST "$BASE_URL/api/open/agent-sessions" \
      -H "Authorization: Bearer $API_KEY" \
      -H "X-CSRF-Token: $csrf" \
      -H "Cookie: csrf_token=$csrf" \
      -H "Content-Type: application/json" \
      --data-binary @"$CREATE_BODY"
  )"
  CREATE_CURL_EXIT=$?
  set -e

  echo "create curl exit=$CREATE_CURL_EXIT http=$CREATE_HTTP_CODE"
  echo "create headers: $CREATE_HEADERS"
  echo "create response: $CREATE_RESPONSE"

  if [ "$CREATE_CURL_EXIT" -ne 0 ] || [ "$CREATE_HTTP_CODE" -lt 200 ] || [ "$CREATE_HTTP_CODE" -ge 300 ]; then
    echo "Create session failed. Response body:" >&2
    cat "$CREATE_RESPONSE" >&2 || true
    exit 1
  fi

  SESSION_ID="$(extract_session_id)"
  if [ -z "$SESSION_ID" ]; then
    echo "Create session response does not contain session_id or id. Body:" >&2
    cat "$CREATE_RESPONSE" >&2 || true
    exit 1
  fi

  echo "SESSION_ID=$SESSION_ID"
  echo
}

curl_stream_message() {
  local csrf="$RUN_ID-message"
  echo "=== Calling SuperAgent message stream ==="
  echo "This may run for a long time. Output is saved to: $STREAM_RESPONSE"

  local started_at ended_at elapsed
  started_at="$(date +%s)"

  set +e
  STREAM_HTTP_CODE="$(
    curl -sS -N --no-buffer \
      --connect-timeout "$CONNECT_TIMEOUT_SECONDS" \
      --max-time "$TIMEOUT_SECONDS" \
      -w "%{http_code}" \
      -D "$STREAM_HEADERS" \
      -o "$STREAM_RESPONSE" \
      -X POST "$BASE_URL/api/open/agent-sessions/$SESSION_ID/messages/stream" \
      -H "Authorization: Bearer $API_KEY" \
      -H "X-CSRF-Token: $csrf" \
      -H "Cookie: csrf_token=$csrf" \
      -H "Content-Type: application/json" \
      -H "Accept: text/event-stream" \
      --data-binary @"$STREAM_BODY"
  )"
  STREAM_CURL_EXIT=$?
  set -e

  ended_at="$(date +%s)"
  elapsed="$((ended_at - started_at))"

  echo "stream curl exit=$STREAM_CURL_EXIT http=$STREAM_HTTP_CODE elapsed_seconds=$elapsed"
  echo "stream headers: $STREAM_HEADERS"
  echo "stream response: $STREAM_RESPONSE"
  echo
}

summarize_stream() {
  echo "=== Stream headers ==="
  cat "$STREAM_HEADERS" || true
  echo

  echo "=== Stream event summary ==="
  if [ -s "$STREAM_RESPONSE" ]; then
    grep -E '^event:' "$STREAM_RESPONSE" | sort | uniq -c || true
    echo
    echo "Last 120 lines:"
    tail -n 120 "$STREAM_RESPONSE" || true
  else
    echo "Stream response file is empty."
  fi
  echo
}

#######################################
# Main
#######################################

require_command curl
require_command python3

load_env_file
normalize_config

RUN_ID="${RUN_ID:-direct-curl-$(date +%Y%m%d-%H%M%S)}"
export BASE_URL API_KEY EXTERNAL_SUBJECT_ID RUN_ID
export MESSAGE_SUBJECT MESSAGE_TEXT MESSAGE_PAYLOAD_FILE EML_FILE MESSAGE_PREFIX

mkdir -p "$OUTPUT_DIR"

CREATE_BODY="$OUTPUT_DIR/$RUN_ID-create-body.json"
CREATE_HEADERS="$OUTPUT_DIR/$RUN_ID-create.headers"
CREATE_RESPONSE="$OUTPUT_DIR/$RUN_ID-create.json"
STREAM_BODY="$OUTPUT_DIR/$RUN_ID-stream-body.json"
STREAM_HEADERS="$OUTPUT_DIR/$RUN_ID-stream.headers"
STREAM_RESPONSE="$OUTPUT_DIR/$RUN_ID-stream.sse"

export CREATE_BODY STREAM_BODY CREATE_RESPONSE

print_config
write_create_body
write_stream_body

echo "create request body: $CREATE_BODY"
echo "stream request body: $STREAM_BODY"
echo

curl_create_session
curl_stream_message
summarize_stream

echo "Done."
