#!/bin/bash

#===============================================================================
# iConsulting 部署管理脚本
#
# 用法: ./deploy.sh <command> [service] [options]
#
# 命令:
#   build     - 编译构建
#   start     - 启动服务
#   stop      - 停止服务
#   restart   - 重启服务
#   status    - 查看状态
#   logs      - 查看日志
#   clean     - 清理构建产物
#   deploy    - 完整部署（构建+启动）
#   db        - 数据库操作
#   help      - 显示帮助
#
# 服务:
#   all                - 所有服务
#   web-client         - 用户前端
#   admin-client       - 管理后台前端
#   conversation       - 对话服务
#   user               - 用户服务
#   payment            - 支付服务
#   knowledge          - 知识库服务
#   evolution          - 进化服务
#   kong               - API网关
#   postgres           - PostgreSQL数据库
#   redis              - Redis缓存
#   neo4j              - Neo4j图数据库
#   nginx              - Nginx静态服务
#
#===============================================================================

set -e

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

# 项目根目录
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$PROJECT_ROOT"

# 配置
COMPOSE_FILE="docker-compose.yml"
ENV_FILE=".env"

# Docker Compose 命令 (默认值，会在 check_environment 中更新)
DOCKER_COMPOSE="docker-compose"

# 域名配置
DOMAIN="${DOMAIN:-iconsulting.szaiai.com}"
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@szaiai.com}"

# 服务端口配置
declare -A SERVICE_PORTS=(
    ["conversation"]=3004
    ["user"]=3001
    ["payment"]=3002
    ["knowledge"]=3003
    ["evolution"]=3005
    ["file"]=3006
    ["kong"]=8000
    ["postgres"]=5432
    ["redis"]=6379
    ["neo4j"]=7474
    ["nginx"]=8080
)

# 服务目录映射
declare -A SERVICE_DIRS=(
    ["conversation"]="packages/services/conversation-service"
    ["user"]="packages/services/user-service"
    ["payment"]="packages/services/payment-service"
    ["knowledge"]="packages/services/knowledge-service"
    ["evolution"]="packages/services/evolution-service"
    ["file"]="packages/services/file-service"
    ["web-client"]="packages/web-client"
    ["admin-client"]="packages/admin-client"
    ["shared"]="packages/shared"
)

# Docker服务名映射
declare -A DOCKER_SERVICES=(
    ["conversation"]="conversation-service"
    ["user"]="user-service"
    ["payment"]="payment-service"
    ["knowledge"]="knowledge-service"
    ["evolution"]="evolution-service"
    ["file"]="file-service"
    ["web-client"]="web-client"
    ["admin-client"]="admin-client"
    ["kong"]="kong"
    ["postgres"]="postgres"
    ["redis"]="redis"
    ["neo4j"]="neo4j"
    ["nginx"]="nginx"
)

#===============================================================================
# 工具函数
#===============================================================================

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_step() {
    echo -e "${PURPLE}[STEP]${NC} $1"
}

# 检查命令是否存在
check_command() {
    if ! command -v "$1" &> /dev/null; then
        log_error "$1 未安装，请先安装"
        exit 1
    fi
}

# 检查环境 (只需要 Docker)
check_environment() {
    log_step "检查运行环境..."

    check_command "docker"

    # 检查 docker-compose 或 docker compose
    if command -v docker-compose &> /dev/null; then
        DOCKER_COMPOSE="docker-compose"
    elif docker compose version &> /dev/null 2>&1; then
        DOCKER_COMPOSE="docker compose"
    else
        log_error "docker-compose 或 docker compose 未安装"
        exit 1
    fi

    log_success "环境检查通过 (使用 $DOCKER_COMPOSE)"
}

# Builder 镜像名称
BUILDER_IMAGE="iconsulting-builder:latest"

# 构建 Builder 镜像
build_builder_image() {
    log_step "检查/构建 Builder 镜像..."

    # 检查镜像是否存在
    if docker images | grep -q "iconsulting-builder"; then
        log_info "Builder 镜像已存在"
        return 0
    fi

    log_info "创建 Builder 镜像..."

    # 创建临时 Dockerfile
    cat > "$PROJECT_ROOT/.builder.Dockerfile" << 'DOCKERFILE'
FROM node:20-alpine

# 安装 pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate

# 设置工作目录
WORKDIR /app

# 设置 pnpm store 目录
ENV PNPM_HOME=/root/.local/share/pnpm
ENV PATH=$PNPM_HOME:$PATH

CMD ["sh"]
DOCKERFILE

    docker build -t "$BUILDER_IMAGE" -f "$PROJECT_ROOT/.builder.Dockerfile" "$PROJECT_ROOT"
    rm -f "$PROJECT_ROOT/.builder.Dockerfile"

    log_success "Builder 镜像创建完成"
}

# 加载环境变量
load_env() {
    if [ -f "$ENV_FILE" ]; then
        export $(grep -v '^#' "$ENV_FILE" | xargs)
    fi
}

# 等待服务就绪
wait_for_service() {
    local host=$1
    local port=$2
    local service=$3
    local max_attempts=${4:-30}
    local attempt=1

    log_info "等待 $service ($host:$port) 就绪..."

    while [ $attempt -le $max_attempts ]; do
        if nc -z "$host" "$port" 2>/dev/null; then
            log_success "$service 已就绪"
            return 0
        fi
        echo -n "."
        sleep 2
        attempt=$((attempt + 1))
    done

    echo ""
    log_error "$service 启动超时"
    return 1
}

#===============================================================================
# 构建函数 (使用 Docker 容器构建，无需在主机安装 Node.js)
#===============================================================================

# 在容器中执行命令
run_in_builder() {
    docker run --rm \
        -v "$PROJECT_ROOT:/app" \
        -v "iconsulting-pnpm-store:/root/.local/share/pnpm/store" \
        -w /app \
        "$BUILDER_IMAGE" \
        sh -c "$1"
}

# 安装依赖 (在容器中)
install_deps() {
    log_step "安装项目依赖 (在 Docker 容器中)..."
    build_builder_image
    run_in_builder "pnpm install --frozen-lockfile || pnpm install"
    log_success "依赖安装完成"
}

# 构建共享包 (在容器中)
build_shared() {
    log_step "构建 shared 包..."
    run_in_builder "cd packages/shared && pnpm run build"
    log_success "shared 构建完成"
}

# 构建单个后端服务 (在容器中)
build_backend_service() {
    local service=$1
    local dir="${SERVICE_DIRS[$service]}"

    if [ -z "$dir" ]; then
        log_error "未知服务: $service"
        return 1
    fi

    log_step "构建 $service..."
    run_in_builder "cd $dir && rm -rf dist && pnpm run build"
    log_success "$service 构建完成"
}

# 构建单个前端 (在容器中)
build_frontend() {
    local service=$1
    local dir="${SERVICE_DIRS[$service]}"

    if [ -z "$dir" ]; then
        log_error "未知服务: $service"
        return 1
    fi

    log_step "构建 $service..."
    run_in_builder "cd $dir && rm -rf dist && pnpm run build"
    log_success "$service 构建完成"
}

