#!/bin/bash
# CTF 系统统一部署和启动脚本
# 自动检测运行环境：宿主机执行部署，容器内执行启动

set -e

# 检测是否在容器内运行
# 如果在容器内，会有 /app 目录且是容器启动脚本路径
if [ "$0" = "/docker-entrypoint.sh" ] || ([ -d "/app" ] && [ -f "/app/run.py" ] && [ "$(pwd)" = "/app" ]); then
    # ============================================
    # 容器内启动逻辑（原 entrypoint.sh）
    # ============================================
    
    # 设置 UTF-8 编码环境
    export LANG=C.UTF-8
    export LC_ALL=C.UTF-8
    export PYTHONIOENCODING=utf-8
    
    # 信号处理函数
    cleanup() {
        echo ""
        echo "收到停止信号，正在关闭服务..."
        
        # 停止 PostgreSQL
        if [ -f /var/lib/postgresql/data/pgdata/postmaster.pid ]; then
            echo "停止 PostgreSQL..."
            su - postgres -c "/usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/data/pgdata stop" || true
        fi
        
        exit 0
    }
    
    # 注册信号处理
    trap cleanup SIGTERM SIGINT
    
    echo "==================================="
    echo "CTF 题目生成系统启动中（单容器模式）"
    echo "==================================="
    
    # 修复 PostgreSQL 数据目录和日志权限
    echo "[1/7] 修复 PostgreSQL 权限..."
    mkdir -p /var/lib/postgresql/data
    mkdir -p /var/log/postgresql
    chown -R postgres:postgres /var/lib/postgresql /var/log/postgresql
    chmod 700 /var/lib/postgresql/data
    
    # 初始化 PostgreSQL（如果需要）
    if [ ! -d "/var/lib/postgresql/data/pgdata" ]; then
        echo "[2/7] 初始化 PostgreSQL 数据库..."
        su - postgres -c "/usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/data/pgdata" || {
            echo "❌ PostgreSQL 初始化失败"
            exit 1
        }
    
        # 配置 PostgreSQL
        echo "host all all 0.0.0.0/0 md5" >> /var/lib/postgresql/data/pgdata/pg_hba.conf
        echo "listen_addresses = '*'" >> /var/lib/postgresql/data/pgdata/postgresql.conf
        
        # 优化 PostgreSQL 配置（单容器模式）
        echo "max_connections = 100" >> /var/lib/postgresql/data/pgdata/postgresql.conf
        echo "shared_buffers = 256MB" >> /var/lib/postgresql/data/pgdata/postgresql.conf
        echo "effective_cache_size = 1GB" >> /var/lib/postgresql/data/pgdata/postgresql.conf
    else
        echo "[2/7] PostgreSQL 数据目录已存在，跳过初始化"
    fi
    
    # 确保数据目录权限正确
    chown -R postgres:postgres /var/lib/postgresql/data
    if [ -d "/var/lib/postgresql/data/pgdata" ]; then
        chmod 700 /var/lib/postgresql/data/pgdata
    fi
    
    # 启动 PostgreSQL
    echo "[3/7] 启动 PostgreSQL..."
    if [ -f /var/lib/postgresql/data/pgdata/postmaster.pid ]; then
        echo "检测到旧的 PostgreSQL 进程，清理..."
        rm -f /var/lib/postgresql/data/pgdata/postmaster.pid
    fi
    
    su - postgres -c "/usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/data/pgdata -l /var/log/postgresql/postgresql.log start" || {
        echo "❌ PostgreSQL 启动失败"
        exit 1
    }
    
    # 等待 PostgreSQL 就绪
    echo "[4/7] 等待 PostgreSQL 就绪..."
    MAX_RETRIES=30
    RETRY_COUNT=0
    while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
        if su - postgres -c "psql -c 'SELECT 1' > /dev/null 2>&1"; then
            echo "✓ PostgreSQL 已就绪"
            break
        fi
        RETRY_COUNT=$((RETRY_COUNT + 1))
        echo "等待中... ($RETRY_COUNT/$MAX_RETRIES)"
        sleep 1
    done
    
    if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
        echo "❌ PostgreSQL 启动超时"
        exit 1
    fi
    
    # 创建数据库和用户（使用 UTF-8 编码）
    echo "[5/7] 配置数据库..."
    su - postgres -c "psql -c \"CREATE DATABASE ctf WITH ENCODING 'UTF8' LC_COLLATE='C.UTF-8' LC_CTYPE='C.UTF-8' TEMPLATE=template0;\" 2>/dev/null || echo 'Database already exists'"
    su - postgres -c "psql -c \"ALTER USER postgres WITH PASSWORD '${POSTGRES_PASSWORD:-postgres}';\" 2>/dev/null || true"
    
    # 设置环境变量
    export DATABASE_TYPE=postgresql
    export POSTGRES_HOST=localhost
    export POSTGRES_PORT=5432
    export POSTGRES_DB=ctf
    export POSTGRES_USER=postgres
    
    # 初始化应用数据库
    if [ "$AUTO_INIT_DB" = "true" ]; then
        echo "[6/7] 初始化应用数据库..."
        cd /app

        # 检查数据库是否已经初始化（通过检查是否存在用户表）
        DB_INITIALIZED=false
        if su - postgres -c "psql -d ctf -c 'SELECT 1 FROM users LIMIT 1;' > /dev/null 2>&1"; then
            DB_INITIALIZED=true
            echo "数据库已初始化，跳过重置"
        fi

        # 只在数据库未初始化且提供了管理员配置时才重置并创建管理员
        if [ "$DB_INITIALIZED" = false ] && [ -n "$ADMIN_USERNAME" ] && [ -n "$ADMIN_EMAIL" ] && [ -n "$ADMIN_PASSWORD" ]; then
            echo "首次部署，将初始化数据库并创建管理员账户..."
            if python3 scripts/init_db.py --reset --yes -u "$ADMIN_USERNAME" -e "$ADMIN_EMAIL" -p "$ADMIN_PASSWORD"; then
                echo "✓ 数据库初始化成功，管理员账户已创建"
                echo "  用户名: $ADMIN_USERNAME"
                echo "  邮箱: $ADMIN_EMAIL"
            else
                echo "⚠ 数据库初始化失败"
            fi
        elif [ "$DB_INITIALIZED" = false ]; then
            # 数据库未初始化，但没有管理员配置，只做普通初始化
            echo "首次部署，初始化数据库..."
            if python3 scripts/init_db.py; then
                echo "✓ 数据库初始化成功"
            else
                echo "⚠ 数据库初始化失败"
            fi
        else
            echo "✓ 数据库已存在，跳过初始化"
        fi
    else
        echo "[6/7] 跳过数据库初始化（AUTO_INIT_DB=false）"
    fi
    
    # 检查依赖
    echo "[7/7] 检查依赖..."
    if command -v docker &> /dev/null; then
        echo "✓ Docker 已安装: $(docker --version 2>/dev/null || echo '版本信息不可用')"
    else
        echo "⚠ Docker 未安装或不可用"
    fi
    
    if command -v auggie &> /dev/null; then
        echo "✓ Auggie 已安装: $(auggie --version 2>/dev/null || echo '版本信息不可用')"
    else
        echo "⚠ Auggie 未安装"
    fi
    
    echo "==================================="
    echo "启动应用..."
    echo "==================================="
    
    # 启动应用
    cd /app
    
    # 创建必要的目录
    mkdir -p logs flask_session backups/database
    
    # 设置 Flask 环境变量
    export FLASK_APP=${FLASK_APP:-run.py}
    export FLASK_ENV=${FLASK_ENV:-production}
    
    # 根据环境模式启动
    if [ "$FLASK_ENV" = "production" ]; then
        echo "🚀 生产模式启动 - 监听 0.0.0.0:5002"
        echo "📝 应用日志: logs/production.log"
        echo "📝 访问日志已禁用（静态文件请求不记录）"
        echo "==================================="
        exec python3 run.py >> logs/production.log 2>&1
    else
        echo "🔧 开发模式启动"
        echo "📝 详细日志输出到控制台"
        echo "==================================="
        exec python3 run.py
    fi
    
    exit 0
