#!/usr/bin/env bash
# OPC 永久记忆端到端测试
# 以一个 agent 为对象，验证：写入 → (新会话)读回 → 向量库核查
# 用法: opc-memory-e2e.sh [agent_id]   默认 xiaozhen(小真)
# 退出码: 0=全过, 1=有失败。stdout 末行输出 RESULT=PASS|FAIL 及 JSON 摘要。
set -uo pipefail

AGENT="${1:-xiaozhen}"
TS="$(date +%Y%m%d-%H%M%S)"
TOKEN="E2E校验码-${AGENT}-${TS}-$RANDOM"
QDRANT="http://127.0.0.1:6333"
MEMAPI="http://127.0.0.1:17760"
WRITE_SK="agent:${AGENT}:e2e-w-${TS}"
READ_SK="agent:${AGENT}:e2e-r-${TS}"
LOG="/root/.openclaw/logs/opc-memory-e2e.log"
PATH="/root/.local/share/pnpm:/root/.nvm/versions/node/v22.22.1/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
export PATH

w=FAIL; r=FAIL; d=FAIL   # 三阶段结果
note=""

log(){ echo "[$(date '+%F %T')] $*"; }

# 计数：库里属于本 agent、且含 TOKEN 的记忆条数
count_token(){
  curl -s -m 20 -X POST "$QDRANT/collections/opc_memories/points/scroll" \
    -H 'Content-Type: application/json' \
    -d "{\"limit\":200,\"with_payload\":true,\"filter\":{\"must\":[{\"key\":\"agent_id\",\"match\":{\"value\":\"$AGENT\"}}]}}" 2>/dev/null \
  | python3 -c "import sys,json;
d=json.load(sys.stdin);
pts=d.get('result',{}).get('points',[]);
tok=sys.argv[1];
print(sum(1 for p in pts if tok in json.dumps(p.get('payload',{}),ensure_ascii=False)))" "$TOKEN" 2>/dev/null || echo 0
}

log "===== E2E 开始 agent=$AGENT token=$TOKEN ====="

# ---------- 阶段 A：发指令让其写入记忆 ----------
log "[A] 发送写入指令..."
timeout 200 openclaw agent --agent "$AGENT" --session-key "$WRITE_SK" \
  --message "这是一次记忆系统自检，请严格执行：把下面这句话用 /memory/add 存入你的长期向量记忆，agent_id 用你自己的。要存的内容原文：【今日记忆自检码 ${TOKEN}】。存完后只回复 SAVED。" \
  --json >/tmp/e2e_write_${TS}.json 2>>"$LOG"
log "[A] 写入回合完成"

sleep 3
CNT_AFTER_WRITE=$(count_token)
log "[A] 库内含 token 的本 agent 记忆数 = $CNT_AFTER_WRITE"
[ "${CNT_AFTER_WRITE:-0}" -ge 1 ] && w=PASS

# ---------- 阶段 C(写后核查)：若 agent 没写进去，兜底直接判失败 ----------
[ "$w" = PASS ] && d=PASS

# ---------- 阶段 B：新会话读回，验证持久记忆 ----------
log "[B] 新会话发送读取指令..."
timeout 200 openclaw agent --agent "$AGENT" --session-key "$READ_SK" \
  --message "记忆自检读取：请从你的长期向量记忆里找出今天的『今日记忆自检码』，把完整校验码原样回复给我，只回复那串码。" \
  --json >/tmp/e2e_read_${TS}.json 2>>"$LOG"
REPLY="$(python3 -c "import json,sys;
try:
 d=json.load(open('/tmp/e2e_read_${TS}.json'));
 print(json.dumps(d,ensure_ascii=False))
except Exception as e: print('')" 2>/dev/null)"
if echo "$REPLY" | grep -qF "$TOKEN"; then r=PASS; else r=FAIL; note="读回未命中token"; fi
log "[B] 读回结果: $r"

# ---------- 自清理：删除本次测试码，避免污染真实记忆 ----------
DEL=$(curl -s -m 20 -X POST "$QDRANT/collections/opc_memories/points/scroll" \
  -H 'Content-Type: application/json' \
  -d "{\"limit\":200,\"with_payload\":true,\"filter\":{\"must\":[{\"key\":\"agent_id\",\"match\":{\"value\":\"$AGENT\"}}]}}" 2>/dev/null \
  | python3 -c "import sys,json;
d=json.load(sys.stdin);tok=sys.argv[1];
print(json.dumps([p['id'] for p in d.get('result',{}).get('points',[]) if tok in json.dumps(p.get('payload',{}),ensure_ascii=False)]))" "$TOKEN" 2>/dev/null)
if [ -n "$DEL" ] && [ "$DEL" != "[]" ]; then
  curl -s -m 20 -X POST "$QDRANT/collections/opc_memories/points/delete?wait=true" \
    -H 'Content-Type: application/json' -d "{\"points\":$DEL}" >/dev/null 2>&1
  log "[清理] 已删除本次测试码点: $DEL"
fi

# ---------- 汇总 ----------
[ "$w" = PASS ] && [ "$r" = PASS ] && [ "$d" = PASS ] && RESULT=PASS || RESULT=FAIL
SUMMARY=$(python3 -c "import json;print(json.dumps({'agent':'$AGENT','ts':'$TS','token':'$TOKEN','write':'$w','read':'$r','db':'$d','db_count':$CNT_AFTER_WRITE,'result':'$RESULT','note':'$note'},ensure_ascii=False))")
log "===== E2E 结束 $SUMMARY ====="
echo "RESULT=$RESULT"
echo "SUMMARY=$SUMMARY"
[ "$RESULT" = PASS ] && exit 0 || exit 1
