#!/usr/bin/env bash
# ============================================================
# LambdAgent PaaS 一键安装启动脚本
# 用法:
#   chmod +x setup.sh
#   ./setup.sh              # 安装并启动（自动识别 发行包/源码 两种模式）
#   ./setup.sh --build      # 构建普通 wheel 包到 dist/（含 .py 源码）
#   ./setup.sh --build-secure  # 用 Nuitka 编译成 .so wheel 到 dist-secure/（防逆向，仍需 Python）
#   ./setup.sh --build-binary  # 用 Nuitka 打成单文件二进制 dist-binary/（防逆向 + 免装 Python）
#   ./setup.sh --package    # 打出「不含源码」的发行包 release/（优先用编译版）
#   ./setup.sh --docker     # 使用 Docker 启动
#   ./setup.sh --help       # 查看帮助
#
# 安装模式（install_deps 自动判定）:
#   发行模式  dist/*.whl 存在 → 从预编译 wheel 安装（终端用户拿到的包用这种）
#   开发模式  无 wheel 但有源码目录 → editable 安装（开发者本机）
# ============================================================

set -e

# ── 颜色输出 ──────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

info()  { echo -e "${BLUE}[INFO]${NC}  $1"; }
ok()    { echo -e "${GREEN}[OK]${NC}    $1"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $1"; }
fail()  { echo -e "${RED}[FAIL]${NC}  $1"; exit 1; }

# ── 项目根目录 ────────────────────────────────────────────
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$PROJECT_DIR"

# ── 帮助信息 ──────────────────────────────────────────────
show_help() {
    echo ""
    echo "LambdAgent PaaS 一键安装启动脚本"
    echo ""
    echo "用法:"
    echo "  ./setup.sh              安装依赖并启动服务（自动识别发行/源码模式）"
    echo "  ./setup.sh --build         构建普通 wheel 包 → dist/*.whl（仍含 .py 源码）"
    echo "  ./setup.sh --build-secure  Nuitka 编译成 .so wheel → dist-secure/（防逆向，仍需 Python）"
    echo "  ./setup.sh --build-binary  Nuitka 打成单文件二进制 → dist-binary/（防逆向 + 免装 Python）"
    echo "  ./setup.sh --package    打出不含源码的发行包 → release/（有编译版则优先用）"
    echo "  ./setup.sh --docker     使用 Docker Compose 启动"
    echo "  ./setup.sh --install    仅安装依赖，不启动服务"
    echo "  ./setup.sh --launch     安装并一键启动 Agent 对话"
    echo "  ./setup.sh --help       显示此帮助信息"
    echo ""
    echo "发布给终端用户的流程（开发者执行）:"
    echo "  ./setup.sh --build      # 在源码树里先构建 wheel"
    echo "  ./setup.sh --package    # 组装 release/，里面只有 wheel + 启动脚本，无源码"
    echo "  然后把 release/ 压缩发给用户；用户解压后跑 ./setup.sh 即可"
    echo ""
    echo "环境要求:"
    echo "  Python 方式: Python 3.10+"
    echo "  Docker 方式: Docker + Docker Compose"
    echo ""
}

# ── 检查 Python ───────────────────────────────────────────
check_python() {
    if command -v python3 &>/dev/null; then
        PYTHON=python3
    elif command -v python &>/dev/null; then
        PYTHON=python
    else
        fail "未找到 Python。请安装 Python 3.10+\n  macOS:   brew install python@3.12\n  Ubuntu:  sudo apt install python3 python3-venv python3-pip"
    fi

    # 检查版本
    PY_VERSION=$($PYTHON -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
    PY_MAJOR=$($PYTHON -c 'import sys; print(sys.version_info.major)')
    PY_MINOR=$($PYTHON -c 'import sys; print(sys.version_info.minor)')

    if [ "$PY_MAJOR" -lt 3 ] || { [ "$PY_MAJOR" -eq 3 ] && [ "$PY_MINOR" -lt 10 ]; }; then
        fail "Python 版本过低: $PY_VERSION（需要 3.10+）"
    fi

    ok "Python $PY_VERSION"
}

# ── 检查 Docker ───────────────────────────────────────────
check_docker() {
    if ! command -v docker &>/dev/null; then
        fail "未找到 Docker。请先安装 Docker Desktop\n  https://www.docker.com/products/docker-desktop/"
    fi

    if ! docker info &>/dev/null 2>&1; then
        fail "Docker 未运行。请启动 Docker Desktop"
    fi

    if ! command -v docker-compose &>/dev/null && ! docker compose version &>/dev/null 2>&1; then
        fail "未找到 Docker Compose"
    fi

    ok "Docker $(docker --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
}

# ── 配置 .env 文件 ────────────────────────────────────────
setup_env() {
    if [ ! -f .env ]; then
        if [ -f .env.example ]; then
            cp .env.example .env
            warn ".env 文件已从 .env.example 创建"
            echo ""
            echo "  ┌─────────────────────────────────────────────┐"
            echo "  │  请编辑 .env 文件，填入你的 LLM API Key：   │"
            echo "  │                                             │"
            echo "  │  至少填写以下其中一个:                       │"
            echo "  │    DASHSCOPE_API_KEY=sk-xxx                 │"
            echo "  │    OPENAI_API_KEY=sk-xxx                    │"
            echo "  │    ANTHROPIC_API_KEY=sk-xxx                 │"
            echo "  │    DEEPSEEK_API_KEY=sk-xxx                  │"
            echo "  │                                             │"
            echo "  │  编辑命令: nano .env 或 vim .env             │"
            echo "  └─────────────────────────────────────────────┘"
            echo ""

            read -p "是否现在编辑 .env 文件？(y/N) " -r
            if [[ $REPLY =~ ^[Yy]$ ]]; then
                if command -v nano &>/dev/null; then
                    nano .env
                elif command -v vim &>/dev/null; then
                    vim .env
                else
                    info "请手动编辑 .env 文件后重新运行此脚本"
                    exit 0
                fi
            fi
        fi
    else
        ok ".env 文件已存在"
    fi
}

# ── 构建发行 wheel 包 ─────────────────────────────────────
# 把 lambdagent / agentpaas 两个子包构建成 .whl 放进 dist/。
# wheel 是「打包后的安装件」——发给用户的不再是整个源码树（含 .git、
# 测试、商业计划书等），而是这两个 whl。注意：普通 wheel 内部仍是 .py
# 源文件，它解决的是「别再把整个仓库 editable 送人」，不是代码混淆；
# 真要防逆向需要 Nuitka 编译，见 docs/DESKTOP_MANUAL_zh.md「源码保护」一节。
build_wheels() {
    check_python

    if [ ! -d lambdagent ] || [ ! -d agentpaas ]; then
        fail "未找到源码目录（lambdagent/ agentpaas/）。--build 只能在源码树里执行。"
    fi

    # 构建 wheel 走 PEP 517 构建隔离，不依赖 .venv —— 直接用 $PYTHON 即可。
    info "构建 wheel 包 → dist/ ..."
    mkdir -p dist
    rm -f dist/lambdagent-*.whl dist/agentpaas-*.whl

    $PYTHON -m pip wheel --no-deps ./lambdagent -w dist/ --quiet
    $PYTHON -m pip wheel --no-deps ./agentpaas  -w dist/ --quiet

    echo ""
    ok "wheel 构建完成:"
    ls -1 dist/lambdagent-*.whl dist/agentpaas-*.whl 2>/dev/null | sed 's/^/    /'
    echo ""
    echo "  下一步: ./setup.sh --package  组装不含源码的发行包"
    echo ""
}

# ── 组装「不含源码」的发行包 ──────────────────────────────
# 产出 release/：只含 wheel + 启动脚本 + 前端静态产物 + 配置样例 + 文档，
# 不含 lambdagent/src、agentpaas/src、tests、.git、商业计划书等。
# 把 release/ 压缩后发给终端用户即可。
package_release() {
    # 优先用编译版（dist-secure/，.so wheel，防逆向）；没有则退回普通 dist/
    local WHEEL_SRC=dist
    if ls dist-secure/lambdagent-*.whl >/dev/null 2>&1 && ls dist-secure/agentpaas-*.whl >/dev/null 2>&1; then
        WHEEL_SRC=dist-secure
        info "检测到编译版 wheel，发行包将使用 dist-secure/（.so，防逆向）。"
    elif ! ls dist/lambdagent-*.whl >/dev/null 2>&1 || ! ls dist/agentpaas-*.whl >/dev/null 2>&1; then
        warn "未找到 wheel，先执行普通构建（如需防逆向请改用 ./setup.sh --build-secure）..."
        build_wheels
    fi

    # 从 agentpaas/pyproject.toml 取版本号（兼容无源码时回退到 wheel 文件名）
    local VER
    if [ -f agentpaas/pyproject.toml ]; then
        VER=$(grep -m1 '^version' agentpaas/pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')
    else
        VER=$(ls dist/agentpaas-*.whl 2>/dev/null | sed -E 's/.*agentpaas-([0-9][^-]*)-.*/\1/' | head -1)
    fi
    [ -z "$VER" ] && VER="dev"

    info "组装发行包 → release/ ..."
    rm -rf release
    mkdir -p release/dist

    cp "$WHEEL_SRC"/lambdagent-*.whl "$WHEEL_SRC"/agentpaas-*.whl release/dist/
    cp setup.sh release/
    chmod +x release/setup.sh

    # 前端静态产物（已编译，无源码）
    [ -d webui-dist ] && cp -R webui-dist release/

    # 用户需要的配置样例 / 编排文件 / 文档（均非核心源码）
    [ -f .env.example ]        && cp .env.example release/
    [ -f docker-compose.yml ]  && cp docker-compose.yml release/
    [ -f Dockerfile ]          && cp Dockerfile release/ 2>/dev/null || true
    [ -d agentexample ]        && cp -R agentexample release/
    mkdir -p release/docs
    [ -f docs/DESKTOP_MANUAL_zh.md ] && cp docs/DESKTOP_MANUAL_zh.md release/docs/
    [ -f QUICK_START.md ]      && cp QUICK_START.md release/
    [ -f README.md ]           && cp README.md release/
    [ -f LICENSE ]             && cp LICENSE release/

    # 清掉 macOS 垃圾文件
    find release -name '.DS_Store' -delete 2>/dev/null || true

    echo ""
    ok "发行包已生成: release/"
    echo "  内容（不含任何 src 源码 / .git / 内部文档）:"
    (cd release && find . -maxdepth 2 -type f | sed 's/^/    /' | head -30)
    echo ""
    echo "  压缩发布:  zip -r lambdagent-paas-${VER}.zip release/"
    echo "  用户使用:  解压 → cd release → ./setup.sh"
    echo ""
}

# ── 创建虚拟环境并安装依赖 ────────────────────────────────
# 自动判定两种模式:
#   发行模式: 同目录 dist/*.whl 存在 → 从预编译 wheel 安装（终端用户）
#   开发模式: 无 wheel 但有源码目录 → editable 安装（开发者本机）
install_deps() {
    info "创建 Python 虚拟环境..."

    if [ ! -d .venv ]; then
        $PYTHON -m venv .venv
        ok "虚拟环境已创建: .venv/"
    else
        ok "虚拟环境已存在: .venv/"
    fi

    # 激活虚拟环境
    source .venv/bin/activate
    pip install --quiet --upgrade pip >/dev/null 2>&1

    if ls dist/lambdagent-*.whl >/dev/null 2>&1 && ls dist/agentpaas-*.whl >/dev/null 2>&1; then
        # ── 发行模式: 从 wheel 安装 ──
        info "检测到预编译 wheel，按【发行模式】安装..."
        # 先装 lambdagent（agentpaas 依赖它），再装 agentpaas；
        # 第三方依赖（fastapi 等）由 pip 从 PyPI 拉取。
        pip install --quiet --upgrade dist/lambdagent-*.whl
        ok "lambdagent 已从 wheel 安装"
        pip install --quiet --upgrade dist/agentpaas-*.whl
        ok "agentpaas 已从 wheel 安装"
    elif [ -d lambdagent ] && [ -d agentpaas ]; then
        # ── 开发模式: editable 源码安装 ──
        info "未检测到 wheel，按【开发模式】editable 安装源码..."
        # 修复历史 bug: 原为 `pip install -e ".[all]"`（root 无 pyproject，
        # 实际安装失败），lambdagent 真实路径是 ./lambdagent。
        pip install -e "./lambdagent[all]" --quiet 2>&1 | tail -1
        ok "lambdagent 已安装（editable）"
        pip install -e "./agentpaas[dev]" --quiet 2>&1 | tail -1
        ok "agentpaas 已安装（editable）"
    else
        fail "既无 dist/*.whl 也无源码目录（lambdagent/ agentpaas/），无法安装。"
    fi

    echo ""
    ok "所有依赖安装完成!"
    echo ""
    echo "  激活虚拟环境: source .venv/bin/activate"
    echo ""
}

# ── Python 方式启动 ───────────────────────────────────────
start_python() {
    source .venv/bin/activate

    # 加载 .env
    if [ -f .env ]; then
        set -a
        source .env
        set +a
    fi

    info "启动 AgentPaaS 服务（开发模式）..."
    echo ""
    echo "  ┌─────────────────────────────────────────────┐"
    echo "  │  服务地址: http://localhost:${AGENTPAAS_PORT:-8000}            │"
    echo "  │  API 文档: http://localhost:${AGENTPAAS_PORT:-8000}/docs       │"
    echo "  │  按 Ctrl+C 停止服务                          │"
    echo "  └─────────────────────────────────────────────┘"
    echo ""

    python -m agentpaas serve --dev
}

# ── Docker 方式启动 ───────────────────────────────────────
start_docker() {
    check_docker
    setup_env

    info "使用 Docker Compose 启动..."

    # 使用根目录的 docker-compose
    if docker compose version &>/dev/null 2>&1; then
        COMPOSE_CMD="docker compose"
    else
        COMPOSE_CMD="docker-compose"
    fi

    $COMPOSE_CMD -f docker-compose.yml up --build

}

# ── 一键启动 Agent 对话 ───────────────────────────────────
launch_agent() {
    source .venv/bin/activate

    # 加载 .env
    if [ -f .env ]; then
        set -a
        source .env
        set +a
    fi

    CONFIG_FILE="${1:-agent-config.yml}"

    if [ ! -f "$CONFIG_FILE" ]; then
        fail "Agent 配置文件不存在: $CONFIG_FILE\n  请创建配置文件或指定路径: ./setup.sh --launch your-config.yml"
    fi

    info "一键启动 Agent: $CONFIG_FILE"
    python -m agentpaas launch "$CONFIG_FILE"
}

# ── 主流程 ────────────────────────────────────────────────
main() {
    echo ""
    echo "================================================"
    echo "  LambdAgent PaaS 一键安装启动"
    echo "================================================"
    echo ""

    case "${1:-}" in
        --help|-h)
            show_help
            exit 0
            ;;
        --build)
            build_wheels
            ;;
        --build-secure)
            check_python
            bash scripts/build_secure.sh "$PYTHON"
            ;;
        --build-binary)
            check_python
            bash scripts/build_binary.sh "$PYTHON"
            ;;
        --package)
            package_release
            ;;
        --docker)
            start_docker
            ;;
        --install)
            check_python
            setup_env
            install_deps
            echo "安装完成! 启动服务请运行:"
            echo "  source .venv/bin/activate"
            echo "  python -m agentpaas serve --dev"
            ;;
        --launch)
            check_python
            setup_env
            install_deps
            launch_agent "${2:-}"
            ;;
        *)
            check_python
            setup_env
            install_deps
            start_python
            ;;
    esac
}

main "$@"