fi

# ============================================
# 宿主机部署逻辑（原 deploy.sh）
# ============================================

# 获取脚本所在目录（项目根目录）
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

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

# 配置
MAX_HEALTH_CHECK_RETRIES=30
HEALTH_CHECK_INTERVAL=2
APP_PORT=${APP_PORT:-5002}

# 错误处理函数
error_exit() {
    echo -e "${RED}❌ 错误: $1${NC}" >&2
    exit 1
}

warning() {
    echo -e "${YELLOW}⚠️  警告: $1${NC}"
}

info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

success() {
    echo -e "${GREEN}✅ $1${NC}"
}

# 生成环境变量文件
generate_env() {
    info "生成安全密码和密钥..."
    
    # 检查 Python3
    if ! command -v python3 &> /dev/null; then
        error_exit "需要 Python3 来生成密码"
    fi
    
    # 生成 PostgreSQL 密码（24位，包含大小写字母、数字和特殊字符）
    POSTGRES_PASSWORD=$(python3 -c "import secrets, string; chars = string.ascii_letters + string.digits + '!@#$%^&*'; print(''.join(secrets.choice(chars) for _ in range(24)))")
    
    # 生成 Flask SECRET_KEY（64位十六进制）
    SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
    
    # 生成其他可选配置
    FLASK_ENV=${FLASK_ENV:-production}
    AUTO_INIT_DB=${AUTO_INIT_DB:-true}
    TZ=${TZ:-Asia/Shanghai}
    CPU_LIMIT=${CPU_LIMIT:-2.0}
    MEMORY_LIMIT=${MEMORY_LIMIT:-2G}
    CPU_RESERVATION=${CPU_RESERVATION:-0.5}
    MEMORY_RESERVATION=${MEMORY_RESERVATION:-512M}

    # 管理员账户配置（首次部署时自动创建）
    ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
    ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
    ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin123456}
    
    # 写入 .env 文件
    cat > .env << EOF