# 构建所有后端服务
build_all_backend() {
    build_shared

    for service in conversation user payment knowledge evolution file; do
        build_backend_service "$service"
    done
}

# 构建所有前端
build_all_frontend() {
    for service in web-client admin-client; do
        build_frontend "$service"
    done
}

# 构建所有
build_all() {
    log_info "开始构建所有服务 (使用 Docker 容器)..."
    build_builder_image
    install_deps
    build_all_backend
    build_all_frontend
    log_success "所有服务构建完成"
}

# 构建入口
do_build() {
    local target=${1:-all}

    # 确保 builder 镜像存在
    build_builder_image

    # 如果不是构建全部，先安装依赖
    if [ "$target" != "all" ]; then
        install_deps
    fi

    case $target in
        all)
            build_all
            ;;
        shared)
            build_shared
            ;;
        backend)
            build_shared
            build_all_backend
            ;;
        frontend)
            build_all_frontend
            ;;
        web-client|admin-client)
            build_frontend "$target"
            ;;
        conversation|user|payment|knowledge|evolution|file)
            build_shared
            build_backend_service "$target"
            ;;
        *)
            log_error "未知构建目标: $target"
            exit 1
            ;;
    esac
}

#===============================================================================
# Docker 操作函数
#===============================================================================

# 构建 Docker 镜像
build_docker_images() {
    local service=${1:-}
    local no_cache=${2:-}

    log_step "构建 Docker 镜像${no_cache:+ (--no-cache)}..."

    if [ -n "$service" ] && [ "$service" != "all" ] && [ "$service" != "--no-cache" ]; then
        local docker_service="${DOCKER_SERVICES[$service]}"
        if [ -n "$docker_service" ]; then
            $DOCKER_COMPOSE build $no_cache "$docker_service"
        else
            log_error "未知服务: $service"
            return 1
        fi
    else
        # 如果第一个参数是 --no-cache，则构建全部
        if [ "$service" = "--no-cache" ]; then
            no_cache="--no-cache"
        fi
        $DOCKER_COMPOSE build $no_cache
    fi

    log_success "Docker 镜像构建完成"
}

# 启动基础设施
start_infrastructure() {
    log_step "启动基础设施服务..."

    $DOCKER_COMPOSE up -d postgres redis neo4j

    # 等待数据库就绪
    wait_for_service localhost 5432 "PostgreSQL"
    wait_for_service localhost 6379 "Redis"
    wait_for_service localhost 7474 "Neo4j"

    log_success "基础设施启动完成"
}

# 运行数据库种子脚本 (使用 Docker 容器中的 ts-node)
run_db_seed() {
    log_step "运行数据库种子脚本..."

    # 确保 builder 镜像存在
    build_builder_image

    # 获取数据库连接信息
    local db_host="host.docker.internal"
    local db_port="${POSTGRES_PORT:-5432}"
    local db_user="${POSTGRES_USER:-postgres}"
    local db_password="${POSTGRES_PASSWORD:-postgres}"
    local db_name="${POSTGRES_DB:-iconsulting}"

    # 如果在 Linux 上，使用 docker network inspect 获取 postgres 容器 IP
    if [ "$(uname)" = "Linux" ]; then
        db_host=$($DOCKER_COMPOSE exec -T postgres hostname -i 2>/dev/null | tr -d '[:space:]' || echo "172.20.0.2")
    fi

    # 在容器中运行 seed 脚本
    docker run --rm \
        -v "$PROJECT_ROOT:/app" \
        -v "iconsulting-pnpm-store:/root/.local/share/pnpm/store" \
        --network "${PROJECT_NAME:-iconsulting}_iconsulting-network" \
        -e "DB_HOST=postgres" \
        -e "DB_PORT=$db_port" \
        -e "DB_USER=$db_user" \
        -e "DB_PASSWORD=$db_password" \
        -e "DB_NAME=$db_name" \
        -w /app/scripts \
        "$BUILDER_IMAGE" \
        sh -c "npm install --silent 2>/dev/null && npx ts-node seed.ts"

    if [ $? -eq 0 ]; then
        log_success "种子数据初始化完成"
    else
        log_warning "种子脚本执行失败，可能数据已存在"
    fi
}

# 初始化数据库 (自动检测并执行)
init_database() {
    log_step "检查数据库初始化状态..."

    # 等待 PostgreSQL 完全就绪
    sleep 3

    # 检查 admins 表是否存在 (作为初始化完成的标志)
    local table_exists
    table_exists=$($DOCKER_COMPOSE exec -T postgres psql -U postgres -d iconsulting -tAc "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'admins');" 2>/dev/null)

    if [ "$table_exists" = "t" ]; then
        log_success "数据库已初始化"
        # 即使数据库已初始化，也运行 seed 确保种子数据存在
        run_db_seed
        return 0
    fi

    log_info "首次部署，开始初始化数据库..."

    # 执行初始化脚本
    if $DOCKER_COMPOSE exec -T postgres psql -U postgres -d iconsulting -f /docker-entrypoint-initdb.d/init.sql > /dev/null 2>&1; then
        log_success "数据库初始化完成"

        # 验证关键表
        local admin_count
        admin_count=$($DOCKER_COMPOSE exec -T postgres psql -U postgres -d iconsulting -tAc "SELECT COUNT(*) FROM admins;" 2>/dev/null)
        log_info "默认管理员账户已创建 (用户名: admin, 密码: admin123)"

        # 验证 vector 扩展
        local vector_exists
        vector_exists=$($DOCKER_COMPOSE exec -T postgres psql -U postgres -d iconsulting -tAc "SELECT EXISTS (SELECT FROM pg_extension WHERE extname = 'vector');" 2>/dev/null)
        if [ "$vector_exists" = "t" ]; then
            log_success "pgvector 扩展已启用"
        else
            log_warning "pgvector 扩展未能启用，向量搜索功能可能受限"
        fi

        # 运行种子脚本确保数据完整
        run_db_seed
    else
        log_error "数据库初始化失败，请检查 init-db.sql"
        return 1
    fi
}

# 启动 Kong 网关 (DB-less 模式)
start_kong() {
    log_step "启动 Kong API 网关 (DB-less 模式)..."

    # Kong 使用 DB-less 模式，直接启动即可
    $DOCKER_COMPOSE up -d kong
    wait_for_service localhost 8000 "Kong"

    log_success "Kong 启动完成"
}

# 启动后端服务 (非 Docker 模式 - 已弃用，统一使用 Docker)
# 注意: 本函数已不再使用，保留仅作参考
start_backend_service_local() {
    log_warning "本地模式已弃用，将使用 Docker 模式启动服务"
    start_backend_service_docker "$1"
}

# 启动后端服务 (Docker 模式)
start_backend_service_docker() {
    local service=$1
    local docker_service="${DOCKER_SERVICES[$service]}"

    log_step "启动 $service (Docker)..."
    $DOCKER_COMPOSE up -d "$docker_service"

    local port="${SERVICE_PORTS[$service]}"
    wait_for_service localhost "$port" "$service"
}

