#!/usr/bin/env bash
set -u
# ============================================================
#  LangGraph 构建 AI Agent 工作流 一键脚本（macOS / Linux / WSL）
#  公开源码，欢迎审查 —— 不放心可先复制给 AI 判断
#  默认配置：云间 API 中转站（https://cloudzone-api.cyou/）
# ============================================================

GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; CYAN='\033[0;36m'; NC='\033[0m'
info()  { echo -e "${GREEN}[INFO]${NC} $1"; }
warn()  { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
step()  { echo -e "${CYAN}[STEP]${NC} $1"; }

CLOUDZONE_URL="https://cloudzone-api.cyou"
CLOUDZONE_API_BASE="https://cloudzone-api.cyou/v1"

detect_network() {
  step "检测网络环境（国内 / 国外）..."
  if curl -fsI --max-time 5 "https://claude.ai" >/dev/null 2>&1; then
    info "可直连 claude.ai，判定为海外网络"
    echo "overseas"
  else
    warn "无法直连 claude.ai，判定为国内网络环境（将自动切换国内镜像）"
    echo "domestic"
  fi
}

check_python() {
  step "检查 Python 3..."
  if command -v python3 >/dev/null 2>&1 && python3 --version >/dev/null 2>&1; then
    PY="python3"
    info "找到 python3：$(python3 --version 2>&1)"
    return 0
  fi
  error "未找到 python3。请先安装：https://www.python.org/downloads/ （Windows 建议使用 WSL）"
  return 1
}

setup_env() {
  local net="$1"
  step "创建虚拟环境并安装 LangGraph 依赖..."
  mkdir -p langgraph-demo && cd langgraph-demo || return 1
  python3 -m venv .venv 2>/dev/null || { error "创建虚拟环境失败，手动执行：python3 -m venv .venv"; return 1; }
  # shellcheck disable=SC1091
  source .venv/bin/activate || { warn "激活虚拟环境失败，继续使用系统环境"; }

  step "安装 langgraph + langchain-openai..."
  local pypi="https://pypi.org/simple"
  if [ "$net" = "domestic" ]; then
    pypi="https://pypi.tuna.tsinghua.edu.cn/simple"
  fi

  if pip install langgraph langchain-openai -i "$pypi" --timeout 90 >/dev/null 2>&1; then
    info "依赖安装成功"
    return 0
  fi
  warn "主源失败，回退备用镜像（阿里云 PyPI）..."
  if pip install langgraph langchain-openai -i "https://mirrors.aliyun.com/pypi/simple" --timeout 90 >/dev/null 2>&1; then
    info "备用镜像安装成功"
    return 0
  fi
  error "依赖安装失败。请手动执行：pip install langgraph langchain-openai -i https://pypi.tuna.tsinghua.edu.cn/simple"
  return 1
}

configure_api() {
  step "配置 API Key..."
  echo ""
  echo "LangGraph 的节点调用大模型需要一把 OpenAI 兼容的 API Key。"
  echo "默认配置云间 API 中转站（OpenAI 兼容格式，一把 Key 调 Claude/GPT/DeepSeek/GLM 等 90+ 模型）："
  echo "  · 国内直连免翻墙，按 token 精确计费，最低官方 0.05 倍起，香港节点延迟低"
  echo ""
  echo "是否现在跳转注册并获取 API Key？"
  echo "  Y - 立即跳转至 ${CLOUDZONE_URL}"
  echo "  N - 我已有 Key（任一 OpenAI 兼容服务），自行输入"
  read -r -p "请选择 [Y/N]: " choice

  local API_KEY=""
  local BASE_URL="$CLOUDZONE_API_BASE"
  if [ "${choice:-N}" = "Y" ] || [ "${choice:-N}" = "y" ]; then
    info "正在打开浏览器..."
    if command -v xdg-open >/dev/null 2>&1; then
      xdg-open "$CLOUDZONE_URL" >/dev/null 2>&1
    elif command -v open >/dev/null 2>&1; then
      open "$CLOUDZONE_URL" >/dev/null 2>&1
    else
      warn "无法自动打开浏览器，请手动访问：$CLOUDZONE_URL"
    fi
    echo "注册后在控制台复制 Key（以 sk- 开头）。"
    read -r -p "粘贴你的 API Key: " API_KEY
    read -r -p "中转地址(直接回车用默认 ${CLOUDZONE_API_BASE}): " input_base
    [ -n "${input_base:-}" ] && BASE_URL="$input_base"
  else
    read -r -s -p "请输入你的 API Key (sk-...): " API_KEY
    echo
    echo "服务地址：OpenAI 官方可不填（默认 api.openai.com）；第三方兼容服务请填写其地址。"
    read -r -p "API 地址(直接回车用默认 ${CLOUDZONE_API_BASE}): " input_base
    [ -n "${input_base:-}" ] && BASE_URL="$input_base"
  fi

  if [ -z "${API_KEY:-}" ]; then
    error "未输入 API Key，跳过配置。可稍后手动设置环境变量后重跑。"
    return 1
  fi

  local SHELL_RC=""
  case "$SHELL" in
    */zsh)  SHELL_RC="$HOME/.zshrc" ;;
    */bash) SHELL_RC="$HOME/.bashrc" ;;
    *)      SHELL_RC="$HOME/.profile" ;;
  esac

  info "写入环境变量到 $SHELL_RC（备份原值到 .bak）"
  if [ -f "$SHELL_RC" ]; then
    sed -i.bak '/OPENAI_API_KEY/d; /OPENAI_BASE_URL/d' "$SHELL_RC"
  fi
  {
    echo ""
    echo "# LangGraph 客服 Demo - 由一键脚本写入"
    echo "export OPENAI_API_KEY=\"$API_KEY\""
    echo "export OPENAI_BASE_URL=\"$BASE_URL\""
  } >> "$SHELL_RC"

  export OPENAI_API_KEY="$API_KEY"
  export OPENAI_BASE_URL="$BASE_URL"

  info "配置完成！"
  echo "  API Key : ${API_KEY:0:10}********"
  echo "  Base URL: $BASE_URL"
  echo ""
  warn "新开终端窗口后永久生效，或立即执行：source $SHELL_RC"
}