# PostgreSQL 配置
POSTGRES_PASSWORD=$POSTGRES_PASSWORD

# Flask 配置
SECRET_KEY=$SECRET_KEY
FLASK_ENV=$FLASK_ENV
FLASK_APP=run.py

# 应用配置
APP_PORT=$APP_PORT
AUTO_INIT_DB=$AUTO_INIT_DB
TZ=$TZ

# 管理员账户配置（首次部署时自动创建）
ADMIN_USERNAME=$ADMIN_USERNAME
ADMIN_EMAIL=$ADMIN_EMAIL
ADMIN_PASSWORD=$ADMIN_PASSWORD

# OpenAI API（可选，请填入您的 API Key）
OPENAI_API_KEY=

# 资源限制（可选，根据服务器配置调整）
CPU_LIMIT=$CPU_LIMIT
MEMORY_LIMIT=$MEMORY_LIMIT
CPU_RESERVATION=$CPU_RESERVATION
MEMORY_RESERVATION=$MEMORY_RESERVATION
EOF
    
    success ".env 文件已生成"
}

echo "==================================="
echo "CTF 系统 - 一键部署"
echo "==================================="
echo ""

# 步骤 1：检查应用程序文件
echo "📋 步骤 1/6: 检查应用程序文件"
if [ ! -f "docker/docker-compose.yml" ]; then
    error_exit "不存在 docker/docker-compose.yml"
fi

if [ ! -d "ctf/app" ] || [ ! -f "ctf/run.py" ]; then
    error_exit "应用程序文件不存在！"
fi

if [ ! -f "ctf/requirements.txt" ]; then
    warning "未找到 requirements.txt，可能影响依赖安装"
fi

success "应用程序文件已就绪"
echo ""

# 步骤 2：检查环境变量
echo "📋 步骤 2/6: 检查环境变量"
if [ ! -f ".env" ]; then
    warning ".env 文件不存在，自动生成..."
    echo ""
    generate_env
    echo ""
    info "📝 重要提示："
    info "  1. 请妥善保管 .env 文件，不要提交到版本控制系统"
    info "  2. 如需使用 OpenAI API，请在 .env 文件中填入 OPENAI_API_KEY"
    info "  3. 可以根据服务器配置调整资源限制参数"
    echo ""
else
    info ".env 文件已存在，跳过生成"
fi

# 检查密码是否修改
if grep -q "ChangeMe_StrongPassword_2024!" .env 2>/dev/null; then
    warning "检测到默认密码，强烈建议修改！"
    read -p "是否继续部署？(y/n) " -n 1 -r
    echo ""
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        info "请修改 .env 文件中的密码后重新运行脚本"
        info "编辑命令: nano .env"
        exit 1
    fi
fi

# 检查必要的环境变量
if ! grep -q "SECRET_KEY=" .env 2>/dev/null || ! grep -q "POSTGRES_PASSWORD=" .env 2>/dev/null; then
    warning ".env 文件可能不完整，建议检查"
fi

success "环境变量已配置"
echo ""

# 步骤 3：检查 Docker
echo "📋 步骤 3/6: 检查 Docker 环境"
if ! command -v docker &> /dev/null; then
    error_exit "Docker 未安装。请先安装 Docker: https://docs.docker.com/get-docker/"
fi

# 检查 Docker Compose（支持新版本的 docker compose 命令）
if command -v docker-compose2 &> /dev/null; then
    DOCKER_COMPOSE_CMD="docker-compose2"
elif docker compose version &> /dev/null; then
    DOCKER_COMPOSE_CMD="docker compose"
    info "使用新版本的 docker compose 命令"