# 启动所有后端服务
start_all_backend() {
    local mode=${1:-docker}

    for service in user payment knowledge conversation evolution file; do
        if [ "$mode" = "docker" ]; then
            start_backend_service_docker "$service"
        else
            start_backend_service_local "$service"
        fi
    done
}

# 启动 Nginx (静态文件服务)
start_nginx() {
    log_step "启动 iConsulting Nginx..."
    $DOCKER_COMPOSE up -d nginx
    wait_for_service localhost 8080 "Nginx"
    log_success "iConsulting Nginx 启动完成 (端口 8080)"

    # 自动配置系统nginx反向代理
    setup_system_nginx_proxy
}

# 自动配置系统nginx反向代理 (傻瓜式)
setup_system_nginx_proxy() {
    log_step "配置系统 Nginx 反向代理..."

    # 检查系统nginx是否存在
    if ! command -v nginx &> /dev/null; then
        log_warning "系统未安装 nginx，跳过反向代理配置"
        log_info "您可以通过 http://服务器IP:8080 直接访问"
        return 0
    fi

    # 检查nginx配置目录
    local nginx_available="/etc/nginx/sites-available"
    local nginx_enabled="/etc/nginx/sites-enabled"
    local nginx_conf_d="/etc/nginx/conf.d"

    # 生成配置文件内容
    local proxy_conf="# iConsulting 反向代理配置 (自动生成)
# 生成时间: $(date)

server {
    listen 80;
    listen [::]:80;
    server_name $DOMAIN;

    # Let's Encrypt 验证
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # 反向代理到 iConsulting Docker Nginx
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection \"upgrade\";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
"

    # 尝试写入配置 (需要sudo权限)
    if [ -d "$nginx_available" ]; then
        # Debian/Ubuntu 风格
        echo "$proxy_conf" | sudo tee "$nginx_available/iconsulting.conf" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            sudo ln -sf "$nginx_available/iconsulting.conf" "$nginx_enabled/iconsulting.conf" 2>/dev/null
            log_success "配置已写入 $nginx_available/iconsulting.conf"
        else
            log_warning "无法写入nginx配置，请手动配置或使用sudo运行"
            return 1
        fi
    elif [ -d "$nginx_conf_d" ]; then
        # CentOS/RHEL 风格
        echo "$proxy_conf" | sudo tee "$nginx_conf_d/iconsulting.conf" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            log_success "配置已写入 $nginx_conf_d/iconsulting.conf"
        else
            log_warning "无法写入nginx配置，请手动配置或使用sudo运行"
            return 1
        fi
    else
        log_warning "未找到nginx配置目录，请手动配置"
        return 1
    fi

    # 测试nginx配置
    log_info "测试 nginx 配置..."
    if sudo nginx -t 2>/dev/null; then
        log_success "nginx 配置测试通过"

        # 重载nginx
        log_info "重载 nginx..."
        sudo systemctl reload nginx 2>/dev/null || sudo nginx -s reload 2>/dev/null
        log_success "系统 nginx 已重载"

        echo ""
        log_success "反向代理配置完成！"
        echo -e "${CYAN}现在可以通过以下地址访问:${NC}"
        echo "  http://$DOMAIN"
        echo ""
        echo -e "${YELLOW}如需配置 HTTPS，请执行:${NC}"
        echo "  sudo certbot --nginx -d $DOMAIN"
    else
        log_error "nginx 配置测试失败，请检查配置"
        return 1
    fi
}

# 启动所有服务
start_all() {
    local mode=${1:-docker}

    log_info "开始启动所有服务 (模式: $mode)..."

    # 创建必要目录
    mkdir -p "$PROJECT_ROOT/logs"
    mkdir -p "$PROJECT_ROOT/pids"

    start_infrastructure
    init_database
    start_kong
    start_all_backend "$mode"
    start_nginx

    log_success "所有服务启动完成"
    do_status
}

# 重新构建 Docker 镜像
do_rebuild() {
    local target=${1:-all}
    local no_cache=""
    local cache_msg=""
    local run_seed=false

    # 检查是否有 --no-cache 或 --seed 参数
    for arg in "$@"; do
        if [ "$arg" = "--no-cache" ]; then
            no_cache="--no-cache"
            cache_msg=" (--no-cache)"
        fi
        if [ "$arg" = "--seed" ]; then
            run_seed=true
        fi
    done

    if [ "$target" = "all" ] || [ "$target" = "--no-cache" ] || [ "$target" = "--seed" ]; then
        # 如果第一个参数是 --no-cache 或 --seed，则 target 是 all
        if [ "$target" = "--no-cache" ] || [ "$target" = "--seed" ]; then
            target="all"
        fi

        log_step "重新构建所有服务镜像${cache_msg}..."
        $DOCKER_COMPOSE build $no_cache

        # 重启所有后端服务
        log_step "重启所有后端服务..."
        $DOCKER_COMPOSE up -d user-service payment-service knowledge-service conversation-service evolution-service file-service

        # 等待服务就绪
        sleep 5

        # 运行种子脚本
        run_db_seed
    else
        # 获取服务名
        local service_name=""
        case $target in
            user) service_name="user-service" ;;
            payment) service_name="payment-service" ;;
            knowledge) service_name="knowledge-service" ;;
            conversation) service_name="conversation-service" ;;
            evolution) service_name="evolution-service" ;;
            file) service_name="file-service" ;;
            nginx) service_name="nginx" ;;
            kong) service_name="kong" ;;
            *) service_name="$target-service" ;;
        esac

        log_step "重新构建 $target 镜像${cache_msg}..."
        $DOCKER_COMPOSE build $no_cache "$service_name"

        # 重启服务使用新镜像
        log_step "重启 $target 服务..."
        $DOCKER_COMPOSE up -d "$service_name"

        # 如果重建的是 evolution 服务，也运行 seed (因为管理员在这个服务)
        if [ "$target" = "evolution" ] || [ "$run_seed" = true ]; then
            sleep 3
            run_db_seed
        fi
    fi

    log_success "镜像重新构建并重启完成"
}

# 启动入口
do_start() {
    local target=${1:-all}
    local mode=${2:-docker}

    load_env

    case $target in
        all)
            start_all "$mode"
            ;;
        infra|infrastructure)
            start_infrastructure
            ;;
        kong)
            start_kong
            ;;
        nginx)
            start_nginx
            ;;
        postgres|redis|neo4j)
            $DOCKER_COMPOSE up -d "$target"
            ;;
        conversation|user|payment|knowledge|evolution|file)
            if [ "$mode" = "docker" ]; then
                start_backend_service_docker "$target"
            else
                start_backend_service_local "$target"
            fi
            ;;
        backend)
            start_all_backend "$mode"
            ;;
        *)
            log_error "未知启动目标: $target"
            exit 1
            ;;
    esac
}

#===============================================================================
# 停止函数
#===============================================================================

