#!/bin/bash

# QAUP 性能优化脚本

set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

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

print_message() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
}

# 获取系统信息
get_system_info() {
    local total_mem=$(free -m | awk 'NR==2{print $2}')
    local cpu_cores=$(nproc)
    local total_disk=$(df -BG . | awk 'NR==2 {print $2}' | sed 's/G//')
    
    echo "系统信息:"
    echo "  CPU 核心数: $cpu_cores"
    echo "  总内存: ${total_mem}MB"
    echo "  可用磁盘: ${total_disk}GB"
    echo ""
    
    # 导出变量供其他函数使用
    export TOTAL_MEM=$total_mem
    export CPU_CORES=$cpu_cores
    export TOTAL_DISK=$total_disk
}

# 优化 JVM 参数
optimize_jvm() {
    print_message $BLUE "优化 JVM 参数..."
    
    local heap_size
    local metaspace_size
    
    # 根据系统内存计算 JVM 参数
    if [ $TOTAL_MEM -ge 8192 ]; then
        # 8GB+ 内存
        heap_size="4g"
        metaspace_size="512m"
    elif [ $TOTAL_MEM -ge 4096 ]; then
        # 4-8GB 内存
        heap_size="2g"
        metaspace_size="256m"
    else
        # 4GB 以下内存
        heap_size="1g"
        metaspace_size="128m"
    fi
    
    # 生成优化的 JVM 参数
    local jvm_opts="-Dname=qaup-admin.jar"
    jvm_opts="$jvm_opts -Duser.timezone=Asia/Shanghai"
    jvm_opts="$jvm_opts -server"
    jvm_opts="$jvm_opts -Xms${heap_size} -Xmx${heap_size}"
    jvm_opts="$jvm_opts -XX:MetaspaceSize=${metaspace_size} -XX:MaxMetaspaceSize=${metaspace_size}"
    
    # GC 优化
    if [ $CPU_CORES -ge 4 ]; then
        # 多核使用 G1GC
        jvm_opts="$jvm_opts -XX:+UseG1GC"
        jvm_opts="$jvm_opts -XX:G1HeapRegionSize=16m"
        jvm_opts="$jvm_opts -XX:MaxGCPauseMillis=200"
        jvm_opts="$jvm_opts -XX:+UseStringDeduplication"
    else
        # 少核使用 Parallel GC
        jvm_opts="$jvm_opts -XX:+UseParallelGC"
        jvm_opts="$jvm_opts -XX:+UseParallelOldGC"
    fi
    
    # 性能监控和调试
    jvm_opts="$jvm_opts -XX:+HeapDumpOnOutOfMemoryError"
    jvm_opts="$jvm_opts -XX:HeapDumpPath=/app/logs/"
    jvm_opts="$jvm_opts -XX:+PrintGCDetails"
    jvm_opts="$jvm_opts -XX:+PrintGCTimeStamps"
    jvm_opts="$jvm_opts -Xloggc:/app/logs/gc.log"
    
    # 更新环境文件
    if [ -f "$PROJECT_ROOT/.env" ]; then
        # 备份原文件
        cp "$PROJECT_ROOT/.env" "$PROJECT_ROOT/.env.backup.$(date +%Y%m%d_%H%M%S)"
        
        # 更新 JVM_OPTS
        if grep -q "^JVM_OPTS=" "$PROJECT_ROOT/.env"; then
            sed -i "s|^JVM_OPTS=.*|JVM_OPTS=$jvm_opts|" "$PROJECT_ROOT/.env"
        else
            echo "JVM_OPTS=$jvm_opts" >> "$PROJECT_ROOT/.env"
        fi
        
        print_message $GREEN "✓ JVM 参数已优化"
        echo "  堆内存: $heap_size"
        echo "  元空间: $metaspace_size"
        echo "  GC算法: $(echo $jvm_opts | grep -o 'XX:+Use[A-Za-z0-9]*GC')"
    else
        print_message $RED "✗ 环境文件不存在: $PROJECT_ROOT/.env"
    fi
}