else
    error_exit "Docker Compose 未安装。请先安装 Docker Compose"
fi

if ! docker ps &> /dev/null; then
    error_exit "Docker 未运行或权限不足。请确保 Docker 服务正在运行，并且当前用户有权限访问 Docker"
fi

# 检查 Docker 版本
DOCKER_VERSION=$(docker --version | cut -d ' ' -f 3 | cut -d ',' -f 1)
info "Docker 版本: $DOCKER_VERSION"

success "Docker 环境正常"
echo ""

# 步骤 4：构建镜像
echo "📋 步骤 4/6: 构建镜像"
info "正在构建镜像（这可能需要几分钟）..."
cd docker
if $DOCKER_COMPOSE_CMD -f docker-compose.yml build --no-cache=false; then
    success "镜像构建成功"
else
    error_exit "镜像构建失败"
fi
cd ..
echo ""

# 步骤 5：启动服务
echo "📋 步骤 5/6: 启动服务"
info "正在启动容器..."

# 停止旧容器（如果存在）
if docker ps -a --format '{{.Names}}' | grep -q "^ctf-app$"; then
    info "检测到旧容器，正在停止..."
    cd docker
    $DOCKER_COMPOSE_CMD -f docker-compose.yml down 2>/dev/null || true
    cd ..
fi

cd docker
if $DOCKER_COMPOSE_CMD -f docker-compose.yml up -d; then
    success "容器启动成功"
else
    error_exit "容器启动失败"
fi
cd ..

echo ""
info "等待服务就绪..."
sleep 3

# 步骤 6：健康检查
echo "📋 步骤 6/6: 健康检查"
RETRY_COUNT=0
HEALTHY=false

while [ $RETRY_COUNT -lt $MAX_HEALTH_CHECK_RETRIES ]; do
    # 检查容器状态
    CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' ctf-app 2>/dev/null || echo "not_found")
    
    if [ "$CONTAINER_STATUS" = "not_found" ]; then
        error_exit "容器未找到"
    fi
    
    if [ "$CONTAINER_STATUS" = "exited" ]; then
        error_exit "容器已退出。查看日志: cd docker && docker-compose2 logs ctf-app"
    fi
    
    # 检查健康状态
    HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' ctf-app 2>/dev/null || echo "none")
    
    if [ "$HEALTH_STATUS" = "healthy" ]; then
        HEALTHY=true
        break
    fi
    
    # 尝试 HTTP 检查
    if curl -f -s http://localhost:${APP_PORT}/health > /dev/null 2>&1 || \
       curl -f -s http://localhost:${APP_PORT}/ > /dev/null 2>&1; then
        HEALTHY=true
        break
    fi
    
    RETRY_COUNT=$((RETRY_COUNT + 1))
    echo "等待服务就绪... ($RETRY_COUNT/$MAX_HEALTH_CHECK_RETRIES)"
    sleep $HEALTH_CHECK_INTERVAL
done

if [ "$HEALTHY" = true ]; then
    success "服务健康检查通过"
else
    warning "健康检查超时，但容器可能仍在启动中"
    info "查看日志: cd docker && docker-compose2 logs -f ctf-app"
fi

echo ""
echo "==================================="
success "部署完成！"
echo "==================================="
echo ""

# 显示服务状态
echo "📊 服务状态："
cd docker
$DOCKER_COMPOSE_CMD -f docker-compose.yml ps
cd ..
echo ""

echo "📊 服务信息："
echo "  - 应用地址: http://localhost:${APP_PORT}"
echo "  - 容器名称: ctf-app"
echo "  - 健康状态: $(docker inspect --format='{{.State.Health.Status}}' ctf-app 2>/dev/null || echo '未配置')"
echo ""

echo "📝 下一步："
echo "  1. 访问应用: http://localhost:${APP_PORT}"
echo "  2. 使用管理员账户登录（默认: admin / admin123456）"
echo "  3. 查看日志: cd docker && docker-compose logs -f ctf-app"
echo ""
echo "⚠️  安全提示："
echo "  - 首次登录后请立即修改管理员密码"
echo "  - 管理员账户信息保存在 .env 文件中"
echo ""

echo "🔧 常用命令："
echo "  - 查看日志: cd docker && docker-compose logs -f ctf-app"
echo "  - 查看健康状态: docker inspect --format='{{.State.Health.Status}}' ctf-app"
echo "  - 停止服务: cd docker && docker-compose down"
echo "  - 重启服务: cd docker && docker-compose restart"
echo "  - 进入容器: docker exec -it ctf-app bash"
echo "  - 查看资源使用: docker stats ctf-app"
echo ""