# 停止单个服务 (本地模式)
stop_service_local() {
    local service=$1

    log_step "停止 $service..."

    if command -v pm2 &> /dev/null; then
        pm2 stop "iconsulting-$service" 2>/dev/null || true
        pm2 delete "iconsulting-$service" 2>/dev/null || true
    else
        local pid_file="$PROJECT_ROOT/pids/$service.pid"
        if [ -f "$pid_file" ]; then
            kill $(cat "$pid_file") 2>/dev/null || true
            rm -f "$pid_file"
        fi
    fi

    log_success "$service 已停止"
}

# 停止单个服务 (Docker 模式)
stop_service_docker() {
    local service=$1
    local docker_service="${DOCKER_SERVICES[$service]}"

    if [ -n "$docker_service" ]; then
        log_step "停止 $service..."
        $DOCKER_COMPOSE stop "$docker_service"
        log_success "$service 已停止"
    fi
}

# 停止所有服务
stop_all() {
    local mode=${1:-docker}

    log_info "停止所有服务..."

    if [ "$mode" = "docker" ]; then
        $DOCKER_COMPOSE down
    else
        for service in conversation user payment knowledge evolution file; do
            stop_service_local "$service"
        done
        $DOCKER_COMPOSE down
    fi

    log_success "所有服务已停止"
}

# 停止入口
do_stop() {
    local target=${1:-all}
    local mode=${2:-docker}

    case $target in
        all)
            stop_all "$mode"
            ;;
        infra|infrastructure)
            $DOCKER_COMPOSE stop postgres redis neo4j
            ;;
        conversation|user|payment|knowledge|evolution|file)
            if [ "$mode" = "docker" ]; then
                stop_service_docker "$target"
            else
                stop_service_local "$target"
            fi
            ;;
        kong|postgres|redis|neo4j|nginx)
            $DOCKER_COMPOSE stop "$target"
            ;;
        *)
            log_error "未知停止目标: $target"
            exit 1
            ;;
    esac
}

#===============================================================================
# 重启函数
#===============================================================================

do_restart() {
    local target=${1:-all}
    local mode=${2:-docker}

    log_info "重启 $target..."
    do_stop "$target" "$mode"
    sleep 2
    do_start "$target" "$mode"
}

#===============================================================================
# 状态查看
#===============================================================================

do_status() {
    echo ""
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo -e "${CYAN}                    iConsulting 服务状态                        ${NC}"
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo ""

    # Docker 服务状态
    echo -e "${PURPLE}Docker 容器状态:${NC}"
    $DOCKER_COMPOSE ps
    echo ""

    # 端口检查
    echo -e "${PURPLE}服务端口检查:${NC}"
    printf "%-20s %-10s %-10s\n" "服务" "端口" "状态"
    echo "----------------------------------------"

    for service in "${!SERVICE_PORTS[@]}"; do
        local port="${SERVICE_PORTS[$service]}"
        if nc -z localhost "$port" 2>/dev/null; then
            printf "%-20s %-10s ${GREEN}%-10s${NC}\n" "$service" "$port" "运行中"
        else
            printf "%-20s %-10s ${RED}%-10s${NC}\n" "$service" "$port" "未运行"
        fi
    done

    echo ""

    # PM2 状态 (如果使用)
    if command -v pm2 &> /dev/null; then
        echo -e "${PURPLE}PM2 进程状态:${NC}"
        pm2 list 2>/dev/null | grep iconsulting || echo "无 PM2 管理的服务"
        echo ""
    fi
}

#===============================================================================
# 日志查看
#===============================================================================

do_logs() {
    local service=${1:-all}
    local lines=${2:-100}

    if [ "$service" = "all" ]; then
        $DOCKER_COMPOSE logs -f --tail="$lines"
    else
        local docker_service="${DOCKER_SERVICES[$service]}"
        if [ -n "$docker_service" ]; then
            $DOCKER_COMPOSE logs -f --tail="$lines" "$docker_service"
        else
            # 本地日志
            local log_file="$PROJECT_ROOT/logs/$service.log"
            if [ -f "$log_file" ]; then
                tail -f -n "$lines" "$log_file"
            else
                log_error "日志文件不存在: $log_file"
            fi
        fi
    fi
}

#===============================================================================
# 清理函数
#===============================================================================

do_clean() {
    local target=${1:-build}

    case $target in
        build)
            log_step "清理构建产物..."
            for dir in "${SERVICE_DIRS[@]}"; do
                rm -rf "$PROJECT_ROOT/$dir/dist"
            done
            log_success "构建产物已清理"
            ;;
        deps)
            log_step "清理依赖..."
            rm -rf node_modules
            for dir in "${SERVICE_DIRS[@]}"; do
                rm -rf "$PROJECT_ROOT/$dir/node_modules"
            done
            log_success "依赖已清理"
            ;;
        docker)
            log_step "清理 Docker 资源..."
            $DOCKER_COMPOSE down -v --rmi local
            docker system prune -f
            log_success "Docker 资源已清理"
            ;;
        logs)
            log_step "清理日志..."
            rm -rf "$PROJECT_ROOT/logs/*"
            log_success "日志已清理"
            ;;
        all)
            do_clean build
            do_clean deps
            do_clean docker
            do_clean logs
            ;;
        *)
            log_error "未知清理目标: $target (可选: build, deps, docker, logs, all)"
            exit 1
            ;;
    esac
}

#===============================================================================
# 完整部署
#===============================================================================

do_deploy() {
    local mode=${1:-all}
    local use_cache=false

    # 检查参数: --cache 使用缓存，否则默认 --no-cache
    for arg in "$@"; do
        if [ "$arg" = "--cache" ]; then
            use_cache=true
        fi
    done

    if [ "$use_cache" = true ]; then
        log_info "开始完整部署 (使用Docker缓存)..."
    else
        log_info "开始完整部署 (--no-cache 确保最新代码)..."
    fi

    check_environment

    # 构建代码 (在 builder 容器中)
    do_build all

    # 如果是 Docker 模式，构建镜像
    if [ "$mode" = "docker" ] || [ "$mode" = "all" ]; then
        if [ "$use_cache" = true ]; then
            build_docker_images ""
        else
            # deploy 命令默认使用 --no-cache，确保 shared 包被正确打包到镜像
            build_docker_images "" "--no-cache"
        fi
    fi

    # 启动
    do_start all docker

    # 配置 Kong 路由
    setup_kong_routes

    log_success "部署完成！"
    echo ""
    echo -e "${CYAN}访问地址:${NC}"
    echo "  用户前端:   https://$DOMAIN"
    echo "  管理后台:   https://$DOMAIN/admin"
    echo "  API 网关:   https://$DOMAIN/api"
    echo "  Kong 管理:  http://localhost:8001 (仅本地)"
    echo ""
    echo -e "${YELLOW}提示: 如需配置 SSL 证书，请执行:${NC}"
    echo "  ./deploy.sh ssl obtain"
    echo ""
}

