#!/bin/bash

set -euo pipefail

# CyberStrikeAI 一键部署启动脚本
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$ROOT_DIR"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 打印带颜色的消息
info() { echo -e "${BLUE}ℹ️  $1${NC}"; }
success() { echo -e "${GREEN}✅ $1${NC}"; }
warning() { echo -e "${YELLOW}⚠️  $1${NC}"; }
error() { echo -e "${RED}❌ $1${NC}"; }
note() { echo -e "${CYAN}ℹ️  $1${NC}"; }

# 临时源配置（仅在此脚本中生效）
PIP_INDEX_URL="${PIP_INDEX_URL:-https://pypi.tuna.tsinghua.edu.cn/simple}"
GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"

# 保存原始环境变量（用于恢复）
ORIGINAL_PIP_INDEX_URL="${PIP_INDEX_URL:-}"
ORIGINAL_GOPROXY="${GOPROXY:-}"

# 进度显示函数
show_progress() {
    local pid=$1
    local message=$2
    local i=0
    local dots=""
    
    # 检查进程是否存在
    if ! kill -0 "$pid" 2>/dev/null; then
        # 进程已经结束，立即返回
        return 0
    fi
    
    while kill -0 "$pid" 2>/dev/null; do
        i=$((i + 1))
        case $((i % 4)) in
            0) dots="." ;;
            1) dots=".." ;;
            2) dots="..." ;;
            3) dots="...." ;;
        esac
        printf "\r${BLUE}⏳ %s%s${NC}" "$message" "$dots"
        sleep 0.5
        
        # 再次检查进程是否还存在
        if ! kill -0 "$pid" 2>/dev/null; then
            break
        fi
    done
    printf "\r"
}

echo ""
echo "=========================================="
echo "  CyberStrikeAI 一键部署启动脚本"
echo "  （默认 HTTPS 自签证书；纯 HTTP 请用: $0 --http）"
echo "=========================================="
echo ""

# 显示临时源配置信息
echo ""
warning "⚠️  注意：此脚本将使用临时镜像源加速下载"
echo ""
info "Python pip 临时镜像源:"
echo "  ${PIP_INDEX_URL}"
info "Go Proxy 临时镜像源:"
echo "  ${GOPROXY}"
echo ""
note "这些设置仅在脚本运行期间生效，不会修改系统配置"
echo ""
sleep 1

CONFIG_FILE="$ROOT_DIR/config.yaml"
VENV_DIR="$ROOT_DIR/venv"
REQUIREMENTS_FILE="$ROOT_DIR/requirements.txt"
BINARY_NAME="cyberstrike-ai"

# 检查配置文件
if [ ! -f "$CONFIG_FILE" ]; then
    error "配置文件 config.yaml 不存在"
    info "请确保在项目根目录运行此脚本"
    exit 1
fi

# 检查并安装 Python 环境
check_python() {
    if ! command -v python3 >/dev/null 2>&1; then
        error "未找到 python3"
        echo ""
        info "请先安装 Python 3.10 或更高版本："
        echo "  macOS:   brew install python3"
        echo "  Ubuntu:  sudo apt-get install python3 python3-venv"
        echo "  CentOS:  sudo yum install python3 python3-pip"
        exit 1
    fi
    
    PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
    PYTHON_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1)
    PYTHON_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f2)
    
    if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 10 ]); then
        error "Python 版本过低: $PYTHON_VERSION (需要 3.10+)"
        exit 1
    fi
    
    success "Python 环境检查通过: $PYTHON_VERSION"
}

# 检查并安装 Go 环境
check_go() {
    if ! command -v go >/dev/null 2>&1; then
        error "未找到 Go"
        echo ""
        info "请先安装 Go 1.21 或更高版本："
        echo "  macOS:   brew install go"
        echo "  Ubuntu:  sudo apt-get install golang-go"
        echo "  CentOS:  sudo yum install golang"
        echo "  或访问:  https://go.dev/dl/"
        exit 1
    fi
    
    GO_VERSION=$(go version | awk '{print $3}' | sed 's/go//')
    GO_MAJOR=$(echo "$GO_VERSION" | cut -d. -f1)
    GO_MINOR=$(echo "$GO_VERSION" | cut -d. -f2)
    
    if [ "$GO_MAJOR" -lt 1 ] || ([ "$GO_MAJOR" -eq 1 ] && [ "$GO_MINOR" -lt 21 ]); then
        error "Go 版本过低: $GO_VERSION (需要 1.21+)"
        exit 1
    fi
    
    success "Go 环境检查通过: $(go version)"
}