# 优化数据库配置
optimize_database() {
    print_message $BLUE "优化数据库配置..."
    
    local shared_buffers
    local effective_cache_size
    local work_mem
    local maintenance_work_mem
    local max_connections
    
    # 根据系统内存计算数据库参数
    if [ $TOTAL_MEM -ge 8192 ]; then
        # 8GB+ 内存
        shared_buffers="2GB"
        effective_cache_size="6GB"
        work_mem="16MB"
        maintenance_work_mem="256MB"
        max_connections="200"
    elif [ $TOTAL_MEM -ge 4096 ]; then
        # 4-8GB 内存
        shared_buffers="1GB"
        effective_cache_size="3GB"
        work_mem="8MB"
        maintenance_work_mem="128MB"
        max_connections="150"
    else
        # 4GB 以下内存
        shared_buffers="512MB"
        effective_cache_size="1536MB"
        work_mem="4MB"
        maintenance_work_mem="64MB"
        max_connections="100"
    fi
    
    # 生成优化的 PostgreSQL 配置
    cat > "$PROJECT_ROOT/docker/postgres/postgresql-optimized.conf" << EOF
# PostgreSQL 性能优化配置
# 自动生成于: $(date)

# 连接设置
listen_addresses = '*'
port = 5432
max_connections = $max_connections
superuser_reserved_connections = 3

# 内存设置
shared_buffers = $shared_buffers
effective_cache_size = $effective_cache_size
work_mem = $work_mem
maintenance_work_mem = $maintenance_work_mem

# 检查点设置
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100

# 查询规划器设置
random_page_cost = 1.1
effective_io_concurrency = $([ $TOTAL_DISK -gt 100 ] && echo "200" || echo "100")

# 写前日志设置
wal_level = replica
max_wal_size = 2GB
min_wal_size = 80MB

# 自动清理设置
autovacuum = on
autovacuum_max_workers = 3
autovacuum_naptime = 1min
autovacuum_vacuum_threshold = 50
autovacuum_analyze_threshold = 50

# 日志设置
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_min_duration_statement = 1000
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on

# 时区设置
timezone = 'Asia/Shanghai'
log_timezone = 'Asia/Shanghai'

# 字符集设置
lc_messages = 'en_US.UTF-8'
lc_monetary = 'en_US.UTF-8'
lc_numeric = 'en_US.UTF-8'
lc_time = 'en_US.UTF-8'

# 默认文本搜索配置
default_text_search_config = 'pg_catalog.english'

# 并发设置
max_worker_processes = $CPU_CORES
max_parallel_workers_per_gather = $([ $CPU_CORES -gt 2 ] && echo "2" || echo "1")
max_parallel_workers = $CPU_CORES
EOF
    
    print_message $GREEN "✓ 数据库配置已优化"
    echo "  共享缓冲区: $shared_buffers"
    echo "  有效缓存: $effective_cache_size"
    echo "  工作内存: $work_mem"
    echo "  最大连接数: $max_connections"
}