# 完整部署 (含 SSL)
do_deploy_full() {
    log_info "开始完整部署 (含 SSL 证书)..."

    # 基础部署
    do_deploy docker

    # 安装并获取 SSL 证书
    do_ssl obtain

    # 配置自动续期
    do_ssl auto-renew

    log_success "完整部署完成 (含 SSL)！"
    echo ""
    echo -e "${CYAN}访问地址:${NC}"
    echo "  用户前端:   https://$DOMAIN"
    echo "  管理后台:   https://$DOMAIN/admin"
    echo ""
}

#===============================================================================
# 核弹级清理 (只删除本项目的Docker资源)
#===============================================================================
do_nuke() {
    # 获取项目名称 (docker-compose 使用目录名作为前缀)
    local project_name=$(basename "$PROJECT_ROOT" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]//g')

    echo -e "${RED}╔═══════════════════════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${RED}║                         ☢️  iConsulting 核弹级清理 ☢️                           ║${NC}"
    echo -e "${RED}║                                                                               ║${NC}"
    echo -e "${RED}║   这将彻底删除本项目 (${project_name}) 的所有资源：                           ║${NC}"
    echo -e "${RED}║   - 项目容器 (postgres, redis, neo4j, 各微服务等)                             ║${NC}"
    echo -e "${RED}║   - 项目镜像 (iconsulting-*, *-service 等)                                    ║${NC}"
    echo -e "${RED}║   - 项目数据卷 (postgres_data, redis_data, neo4j_data 等)                     ║${NC}"
    echo -e "${RED}║   - 项目网络 (iconsulting-network)                                            ║${NC}"
    echo -e "${RED}║   - 构建缓存 (iconsulting-builder, pnpm-store)                                ║${NC}"
    echo -e "${RED}║                                                                               ║${NC}"
    echo -e "${RED}║   ⚠️  不会影响其他项目的 Docker 资源                                          ║${NC}"
    echo -e "${RED}║   此操作不可撤销！项目数据将永久丢失！                                        ║${NC}"
    echo -e "${RED}╚═══════════════════════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    read -p "确认要执行核弹级清理吗？请输入 NUKE 确认: " confirm

    if [ "$confirm" != "NUKE" ]; then
        log_info "操作已取消"
        exit 0
    fi

    log_warning "开始清理 iConsulting 项目资源..."

    # 1. 使用 docker-compose 停止并删除项目容器、网络、数据卷、镜像
    log_step "停止并删除项目容器、网络、数据卷..."
    $DOCKER_COMPOSE down -v --rmi all --remove-orphans 2>/dev/null || true

    # 2. 删除项目相关镜像 (可能有残留)
    log_step "清理项目镜像..."
    # 删除 iconsulting 相关镜像
    docker images --format "{{.Repository}}:{{.Tag}}" | grep -E "^${project_name}|iconsulting|iconsulting-" | while read img; do
        docker rmi -f "$img" 2>/dev/null || true
    done
    # 删除 *-service 镜像
    docker images --format "{{.Repository}}:{{.Tag}}" | grep -E "user-service|payment-service|knowledge-service|conversation-service|evolution-service|file-service" | while read img; do
        docker rmi -f "$img" 2>/dev/null || true
    done
    # 删除 builder 镜像
    docker rmi -f iconsulting-builder:latest 2>/dev/null || true

    # 3. 删除项目数据卷 (可能有残留)
    log_step "清理项目数据卷..."
    docker volume ls -q | grep -E "^${project_name}_|postgres_data|redis_data|neo4j_data|neo4j_logs|minio_data|pnpm-store" | while read vol; do
        docker volume rm -f "$vol" 2>/dev/null || true
    done

    # 4. 删除项目网络 (可能有残留)
    log_step "清理项目网络..."
    docker network ls -q --filter name="${project_name}" | while read net; do
        docker network rm "$net" 2>/dev/null || true
    done
    docker network rm iconsulting-network 2>/dev/null || true

    # 5. 清理本地构建产物
    log_step "清理本地构建产物..."
    do_clean build 2>/dev/null || true

    # 6. 显示清理结果
    echo ""
    log_success "iConsulting 项目资源清理完成！"
    echo ""
    echo -e "${CYAN}清理后状态:${NC}"
    echo "  项目容器: $(docker ps -a --filter name=${project_name} -q | wc -l | tr -d ' ') 个"
    echo "  项目镜像: $(docker images --format '{{.Repository}}' | grep -E "${project_name}|iconsulting" | wc -l | tr -d ' ') 个"
    echo "  项目数据卷: $(docker volume ls -q | grep -E "${project_name}_|postgres_data|redis_data" | wc -l | tr -d ' ') 个"
    echo ""
    echo -e "${CYAN}重新部署请执行:${NC}"
    echo "  ./deploy.sh deploy"
    echo ""
}

#===============================================================================
# 数据重置 (只删除数据，不重新编译)
#===============================================================================
do_full_reset() {
    echo -e "${RED}╔═══════════════════════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${RED}║                              ⚠️  警告 ⚠️                                       ║${NC}"
    echo -e "${RED}║                                                                               ║${NC}"
    echo -e "${RED}║   这将删除所有数据库数据，包括：                                              ║${NC}"
    echo -e "${RED}║   - PostgreSQL 数据库中的所有表和数据                                         ║${NC}"
    echo -e "${RED}║   - Redis 缓存数据                                                            ║${NC}"
    echo -e "${RED}║   - Neo4j 图数据库中的所有数据                                                ║${NC}"
    echo -e "${RED}║                                                                               ║${NC}"
    echo -e "${RED}║   不会删除：Docker镜像、代码、构建产物                                        ║${NC}"
    echo -e "${RED}║   此操作不可撤销！                                                            ║${NC}"
    echo -e "${RED}╚═══════════════════════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    read -p "确认要重置所有数据吗？请输入 YES 确认: " confirm

    if [ "$confirm" != "YES" ]; then
        log_info "操作已取消"
        exit 0
    fi

    log_warning "开始数据重置..."

    # 1. 停止所有服务 (保留镜像，只删除数据卷)
    log_step "停止所有服务..."
    $DOCKER_COMPOSE down -v 2>/dev/null || true
    log_success "服务已停止，数据卷已删除"

    # 2. 启动基础设施 (数据库会自动初始化为空)
    log_step "启动基础设施..."
    do_start infra docker

    # 3. 等待数据库就绪
    wait_for_service localhost 5432 "PostgreSQL"
    wait_for_service localhost 6379 "Redis"
    wait_for_service localhost 7474 "Neo4j"

    # 4. 初始化数据库 (创建数据库和用户)
    log_step "初始化数据库..."
    sleep 3
    init_database 2>/dev/null || true

    # 5. 启动所有后端服务 (TypeORM synchronize:true 会自动创建表)
    log_step "启动后端服务..."
    do_start backend docker

    # 6. 启动 Nginx 和 Kong
    log_step "启动 Nginx..."
    do_start nginx docker
    log_step "启动 Kong..."
    do_start kong docker

    # 7. 等待服务就绪
    sleep 5

    # 8. 配置 Kong 路由
    log_step "配置 Kong API 网关..."
    do_kong setup 2>/dev/null || log_warning "Kong 配置跳过"

    log_success "数据重置完成！"
    echo ""
    do_status
}