write_demo() {
  step "生成客服分流 Demo 代码 ..."
  cat > agent_demo.py <<'PYEOF'
"""
LangGraph 客服分流 Demo
状态机思路：用户消息 → 意图分类(LLM) → 条件路由 → 技术回复 / 日常回复 → 结束
"""
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.checkpoint.memory import MemorySaver
from langchain_openai import ChatOpenAI

def classify_intent(state: MessagesState):
    model = ChatOpenAI(model="gpt-4o-mini")
    messages = state["messages"] + [{
        "role": "system",
        "content": "判断意图。只回复一个词：technical 或 general，不要其他内容。"
    }]
    result = model.invoke(messages)
    return {"intent": result.content.strip().lower()}

def tech_reply(state: MessagesState):
    model = ChatOpenAI(model="gpt-4o-mini")
    messages = state["messages"] + [{
        "role": "system",
        "content": "你是一位资深工程师，用中文帮助排查技术问题，给出具体命令或代码。"
    }]
    return {"messages": [model.invoke(messages)]}

def general_reply(state: MessagesState):
    model = ChatOpenAI(model="gpt-4o-mini")
    messages = state["messages"] + [{
        "role": "system",
        "content": "你是个有趣的聊天伙伴，说话简短友好。"
    }]
    return {"messages": [model.invoke(messages)]}

def route(state: MessagesState):
    intent = state.get("intent", "general")
    return "tech_reply" if "technical" in intent else "general_reply"

workflow = StateGraph(MessagesState)
workflow.add_node("classify", classify_intent)
workflow.add_node("tech_reply", tech_reply)
workflow.add_node("general_reply", general_reply)
workflow.add_edge(START, "classify")
workflow.add_conditional_edges("classify", route, {
    "tech_reply": "tech_reply",
    "general_reply": "general_reply",
})
workflow.add_edge("tech_reply", END)
workflow.add_edge("general_reply", END)

saver = MemorySaver()
app = workflow.compile(checkpointer=saver)

if __name__ == "__main__":
    print("===== LangGraph 客服分流 Demo =====")
    print("(输入 quit 退出)")
    thread_id = "demo_session"
    while True:
        user_input = input("\n你: ").strip()
        if user_input.lower() == "quit":
            print("再见！")
            break
        result = app.invoke(
            {"messages": [{"role": "user", "content": user_input}]},
            config={"configurable": {"thread_id": thread_id}}
        )
        last = result["messages"][-1]
        print(f"{last.role}: {last.content}")
PYEOF
  info "已生成 agent_demo.py — 运行：cd langgraph-demo && source .venv/bin/activate && python agent_demo.py"
}

main() {
  echo "============================================"
  echo "  LangGraph 构建 AI Agent 工作流 一键脚本"
  echo "  适用于 macOS / Linux / WSL"
  echo "  默认接入：云间 API 中转站"
  echo "============================================"
  echo ""

  local NET
  NET=$(detect_network)

  if ! check_python; then
    error "缺少 Python 3，脚本终止。请先安装 Python 后重跑。"
    exit 1
  fi

  if ! setup_env "$NET"; then
    error "环境准备失败，脚本终止。请按上方提示手动处理。"
    exit 1
  fi

  configure_api || warn "Key 未配置，Demo 仍会生成，运行时需要先 export OPENAI_API_KEY 和 OPENAI_BASE_URL"

  write_demo

  echo ""
  echo "============================================"
  info "全部完成！运行你的客服分流 Demo："
  echo "    cd langgraph-demo && source .venv/bin/activate && python agent_demo.py"
  echo "输入文本和多轮对话，Agent 会自动分类意图并路由回复！"
  echo "============================================"
}

main "$@"