# 设置 Python 虚拟环境
setup_python_env() {
    if [ ! -d "$VENV_DIR" ]; then
        info "创建 Python 虚拟环境..."
        python3 -m venv "$VENV_DIR"
        success "虚拟环境创建完成"
    else
        info "Python 虚拟环境已存在"
    fi
    
    info "激活虚拟环境..."
    # shellcheck disable=SC1091
    source "$VENV_DIR/bin/activate"
    
    if [ -f "$REQUIREMENTS_FILE" ]; then
        echo ""
        note "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        note "⚠️  使用临时 pip 镜像源（仅本次脚本运行有效）"
        note "   镜像地址: ${PIP_INDEX_URL}"
        note "   如需永久配置，请设置环境变量 PIP_INDEX_URL"
        note "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        echo ""
        
        info "升级 pip..."
        pip install --index-url "$PIP_INDEX_URL" --upgrade pip >/dev/null 2>&1 || true
        
        info "安装 Python 依赖包..."
        echo ""
        
        # 尝试安装依赖，捕获错误输出并显示进度
        PIP_LOG=$(mktemp)
        (
            set +e  # 在子shell中禁用错误退出
            pip install --index-url "$PIP_INDEX_URL" -r "$REQUIREMENTS_FILE" >"$PIP_LOG" 2>&1
            echo $? > "${PIP_LOG}.exit"
        ) &
        PIP_PID=$!
        
        # 等待一小段时间，确保进程启动
        sleep 0.1
        
        # 显示进度（如果进程还在运行）
        if kill -0 "$PIP_PID" 2>/dev/null; then
            show_progress "$PIP_PID" "正在安装依赖包"
        else
            # 进程已经结束，等待一下确保退出码文件已写入
            sleep 0.2
        fi
        
        # 等待进程完成，忽略 wait 的退出码
        wait "$PIP_PID" 2>/dev/null || true
        
        PIP_EXIT_CODE=0
        if [ -f "${PIP_LOG}.exit" ]; then
            PIP_EXIT_CODE=$(cat "${PIP_LOG}.exit" 2>/dev/null || echo "1")
            rm -f "${PIP_LOG}.exit" 2>/dev/null || true
        else
            # 如果没有退出码文件，检查日志中是否有错误
            if [ -f "$PIP_LOG" ] && grep -q -i "error\|failed\|exception" "$PIP_LOG" 2>/dev/null; then
                PIP_EXIT_CODE=1
            fi
        fi
        
        if [ $PIP_EXIT_CODE -eq 0 ]; then
            success "Python 依赖安装完成"
        else
            # 检查是否是 angr 安装失败（需要 Rust）
            if grep -q "angr" "$PIP_LOG" && grep -q "Rust compiler\|can't find Rust" "$PIP_LOG"; then
                warning "angr 安装失败（需要 Rust 编译器）"
                echo ""
                info "angr 是可选依赖，主要用于二进制分析工具"
                info "如果需要使用 angr，请先安装 Rust："
                echo "  macOS:   curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
                echo "  Ubuntu:  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
                echo "  或访问:  https://rustup.rs/"
                echo ""
                info "其他依赖已安装，可以继续使用（部分工具可能不可用）"
            else
                warning "部分 Python 依赖安装失败，但可以继续尝试运行"
                warning "如果遇到问题，请检查错误信息并手动安装缺失的依赖"
                # 显示最后几行错误信息
                echo ""
                info "错误详情（最后 10 行）："
                tail -n 10 "$PIP_LOG" | sed 's/^/  /'
                echo ""
            fi
        fi
        rm -f "$PIP_LOG"
    else
        warning "未找到 requirements.txt，跳过 Python 依赖安装"
    fi
}