#===============================================================================
# SSL 证书管理 (Let's Encrypt)
#===============================================================================

# 安装 Certbot
install_certbot() {
    log_step "检查/安装 Certbot..."

    if command -v certbot &> /dev/null; then
        log_success "Certbot 已安装"
        return 0
    fi

    # 检测操作系统
    if [ -f /etc/debian_version ]; then
        # Debian/Ubuntu
        apt-get update
        apt-get install -y certbot python3-certbot-nginx
    elif [ -f /etc/redhat-release ]; then
        # CentOS/RHEL
        yum install -y epel-release
        yum install -y certbot python3-certbot-nginx
    elif [ -f /etc/alpine-release ]; then
        # Alpine
        apk add certbot certbot-nginx
    else
        log_error "无法识别的操作系统，请手动安装 certbot"
        exit 1
    fi

    log_success "Certbot 安装完成"
}

# 申请 SSL 证书
obtain_ssl_cert() {
    local domain=${1:-$DOMAIN}
    local email=${2:-$ADMIN_EMAIL}

    log_step "申请 SSL 证书: $domain..."

    # 创建证书目录
    mkdir -p "$PROJECT_ROOT/nginx/ssl"

    # 停止系统 Nginx 和 Docker Nginx (释放 80 端口)
    systemctl stop nginx 2>/dev/null || true
    $DOCKER_COMPOSE stop nginx 2>/dev/null || true

    # 使用 standalone 模式申请证书
    certbot certonly \
        --standalone \
        --non-interactive \
        --agree-tos \
        --email "$email" \
        -d "$domain" \
        --cert-path "$PROJECT_ROOT/nginx/ssl/cert.pem" \
        --key-path "$PROJECT_ROOT/nginx/ssl/privkey.pem" \
        --fullchain-path "$PROJECT_ROOT/nginx/ssl/fullchain.pem"

    # 复制证书到项目目录
    if [ -d "/etc/letsencrypt/live/$domain" ]; then
        cp "/etc/letsencrypt/live/$domain/fullchain.pem" "$PROJECT_ROOT/nginx/ssl/"
        cp "/etc/letsencrypt/live/$domain/privkey.pem" "$PROJECT_ROOT/nginx/ssl/"
        chmod 644 "$PROJECT_ROOT/nginx/ssl/fullchain.pem"
        chmod 600 "$PROJECT_ROOT/nginx/ssl/privkey.pem"
        log_success "SSL 证书已获取并复制到 nginx/ssl/"
    else
        log_error "证书申请失败"
        return 1
    fi

    # 配置系统 nginx HTTPS
    configure_system_nginx_ssl "$domain"

    # 重启 Docker Nginx
    $DOCKER_COMPOSE up -d nginx

    log_success "SSL 证书配置完成"
}

# 配置系统 nginx 启用 HTTPS
configure_system_nginx_ssl() {
    local domain=${1:-$DOMAIN}
    local nginx_conf="/etc/nginx/sites-available/iconsulting.conf"

    log_step "配置系统 nginx HTTPS..."

    # 备份原配置
    cp "$nginx_conf" "${nginx_conf}.bak" 2>/dev/null || true

    # 生成新的 nginx 配置 (HTTP + HTTPS)
    cat > "$nginx_conf" << EOF
# iConsulting Nginx 配置 (HTTP 重定向 + HTTPS)
# 自动生成于 $(date)

# HTTP - 重定向到 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name $domain;

    # Let's Encrypt 验证
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # 其他请求重定向到 HTTPS
    location / {
        return 301 https://\$host\$request_uri;
    }
}

# HTTPS
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name $domain;

    # SSL 证书
    ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;

    # SSL 安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_session_cache shared:iconsulting_SSL:10m;
    ssl_session_timeout 10m;

    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-XSS-Protection "1; mode=block";

    # 代理到 Docker nginx (端口 8080)
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
EOF

    # 确保 sites-enabled 链接存在
    ln -sf "$nginx_conf" /etc/nginx/sites-enabled/iconsulting.conf

    # 测试配置
    if nginx -t; then
        systemctl start nginx
        systemctl reload nginx
        log_success "系统 nginx HTTPS 配置完成"
    else
        log_error "nginx 配置测试失败，恢复备份"
        cp "${nginx_conf}.bak" "$nginx_conf" 2>/dev/null || true
        systemctl start nginx
        return 1
    fi
}

# 续期 SSL 证书
renew_ssl_cert() {
    log_step "续期 SSL 证书..."

    certbot renew --quiet

    # 复制新证书
    if [ -d "/etc/letsencrypt/live/$DOMAIN" ]; then
        cp "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" "$PROJECT_ROOT/nginx/ssl/"
        cp "/etc/letsencrypt/live/$DOMAIN/privkey.pem" "$PROJECT_ROOT/nginx/ssl/"

        # 重载系统 Nginx 和 Docker Nginx
        systemctl reload nginx 2>/dev/null || true
        $DOCKER_COMPOSE exec nginx nginx -s reload 2>/dev/null || true
        log_success "SSL 证书续期完成"
    fi
}