# 优化 Nginx 配置
optimize_nginx() {
    print_message $BLUE "优化 Nginx 配置..."
    
    # 生成优化的 Nginx 配置
    cat > "$PROJECT_ROOT/docker/nginx/nginx-optimized.conf" << EOF
# Nginx 性能优化配置
# 自动生成于: $(date)

user nginx;
worker_processes $CPU_CORES;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

# 优化事件处理
events {
    worker_connections $([ $TOTAL_MEM -gt 4096 ] && echo "2048" || echo "1024");
    use epoll;
    multi_accept on;
    worker_rlimit_nofile 65535;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # 日志格式
    log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
                    '\$status \$body_bytes_sent "\$http_referer" '
                    '"\$http_user_agent" "\$http_x_forwarded_for" '
                    'rt=\$request_time uct="\$upstream_connect_time" '
                    'uht="\$upstream_header_time" urt="\$upstream_response_time"';

    access_log /var/log/nginx/access.log main;

    # 基本设置
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;

    # 缓冲区设置
    client_body_buffer_size 128k;
    client_max_body_size 50m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    output_buffers 1 32k;
    postpone_output 1460;

    # 超时设置
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;

    # 缓存设置
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # 包含虚拟主机配置
    include /etc/nginx/conf.d/*.conf;
}
EOF
    
    print_message $GREEN "✓ Nginx 配置已优化"
    echo "  工作进程数: $CPU_CORES"
    echo "  连接数: $([ $TOTAL_MEM -gt 4096 ] && echo "2048" || echo "1024")"
    echo "  缓冲区: 优化完成"
}

# 优化 Redis 配置
optimize_redis() {
    print_message $BLUE "优化 Redis 配置..."
    
    local maxmemory
    
    # 根据系统内存计算 Redis 内存限制
    if [ $TOTAL_MEM -ge 8192 ]; then
        maxmemory="1gb"
    elif [ $TOTAL_MEM -ge 4096 ]; then
        maxmemory="512mb"
    else
        maxmemory="256mb"
    fi
    
    # 生成优化的 Redis 配置
    cat > "$PROJECT_ROOT/docker/redis/redis-optimized.conf" << EOF
# Redis 性能优化配置
# 自动生成于: $(date)

# 内存设置
maxmemory $maxmemory
maxmemory-policy allkeys-lru

# 持久化设置
save 900 1
save 300 10
save 60 10000

# AOF 设置
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 网络设置
tcp-keepalive 300
timeout 0

# 客户端设置
maxclients 10000

# 慢日志设置
slowlog-log-slower-than 10000
slowlog-max-len 128

# 其他优化
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
EOF
    
    print_message $GREEN "✓ Redis 配置已优化"
    echo "  最大内存: $maxmemory"
    echo "  淘汰策略: allkeys-lru"
    echo "  持久化: AOF + RDB"
}

# 优化系统参数
optimize_system() {
    print_message $BLUE "优化系统参数..."
    
    # 检查是否有 root 权限
    if [ "$EUID" -ne 0 ]; then
        print_message $YELLOW "⚠ 需要 root 权限来优化系统参数"
        print_message $YELLOW "请手动执行以下命令或使用 sudo 运行此脚本："
        echo ""
        echo "# 网络优化"
        echo "echo 'net.core.somaxconn = 65535' >> /etc/sysctl.conf"
        echo "echo 'net.core.netdev_max_backlog = 5000' >> /etc/sysctl.conf"
        echo "echo 'net.ipv4.tcp_max_syn_backlog = 65535' >> /etc/sysctl.conf"
        echo "echo 'net.ipv4.tcp_fin_timeout = 10' >> /etc/sysctl.conf"
        echo "echo 'net.ipv4.tcp_tw_reuse = 1' >> /etc/sysctl.conf"
        echo "echo 'net.ipv4.tcp_keepalive_time = 600' >> /etc/sysctl.conf"
        echo ""
        echo "# 文件描述符限制"
        echo "echo '* soft nofile 65535' >> /etc/security/limits.conf"
        echo "echo '* hard nofile 65535' >> /etc/security/limits.conf"
        echo ""
        echo "# 应用生效"
        echo "sysctl -p"
        return
    fi
    
    # 网络参数优化
    cat >> /etc/sysctl.conf << EOF

# QAUP 系统优化参数
# 添加时间: $(date)

# 网络优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15

# 虚拟内存优化
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5

EOF
    
    # 文件描述符限制
    cat >> /etc/security/limits.conf << EOF

# QAUP 系统文件描述符限制
# 添加时间: $(date)
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

EOF
    
    # 应用系统参数
    sysctl -p
    
    print_message $GREEN "✓ 系统参数已优化"
}

# 创建性能监控脚本
create_performance_monitor() {
    print_message $BLUE "创建性能监控脚本..."
    
    cat > "$PROJECT_ROOT/docker/performance-monitor.sh" << 'EOF'
#!/bin/bash

# QAUP 性能监控脚本

MONITOR_LOG="./logs/performance-$(date +%Y%m%d).log"

# 记录性能数据
log_performance() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    {
        echo "[$timestamp] 性能监控数据"
        echo "================================"
        
        # 系统资源
        echo "系统负载: $(uptime | awk -F'load average:' '{print $2}')"
        echo "内存使用: $(free | awk 'NR==2{printf "%.2f%%", $3*100/$2}')"
        echo "磁盘使用: $(df -h . | awk 'NR==2{print $5}')"
        
        # 容器资源
        echo ""
        echo "容器资源使用:"
        docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"
        
        # 应用性能
        echo ""
        echo "应用响应时间:"
        local app_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:8080/actuator/health 2>/dev/null || echo "N/A")
        local nginx_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost/health 2>/dev/null || echo "N/A")
        echo "应用健康检查: ${app_time}s"
        echo "Nginx健康检查: ${nginx_time}s"
        
        # 数据库性能
        echo ""
        echo "数据库连接数:"
        local db_connections=$(docker exec qaup-postgres psql -U postgres -d qaup -t -c "SELECT count(*) FROM pg_stat_activity;" 2>/dev/null | xargs || echo "N/A")
        echo "活跃连接: $db_connections"
        
        echo "================================"
        echo ""
        
    } >> "$MONITOR_LOG"
}

# 主循环
while true; do
    log_performance
    sleep 300  # 每5分钟记录一次
done
EOF
    
    chmod +x "$PROJECT_ROOT/docker/performance-monitor.sh"
    
    print_message $GREEN "✓ 性能监控脚本已创建"
}

# 应用所有优化
apply_all_optimizations() {
    print_message $GREEN "开始应用所有性能优化..."
    echo ""
    
    get_system_info
    
    optimize_jvm
    echo ""
    
    optimize_database
    echo ""
    
    optimize_nginx
    echo ""
    
    optimize_redis
    echo ""
    
    optimize_system
    echo ""
    
    create_performance_monitor
    echo ""
    
    print_message $GREEN "========================================="
    print_message $GREEN "性能优化完成！"
    print_message $GREEN "========================================="
    echo ""
    
    print_message $BLUE "优化摘要:"
    echo "  ✓ JVM 参数已根据系统配置优化"
    echo "  ✓ 数据库配置已优化"
    echo "  ✓ Nginx 配置已优化"
    echo "  ✓ Redis 配置已优化"
    echo "  ✓ 系统参数已优化（如有权限）"
    echo "  ✓ 性能监控脚本已创建"
    echo ""
    
    print_message $YELLOW "下一步操作:"
    echo "  1. 重启服务以应用配置: ./deploy.sh restart"
    echo "  2. 启动性能监控: ./docker/performance-monitor.sh &"
    echo "  3. 验证优化效果: ./docker/monitor.sh resources"
    echo ""
}

# 显示帮助信息
show_help() {
    echo "QAUP 性能优化脚本"
    echo ""
    echo "用法: $0 [命令]"
    echo ""
    echo "命令:"
    echo "  all         应用所有优化"
    echo "  jvm         优化 JVM 参数"
    echo "  database    优化数据库配置"
    echo "  nginx       优化 Nginx 配置"
    echo "  redis       优化 Redis 配置"
    echo "  system      优化系统参数"
    echo "  monitor     创建性能监控脚本"
    echo ""
    echo "示例:"
    echo "  $0 all              # 应用所有优化"
    echo "  $0 jvm              # 仅优化 JVM"
    echo "  sudo $0 system      # 优化系统参数（需要 root）"
}

# 主函数
main() {
    if [ $# -eq 0 ]; then
        show_help
        exit 0
    fi
    
    local command=$1
    
    # 获取系统信息
    get_system_info
    
    case $command in
        all)
            apply_all_optimizations
            ;;
        jvm)
            optimize_jvm
            ;;
        database)
            optimize_database
            ;;
        nginx)
            optimize_nginx
            ;;
        redis)
            optimize_redis
            ;;
        system)
            optimize_system
            ;;
        monitor)
            create_performance_monitor
            ;;
        help|--help|-h)
            show_help
            ;;
        *)
            print_message $RED "未知命令: $command"
            show_help
            exit 1
            ;;
    esac
}

main "$@"