# 构建 Go 项目
build_go_project() {
    echo ""
    note "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    note "⚠️  使用临时 Go Proxy（仅本次脚本运行有效）"
    note "   Proxy 地址: ${GOPROXY}"
    note "   如需永久配置，请设置环境变量 GOPROXY"
    note "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    
    info "下载 Go 依赖..."
    GO_DOWNLOAD_LOG=$(mktemp)
    (
        set +e  # 在子shell中禁用错误退出
        export GOPROXY="$GOPROXY"
        go mod download >"$GO_DOWNLOAD_LOG" 2>&1
        echo $? > "${GO_DOWNLOAD_LOG}.exit"
    ) &
    GO_DOWNLOAD_PID=$!
    
    # 等待一小段时间，确保进程启动
    sleep 0.1
    
    # 显示进度（如果进程还在运行）
    if kill -0 "$GO_DOWNLOAD_PID" 2>/dev/null; then
        show_progress "$GO_DOWNLOAD_PID" "正在下载 Go 依赖"
    else
        # 进程已经结束，等待一下确保退出码文件已写入
        sleep 0.2
    fi
    
    # 等待进程完成，忽略 wait 的退出码
    wait "$GO_DOWNLOAD_PID" 2>/dev/null || true
    
    GO_DOWNLOAD_EXIT_CODE=0
    if [ -f "${GO_DOWNLOAD_LOG}.exit" ]; then
        GO_DOWNLOAD_EXIT_CODE=$(cat "${GO_DOWNLOAD_LOG}.exit" 2>/dev/null || echo "1")
        rm -f "${GO_DOWNLOAD_LOG}.exit" 2>/dev/null || true
    else
        # 如果没有退出码文件，检查日志中是否有错误
        if [ -f "$GO_DOWNLOAD_LOG" ] && grep -q -i "error\|failed" "$GO_DOWNLOAD_LOG" 2>/dev/null; then
            GO_DOWNLOAD_EXIT_CODE=1
        fi
    fi
    rm -f "$GO_DOWNLOAD_LOG" 2>/dev/null || true
    
    if [ $GO_DOWNLOAD_EXIT_CODE -ne 0 ]; then
        error "Go 依赖下载失败"
        exit 1
    fi
    success "Go 依赖下载完成"
    
    info "构建项目..."
    GO_BUILD_LOG=$(mktemp)
    (
        set +e  # 在子shell中禁用错误退出
        export GOPROXY="$GOPROXY"
        go build -o "$BINARY_NAME" cmd/server/main.go >"$GO_BUILD_LOG" 2>&1
        echo $? > "${GO_BUILD_LOG}.exit"
    ) &
    GO_BUILD_PID=$!
    
    # 等待一小段时间，确保进程启动
    sleep 0.1
    
    # 显示进度（如果进程还在运行）
    if kill -0 "$GO_BUILD_PID" 2>/dev/null; then
        show_progress "$GO_BUILD_PID" "正在构建项目"
    else
        # 进程已经结束，等待一下确保退出码文件已写入
        sleep 0.2
    fi
    
    # 等待进程完成，忽略 wait 的退出码
    wait "$GO_BUILD_PID" 2>/dev/null || true
    
    GO_BUILD_EXIT_CODE=0
    if [ -f "${GO_BUILD_LOG}.exit" ]; then
        GO_BUILD_EXIT_CODE=$(cat "${GO_BUILD_LOG}.exit" 2>/dev/null || echo "1")
        rm -f "${GO_BUILD_LOG}.exit" 2>/dev/null || true
    else
        # 如果没有退出码文件，检查日志中是否有错误
        if [ -f "$GO_BUILD_LOG" ] && grep -q -i "error\|failed" "$GO_BUILD_LOG" 2>/dev/null; then
            GO_BUILD_EXIT_CODE=1
        fi
    fi
    
    if [ $GO_BUILD_EXIT_CODE -eq 0 ]; then
        success "项目构建完成: $BINARY_NAME"
        rm -f "$GO_BUILD_LOG"
    else
        error "项目构建失败"
        # 显示构建错误
        echo ""
        info "构建错误详情："
        cat "$GO_BUILD_LOG" | sed 's/^/  /'
        echo ""
        rm -f "$GO_BUILD_LOG"
        exit 1
    fi
}

# 检查是否需要重新构建
need_rebuild() {
    if [ ! -f "$BINARY_NAME" ]; then
        return 0  # 需要构建
    fi
    
    # 检查源代码是否有更新
    if [ "$BINARY_NAME" -ot cmd/server/main.go ] || \
       [ "$BINARY_NAME" -ot go.mod ] || \
       find internal cmd -name "*.go" -newer "$BINARY_NAME" 2>/dev/null | grep -q .; then
        return 0  # 需要重新构建
    fi
    
    return 1  # 不需要构建
}

# 主流程
# 默认启动主站 HTTPS（--https 传给二进制）；传 --http 则走明文 HTTP。
main() {
    USE_HTTPS=1
    FORWARD_ARGS=()
    for arg in "$@"; do
        if [ "$arg" = "--http" ]; then
            USE_HTTPS=0
            continue
        fi
        FORWARD_ARGS+=("$arg")
    done

    # 环境检查
    info "检查运行环境..."
    check_python
    check_go
    echo ""
    
    # 设置 Python 环境
    info "设置 Python 环境..."
    setup_python_env
    echo ""
    
    # 构建 Go 项目
    if need_rebuild; then
        info "准备构建项目..."
        build_go_project
    else
        success "可执行文件已是最新，跳过构建"
    fi
    echo ""
    
    # 启动服务器
    success "所有准备工作完成！"
    echo ""
    if [ "$USE_HTTPS" -eq 1 ]; then
        info "启动 CyberStrikeAI 服务器（HTTPS + HTTP/2，自签证书）..."
        note "纯 HTTP 启动请使用: $0 --http"
    else
        info "启动 CyberStrikeAI 服务器（HTTP）..."
    fi
    echo "=========================================="
    echo ""

    # 始终传入项目根目录下的 config.yaml，避免 cwd 不在项目根时找不到配置；额外参数仍可追加（如再次 -config 覆盖，以 Go flag 后写为准）。
    if [ "$USE_HTTPS" -eq 1 ]; then
        if [ "${#FORWARD_ARGS[@]}" -gt 0 ]; then
            exec "./$BINARY_NAME" -config "$CONFIG_FILE" --https "${FORWARD_ARGS[@]}"
        else
            exec "./$BINARY_NAME" -config "$CONFIG_FILE" --https
        fi
    else
        if [ "${#FORWARD_ARGS[@]}" -gt 0 ]; then
            exec "./$BINARY_NAME" -config "$CONFIG_FILE" "${FORWARD_ARGS[@]}"
        else
            exec "./$BINARY_NAME" -config "$CONFIG_FILE"
        fi
    fi
}

# 执行主流程（支持参数，如: ./run.sh --http）
main "$@"