# 配置证书自动续期
setup_ssl_auto_renew() {
    log_step "配置证书自动续期..."

    # 创建续期脚本
    cat > /etc/cron.d/certbot-renew << EOF
# 每天凌晨 3 点检查证书续期
0 3 * * * root certbot renew --quiet && cp /etc/letsencrypt/live/$DOMAIN/*.pem $PROJECT_ROOT/nginx/ssl/ && systemctl reload nginx && docker-compose -f $PROJECT_ROOT/docker-compose.yml exec -T nginx nginx -s reload
EOF

    log_success "自动续期已配置 (每天 3:00 检查)"
}

# SSL 操作入口
do_ssl() {
    local action=${1:-status}

    case $action in
        install)
            install_certbot
            ;;
        obtain|get)
            install_certbot
            obtain_ssl_cert "$2" "$3"
            ;;
        renew)
            renew_ssl_cert
            ;;
        auto-renew)
            setup_ssl_auto_renew
            ;;
        status)
            echo -e "${PURPLE}SSL 证书状态:${NC}"
            if [ -f "$PROJECT_ROOT/nginx/ssl/fullchain.pem" ]; then
                echo "证书文件: 存在"
                openssl x509 -in "$PROJECT_ROOT/nginx/ssl/fullchain.pem" -noout -dates 2>/dev/null || echo "无法读取证书信息"
            else
                echo "证书文件: 不存在"
            fi

            if command -v certbot &> /dev/null; then
                echo ""
                echo "Certbot 证书列表:"
                certbot certificates 2>/dev/null || echo "无证书"
            fi
            ;;
        *)
            log_error "未知 SSL 操作: $action (可选: install, obtain, renew, auto-renew, status)"
            exit 1
            ;;
    esac
}

#===============================================================================
# Kong API Gateway 配置
#===============================================================================

# 配置 Kong 路由
setup_kong_routes() {
    local kong_admin="${KONG_ADMIN_URL:-http://localhost:8001}"

    log_step "配置 Kong API Gateway 路由..."

    # 等待 Kong 就绪
    local max_attempts=30
    local attempt=1
    while [ $attempt -le $max_attempts ]; do
        if curl -s "$kong_admin" > /dev/null 2>&1; then
            break
        fi
        echo -n "."
        sleep 2
        attempt=$((attempt + 1))
    done

    if [ $attempt -gt $max_attempts ]; then
        log_error "Kong Admin API 不可用"
        return 1
    fi

    echo ""
    log_info "Kong Admin API 就绪"

    # 创建服务和路由
    log_info "创建微服务..."

    # User Service
    curl -s -X POST "$kong_admin/services" \
        -d "name=user-service" \
        -d "url=http://user-service:3001" > /dev/null 2>&1 || true

    curl -s -X POST "$kong_admin/services/user-service/routes" \
        -d "name=user-route" \
        -d "paths[]=/v1/users" \
        -d "paths[]=/v1/auth" \
        -d "strip_path=false" > /dev/null 2>&1 || true

    # Payment Service
    curl -s -X POST "$kong_admin/services" \
        -d "name=payment-service" \
        -d "url=http://payment-service:3002" > /dev/null 2>&1 || true

    curl -s -X POST "$kong_admin/services/payment-service/routes" \
        -d "name=payment-route" \
        -d "paths[]=/v1/payments" \
        -d "paths[]=/v1/balance" \
        -d "strip_path=false" > /dev/null 2>&1 || true

    # Knowledge Service
    curl -s -X POST "$kong_admin/services" \
        -d "name=knowledge-service" \
        -d "url=http://knowledge-service:3003" > /dev/null 2>&1 || true

    curl -s -X POST "$kong_admin/services/knowledge-service/routes" \
        -d "name=knowledge-route" \
        -d "paths[]=/v1/knowledge" \
        -d "strip_path=false" > /dev/null 2>&1 || true

    # Conversation Service
    curl -s -X POST "$kong_admin/services" \
        -d "name=conversation-service" \
        -d "url=http://conversation-service:3004" > /dev/null 2>&1 || true

    curl -s -X POST "$kong_admin/services/conversation-service/routes" \
        -d "name=conversation-route" \
        -d "paths[]=/v1/conversations" \
        -d "strip_path=false" > /dev/null 2>&1 || true

    # Evolution Service (Admin)
    curl -s -X POST "$kong_admin/services" \
        -d "name=evolution-service" \
        -d "url=http://evolution-service:3005" > /dev/null 2>&1 || true

    curl -s -X POST "$kong_admin/services/evolution-service/routes" \
        -d "name=evolution-route" \
        -d "paths[]=/v1/evolution" \
        -d "paths[]=/v1/memory" \
        -d "paths[]=/v1/admin" \
        -d "strip_path=false" > /dev/null 2>&1 || true

    log_info "配置全局插件..."

    # Rate Limiting
    curl -s -X POST "$kong_admin/plugins" \
        -d "name=rate-limiting" \
        -d "config.minute=100" \
        -d "config.policy=local" > /dev/null 2>&1 || true

    # CORS
    curl -s -X POST "$kong_admin/plugins" \
        -d "name=cors" \
        -d "config.origins=https://$DOMAIN,http://localhost" \
        -d "config.methods=GET,POST,PUT,DELETE,OPTIONS,PATCH" \
        -d "config.headers=Accept,Authorization,Content-Type,X-User-Id,X-Request-Id" \
        -d "config.credentials=true" \
        -d "config.max_age=3600" > /dev/null 2>&1 || true

    # Request ID
    curl -s -X POST "$kong_admin/plugins" \
        -d "name=correlation-id" \
        -d "config.header_name=X-Request-Id" \
        -d "config.generator=uuid" > /dev/null 2>&1 || true

    log_success "Kong 路由配置完成"

    # 显示配置结果
    echo ""
    echo -e "${PURPLE}已配置的服务:${NC}"
    curl -s "$kong_admin/services" | grep -o '"name":"[^"]*"' | sed 's/"name":"//g;s/"//g' | while read name; do
        echo "  - $name"
    done

    echo ""
    echo -e "${PURPLE}已配置的路由:${NC}"
    curl -s "$kong_admin/routes" | grep -o '"name":"[^"]*"' | sed 's/"name":"//g;s/"//g' | while read name; do
        echo "  - $name"
    done
}

# Kong 操作入口
do_kong() {
    local action=${1:-status}

    case $action in
        setup|init)
            setup_kong_routes
            ;;
        status)
            local kong_admin="${KONG_ADMIN_URL:-http://localhost:8001}"
            echo -e "${PURPLE}Kong 状态:${NC}"
            curl -s "$kong_admin" > /dev/null 2>&1 && echo "Kong Admin API: 运行中" || echo "Kong Admin API: 未运行"
            curl -s "http://localhost:8000" > /dev/null 2>&1 && echo "Kong Proxy: 运行中" || echo "Kong Proxy: 未运行"

            echo ""
            echo "服务数量: $(curl -s "$kong_admin/services" 2>/dev/null | grep -o '"total":[0-9]*' | cut -d: -f2 || echo 0)"
            echo "路由数量: $(curl -s "$kong_admin/routes" 2>/dev/null | grep -o '"total":[0-9]*' | cut -d: -f2 || echo 0)"
            ;;
        services)
            curl -s "http://localhost:8001/services" | python3 -m json.tool 2>/dev/null || curl -s "http://localhost:8001/services"
            ;;
        routes)
            curl -s "http://localhost:8001/routes" | python3 -m json.tool 2>/dev/null || curl -s "http://localhost:8001/routes"
            ;;
        plugins)
            curl -s "http://localhost:8001/plugins" | python3 -m json.tool 2>/dev/null || curl -s "http://localhost:8001/plugins"
            ;;
        *)
            log_error "未知 Kong 操作: $action (可选: setup, status, services, routes, plugins)"
            exit 1
            ;;
    esac
}

#===============================================================================
# 数据库操作
#===============================================================================

do_db() {
    local action=${1:-status}

    case $action in
        migrate)
            log_step "执行数据库迁移 (在 Docker 容器中)..."
            build_builder_image
            # 在容器中执行迁移命令
            for service in user payment knowledge conversation evolution file; do
                local dir="${SERVICE_DIRS[$service]}"
                # 先尝试生产环境迁移（使用编译后的JS），如果失败再尝试开发环境迁移（需要ts-node）
                run_in_builder "cd $dir && (pnpm run migration:run:prod 2>/dev/null || pnpm run migration:run 2>/dev/null)" || log_warning "$service 无迁移或迁移失败"
            done
            log_success "数据库迁移完成"
            ;;
        init)
            log_step "初始化数据库 (执行 init-db.sql)..."
            init_database
            ;;
        seed)
            log_step "初始化种子数据 (使用 ts-node)..."
            run_db_seed
            log_success "种子数据初始化完成"
            ;;
        backup)
            local backup_dir="$PROJECT_ROOT/backups/$(date +%Y%m%d_%H%M%S)"
            mkdir -p "$backup_dir"

            log_step "备份数据库..."
            $DOCKER_COMPOSE exec -T postgres pg_dump -U postgres iconsulting > "$backup_dir/postgres.sql"
            log_success "数据库备份到: $backup_dir"
            ;;
        restore)
            local backup_file=$2
            if [ -z "$backup_file" ]; then
                log_error "请指定备份文件: ./deploy.sh db restore <backup_file>"
                exit 1
            fi

            log_step "恢复数据库..."
            $DOCKER_COMPOSE exec -T postgres psql -U postgres iconsulting < "$backup_file"
            log_success "数据库恢复完成"
            ;;
        reset)
            log_warning "这将删除所有数据！"
            read -p "确认继续? (y/N) " confirm
            if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
                $DOCKER_COMPOSE down -v
                $DOCKER_COMPOSE up -d postgres redis neo4j
                wait_for_service localhost 5432 "PostgreSQL"
                do_db migrate
                log_success "数据库已重置"
            fi
            ;;
        status)
            echo -e "${PURPLE}数据库状态:${NC}"
            $DOCKER_COMPOSE exec postgres psql -U postgres -c "SELECT version();" 2>/dev/null || echo "PostgreSQL 未运行"
            $DOCKER_COMPOSE exec redis redis-cli ping 2>/dev/null || echo "Redis 未运行"
            curl -s http://localhost:7474 > /dev/null && echo "Neo4j 运行中" || echo "Neo4j 未运行"
            ;;
        *)
            log_error "未知数据库操作: $action (可选: migrate, seed, backup, restore, reset, status)"
            exit 1
            ;;
    esac
}

#===============================================================================
# 帮助信息
#===============================================================================

show_help() {
    cat << EOF

╔═══════════════════════════════════════════════════════════════════════════════╗
║                         iConsulting 部署管理脚本                              ║
║                         域名: $DOMAIN                              ║
╚═══════════════════════════════════════════════════════════════════════════════╝

用法: ./deploy.sh <command> [target] [options]

命令:
  build [target]          编译构建
                          target: all, shared, backend, frontend,
                                  conversation, user, payment, knowledge, evolution,
                                  web-client, admin-client

  rebuild [target] [--no-cache]
                          重新构建 Docker 镜像并重启服务
                          target: all, conversation, user, payment, knowledge, evolution,
                                  nginx, kong
                          --no-cache: 可选，忽略缓存完全重新构建

  start [target] [mode]   启动服务
                          target: all, infra, kong, nginx, backend,
                                  conversation, user, payment, knowledge, evolution,
                                  postgres, redis, neo4j
                          mode: docker (默认), local

  stop [target] [mode]    停止服务
                          (target 同上)

  restart [target] [mode] 重启服务
                          (target 同上)

  status                  查看所有服务状态

  logs [service] [lines]  查看日志
                          service: 服务名或 all
                          lines: 显示行数 (默认 100)

  clean [target]          清理
                          target: build, deps, docker, logs, all

  deploy [--cache]        完整部署 (构建 + 重建镜像 + 启动)
                          默认使用 --no-cache 确保 shared 包被正确打包
                          --cache: 可选，使用 Docker 缓存加速构建

  deploy-full             完整部署 (含 SSL 证书自动申请)

  full-reset              ⚠️ 数据重置 (只删除数据库数据，不重新编译)

  nuke                    ☢️ 核弹级清理 (只删除本项目的Docker资源：
                          容器、镜像、数据卷、网络，不影响其他项目)

  ssl <action>            SSL 证书管理 (Let's Encrypt)
                          action: install   - 安装 certbot
                                  obtain    - 申请证书
                                  renew     - 续期证书
                                  auto-renew - 配置自动续期
                                  status    - 查看证书状态

  kong <action>           Kong API Gateway 管理
                          action: setup     - 配置路由和插件
                                  status    - 查看状态
                                  services  - 查看服务列表
                                  routes    - 查看路由列表
                                  plugins   - 查看插件列表

  db <action>             数据库操作
                          action: init, migrate, seed, backup, restore, reset, status

  help                    显示此帮助信息

示例:
  ./deploy.sh deploy                    # 完整部署
  ./deploy.sh deploy-full               # 完整部署 (含 SSL)
  ./deploy.sh ssl obtain                # 申请 SSL 证书
  ./deploy.sh kong setup                # 配置 Kong 路由
  ./deploy.sh build conversation        # 只构建对话服务
  ./deploy.sh start backend local       # 本地模式启动所有后端
  ./deploy.sh restart user docker       # 重启用户服务 (Docker)
  ./deploy.sh logs conversation 200     # 查看对话服务最近200行日志
  ./deploy.sh clean all                 # 清理所有构建产物和依赖
  ./deploy.sh full-reset                # ⚠️ 重置所有数据库数据
  ./deploy.sh nuke                      # ☢️ 彻底删除所有Docker资源
  ./deploy.sh rebuild conversation      # 重新构建对话服务镜像 (使用缓存)
  ./deploy.sh rebuild conversation --no-cache  # 完全重新构建 (忽略缓存)
  ./deploy.sh db init                   # 初始化数据库 (首次部署)
  ./deploy.sh db backup                 # 备份数据库
  ./deploy.sh db migrate                # 执行数据库迁移

环境变量:
  DOMAIN          域名 (默认: iconsulting.szaiai.com)
  ADMIN_EMAIL     管理员邮箱 (用于 SSL 证书)

系统要求:
  - Docker (必须)
  - Docker Compose 或 docker compose (必须)
  - 无需安装 Node.js / pnpm (构建在 Docker 容器中进行)

EOF
}

#===============================================================================
# 主入口
#===============================================================================

main() {
    local command=${1:-help}
    shift || true

    # 对于 help 命令不需要检查环境
    if [ "$command" != "help" ] && [ "$command" != "--help" ] && [ "$command" != "-h" ]; then
        check_environment
    fi

    case $command in
        build)
            do_build "$@"
            ;;
        rebuild)
            do_rebuild "$@"
            ;;
        start)
            do_start "$@"
            ;;
        stop)
            do_stop "$@"
            ;;
        restart)
            do_restart "$@"
            ;;
        status)
            do_status
            ;;
        logs)
            do_logs "$@"
            ;;
        clean)
            do_clean "$@"
            ;;
        deploy)
            do_deploy "$@"
            ;;
        deploy-full)
            do_deploy_full
            ;;
        full-reset)
            do_full_reset
            ;;
        nuke)
            do_nuke
            ;;
        ssl)
            do_ssl "$@"
            ;;
        kong)
            do_kong "$@"
            ;;
        db)
            do_db "$@"
            ;;
        help|--help|-h)
            show_help
            ;;
        *)
            log_error "未知命令: $command"
            show_help
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"
