#!/bin/bash

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

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"
}

# 配置变量
INSTALL_DIR="${1:-$(pwd)}"  # 使用第一个参数作为安装目录，如果没有参数则使用当前目录
TEMP_DIR="/tmp/metrics-install-$$"
VERSION_FILE="version.json"

# 加载配置文件
load_config() {
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local config_file="$script_dir/config.env"
    
    if [[ -f "$config_file" ]]; then
        log_info "加载配置文件: $config_file"
        # 导出配置文件中的环境变量
        set -a  # 自动导出所有变量
        source "$config_file"
        set +a  # 关闭自动导出
        log_success "配置文件加载完成"
    else
        log_warning "配置文件不存在: $config_file，使用默认配置"
    fi
}

# 复制配置文件到安装目录
copy_config_files() {
    log_info "复制配置文件到安装目录..."
    
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local source_config="$script_dir/config.env"
    local target_config="$INSTALL_DIR/config.env"
    
    if [[ -f "$source_config" ]]; then
        # 检查源文件和目标文件是否是同一个文件
        if [[ "$source_config" == "$target_config" ]]; then
            log_info "配置文件已在目标位置，跳过复制"
            log_success "配置文件已存在: $target_config"
        else
            if cp "$source_config" "$target_config"; then
                log_success "配置文件复制完成: $target_config"
            else
                log_error "配置文件复制失败"
                return 1
            fi
        fi
    else
        log_warning "源配置文件不存在: $source_config"
    fi
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本需要 root 权限运行"
        log_info "请使用: sudo $0 [安装目录]"
        log_info "如果不指定安装目录，将使用当前目录: $(pwd)"
        exit 1
    fi
}

# 检查系统要求
check_system() {
    log_info "检查系统要求..."
    
    # 检查操作系统
    if [[ ! -f /etc/os-release ]]; then
        log_error "无法检测操作系统版本"
        exit 1
    fi
    
    source /etc/os-release
    log_info "检测到操作系统: $NAME $VERSION"
    
    # 检查系统架构
    arch=$(uname -m)
    log_info "系统架构: $arch"
    
    # 检查磁盘空间
    available_space=$(df / | awk 'NR==2 {print $4}')
    if [[ $available_space -lt 10485760 ]]; then  # 10GB in KB
        log_warning "可用磁盘空间不足 10GB，当前可用: $(($available_space / 1024 / 1024))GB"
    fi
    
    # 检查内存
    total_mem=$(free -m | awk 'NR==2{print $2}')
    if [[ $total_mem -lt 4096 ]]; then  # 4GB
        log_warning "系统内存不足 4GB，当前: ${total_mem}MB"
    fi
}

# 查找版本文件
find_version_file() {
    log_info "查找版本信息文件..."
    
    # 在当前目录查找
    if [[ -f "$VERSION_FILE" ]]; then
        VERSION_FILE_PATH="$VERSION_FILE"
        log_success "找到版本文件: $VERSION_FILE"
        return 0
    fi
    
    # 在 artifact 目录查找
    for version_dir in artifact/*/; do
        if [[ -f "${version_dir}${VERSION_FILE}" ]]; then
            VERSION_FILE_PATH="${version_dir}${VERSION_FILE}"
            log_success "找到版本文件: $VERSION_FILE_PATH"
            return 0
        fi
    done
    
    log_error "未找到版本信息文件 $VERSION_FILE"
    exit 1
}

# 解析版本信息
parse_version_info() {
    log_info "解析版本信息..."
    
    if [[ ! -f "$VERSION_FILE_PATH" ]]; then
        log_error "版本文件不存在: $VERSION_FILE_PATH"
        exit 1
    fi
    
    # 使用 jq 解析 JSON（如果可用）
    if command -v jq &> /dev/null; then
        # 验证JSON文件格式
        if ! jq empty "$VERSION_FILE_PATH" 2>/dev/null; then
            log_error "JSON文件格式错误，请检查 $VERSION_FILE_PATH"
            exit 1
        fi
        
        VERSION=$(jq -r '.version' "$VERSION_FILE_PATH")
        BUILD_TIME=$(jq -r '.build_time' "$VERSION_FILE_PATH")
        
        # 解析 artifact_list
        if jq -e '.artifact_list' "$VERSION_FILE_PATH" > /dev/null 2>&1; then
            jq -r '.artifact_list | to_entries[] | "\(.key):\(.value)"' "$VERSION_FILE_PATH" > "$TEMP_DIR/components.txt"
        else
            log_error "version.json 中缺少 artifact_list 字段"
            exit 1
        fi
        
        # 解析 checksums
        if jq -e '.checksums' "$VERSION_FILE_PATH" > /dev/null 2>&1; then
            jq -r '.checksums | to_entries[] | "\(.key):\(.value)"' "$VERSION_FILE_PATH" > "$TEMP_DIR/checksums.txt"
        else
            log_error "version.json 中缺少 checksums 字段"
            exit 1
        fi
        
        # 解析 install_order（现在包含完整的文件名）
        if jq -e '.install_order' "$VERSION_FILE_PATH" > /dev/null 2>&1; then
            jq -r '.install_order[]' "$VERSION_FILE_PATH" > "$TEMP_DIR/install_order.txt"
        else
            log_error "version.json 中缺少 install_order 字段"
            exit 1
        fi
        
    else
        log_warning "jq 未安装，使用简单的 JSON 解析"
        # 简单的 JSON 解析
        VERSION=$(grep '"version"' "$VERSION_FILE_PATH" | sed 's/.*"version": *"\([^"]*\)".*/\1/')
        BUILD_TIME=$(grep '"build_time"' "$VERSION_FILE_PATH" | sed 's/.*"build_time": *"\([^"]*\)".*/\1/')
        
        # 解析 artifact_list
        grep -A 100 '"artifact_list"' "$VERSION_FILE_PATH" | grep -E '^\s*"[^"]+":\s*"[^"]+"' | while read line; do
            component=$(echo "$line" | sed 's/.*"\([^"]*\)":\s*"[^"]*".*/\1/')
            version=$(echo "$line" | sed 's/.*"[^"]*":\s*"\([^"]*\)".*/\1/')
            echo "$component:$version" >> "$TEMP_DIR/components.txt"
        done
        
        # 解析 checksums
        grep -A 100 '"checksums"' "$VERSION_FILE_PATH" | grep -E '^\s*"[^"]+":\s*"[^"]+"' | while read line; do
            component=$(echo "$line" | sed 's/.*"\([^"]*\)":\s*"[^"]*".*/\1/')
            checksum=$(echo "$line" | sed 's/.*"[^"]*":\s*"\([^"]*\)".*/\1/')
            echo "$component:$checksum" >> "$TEMP_DIR/checksums.txt"
        done
        
        # 解析 install_order
        grep -A 100 '"install_order"' "$VERSION_FILE_PATH" | grep -E '^\s*"[^"]+"' | while read line; do
            component=$(echo "$line" | sed 's/.*"\([^"]*\)".*/\1/')
            echo "$component" >> "$TEMP_DIR/install_order.txt"
        done
        
        # 验证解析结果
        if [[ ! -f "$TEMP_DIR/components.txt" || ! -s "$TEMP_DIR/components.txt" ]]; then
            log_error "无法解析 artifact_list，请检查 version.json 格式"
            exit 1
        fi
        
        if [[ ! -f "$TEMP_DIR/checksums.txt" || ! -s "$TEMP_DIR/checksums.txt" ]]; then
            log_error "无法解析 checksums，请检查 version.json 格式"
            exit 1
        fi
        
        if [[ ! -f "$TEMP_DIR/install_order.txt" || ! -s "$TEMP_DIR/install_order.txt" ]]; then
            log_error "无法解析 install_order，请检查 version.json 格式"
            exit 1
        fi
    fi
    
    log_success "版本信息解析完成"
    log_info "  版本: $VERSION"
    log_info "  构建时间: $BUILD_TIME"
    
    component_count=0
    if [[ -f "$TEMP_DIR/components.txt" ]]; then
        component_count=$(wc -l < "$TEMP_DIR/components.txt")
        log_info "  组件数量: $component_count"
        log_info "  组件列表:"
        while IFS= read -r line; do
            component=$(echo "$line" | cut -d':' -f1)
            version=$(echo "$line" | cut -d':' -f2)
            log_info "    - $component v$version"
        done < "$TEMP_DIR/components.txt"
    else
        log_error "components.txt 文件不存在"
        exit 1
    fi
}

# 验证文件完整性
verify_checksums() {
    log_info "验证文件完整性..."
    
    artifact_dir=$(dirname "$VERSION_FILE_PATH")
    failed_verification=0
    
    if [[ -f "$TEMP_DIR/checksums.txt" ]]; then
        while IFS= read -r line; do
            component=$(echo "$line" | cut -d':' -f1)
            expected_checksum=$(echo "$line" | cut -d':' -f2-)
            
            # 查找匹配的 tar 文件
            actual_file=""
            for file in "$artifact_dir/${component}-"*.tar.gz; do
                if [[ -f "$file" ]]; then
                    actual_file="$file"
                    break
                fi
            done
            
            if [[ -z "$actual_file" ]]; then
                log_error "找不到组件文件: $component"
                failed_verification=1
                continue
            fi
            
            # 计算实际校验和
            actual_checksum="sha256:$(sha256sum "$actual_file" | cut -d' ' -f1)"
            
            if [[ "$actual_checksum" == "$expected_checksum" ]]; then
                log_success "  $component: 校验通过"
            else
                log_error "  $component: 校验失败"
                log_error "    期望: $expected_checksum"
                log_error "    实际: $actual_checksum"
                failed_verification=1
            fi
        done < "$TEMP_DIR/checksums.txt"
    fi
    
    if [[ $failed_verification -eq 1 ]]; then
        log_error "文件完整性验证失败"
        exit 1
    fi
    
    log_success "所有文件校验通过"
}

# 创建安装目录
create_install_dirs() {
    log_info "创建安装目录..."
    
    mkdir -p "$INSTALL_DIR"
    mkdir -p "$TEMP_DIR"
    
    log_success "安装目录创建完成: $INSTALL_DIR"
}

# 安装系统依赖包
install_system_deps() {
    log_info "检查系统依赖包..."
    
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local deps_dir="$script_dir/deps"
    
    # 检查deps目录是否存在
    if [[ ! -d "$deps_dir" ]]; then
        log_info "deps 目录不存在，跳过系统依赖包安装"
        return 0
    fi
    
    # 检查是否有tar.gz文件
    local deps_count=$(find "$deps_dir" -name "*.tar.gz" | wc -l)
    if [[ $deps_count -eq 0 ]]; then
        log_info "deps 目录中没有 tar.gz 文件，跳过系统依赖包安装"
        return 0
    fi
    
    log_info "找到 $deps_count 个系统依赖包，开始安装..."
    
    # 创建临时目录用于解压依赖包
    local deps_temp_dir="$TEMP_DIR/deps"
    mkdir -p "$deps_temp_dir"
    
    # 处理每个tar.gz文件
    find "$deps_dir" -name "*.tar.gz" | while read tar_file; do
        local tar_basename=$(basename "$tar_file")
        local extract_name="${tar_basename%.tar.gz}"
        
        log_info "处理依赖包: $tar_basename"
        
        # 解压到临时目录
        local extract_dir="$deps_temp_dir/$extract_name"
        mkdir -p "$extract_dir"
        
        if tar -xzf "$tar_file" -C "$extract_dir" 2>/dev/null; then
            log_success "  $tar_basename 解压完成"
        else
            log_error "  $tar_basename 解压失败"
            continue
        fi
        
        # 进入解压目录，查找deb包
        cd "$extract_dir"
        local deb_count=$(find . -name "*.deb" | wc -l)
        
        if [[ $deb_count -gt 0 ]]; then
            log_info "  找到 $deb_count 个 deb 包，开始安装..."
            
            # 1. 先尝试安装所有deb包
            log_info "  第1步：批量安装deb包..."
            if dpkg -i *.deb 2>/dev/null; then
                log_success "  所有deb包安装成功"
            else
                log_warning "  部分deb包安装失败，可能存在依赖问题"
                
                # 2. 使用apt-get修复依赖
                log_info "  第2步：修复依赖关系..."
                if apt-get install -f -y; then
                    log_success "  依赖关系修复完成"
                else
                    log_error "  依赖关系修复失败"
                    # 继续处理其他包，不退出
                fi
            fi
        else
            log_info "  $tar_basename 中没有找到deb包，跳过"
        fi
        
        # 返回到依赖临时目录
        cd "$deps_temp_dir"
    done
    
    # 检查并启动 cron 服务
    start_cron_service
    
    log_success "系统依赖包安装完成"
}

# 启动 cron 服务
start_cron_service() {
    log_info "检查并启动 cron 服务..."
    
    # 检查 cron 是否已经在运行
    if pgrep -x "cron" > /dev/null; then
        log_success "cron 服务已在运行"
        return 0
    fi
    
    # 检查 /usr/sbin/cron 是否存在
    if [[ ! -f "/usr/sbin/cron" ]]; then
        log_warning "cron 可执行文件不存在，跳过启动"
        return 1
    fi
    
    # 启动 cron 服务
    log_info "启动 cron 服务..."
    if /usr/sbin/cron start 2>/dev/null || /usr/sbin/cron 2>/dev/null; then
        log_success "cron 服务启动成功"
        
        sleep 2
        
        if pgrep -x "cron" > /dev/null; then
            log_success "cron 服务运行正常"
        else
            log_warning "cron 服务可能未正常启动"
        fi
    else
        log_error "cron 服务启动失败"
        return 1
    fi
}

# 安装组件
install_components() {
    log_info "开始安装组件..."
    
    artifact_dir=$(dirname "$VERSION_FILE_PATH")
    install_count=0
    total_count=0
    
    if [[ -f "$TEMP_DIR/install_order.txt" ]]; then
        total_count=$(wc -l < "$TEMP_DIR/install_order.txt")
    fi
    
    if [[ -f "$TEMP_DIR/install_order.txt" ]]; then
        while IFS= read -r filename; do
            install_count=$((install_count + 1))
            
            # 从文件名中提取组件名（去掉时间戳后缀）
            component=$(echo "$filename" | sed 's/-[0-9]\{8\}-[0-9]\{6\}\.tar\.gz$//')
            
            log_info "[$install_count/$total_count] 安装 $component..."
            log_info "  文件名: $filename"
            
            # 直接使用完整的文件名
            tar_file="$artifact_dir/$filename"
            
            if [[ ! -f "$tar_file" ]]; then
                log_error "找不到组件文件: $filename"
                log_info "  期望路径: $tar_file"
                log_info "  当前目录: $(pwd)"
                log_info "  目录内容:"
                ls -la "$artifact_dir" | while read line; do
                    log_info "    $line"
                done
                exit 1
            fi
            
            log_info "  找到文件: $tar_file"
            
            # 解压到临时目录
            component_temp_dir="$TEMP_DIR/$component"
            mkdir -p "$component_temp_dir"
            
            if tar -xzf "$tar_file" -C "$component_temp_dir" 2>/dev/null; then
                log_success "  $component 解压完成"
            else
                log_error "  $component 解压失败"
                exit 1
            fi
            
            # 查找解压后的目录
            extracted_dir=""
            for dir in "$component_temp_dir"/*; do
                if [[ -d "$dir" ]]; then
                    extracted_dir="$dir"
                    break
                fi
            done
            
            if [[ -z "$extracted_dir" ]]; then
                log_error "  $component 解压后未找到目录"
                exit 1
            fi
            
            # 执行安装脚本
            if [[ -f "$extracted_dir/install.sh" ]]; then
                log_info "  执行 $component 安装脚本..."
                if (cd "$extracted_dir" && ./install.sh); then
                    log_success "  $component 安装完成"
                else
                    log_error "  $component 安装失败"
                    exit 1
                fi
            else
                log_error "  $component 缺少 install.sh 文件"
                exit 1
            fi
            
            # 将解压后的目录移动到安装目录，保留组件目录
            component_install_dir="$INSTALL_DIR/$component"
            if [[ -d "$component_install_dir" ]]; then
                log_info "  组件目录已存在，备份后更新: $component_install_dir"
                mv "$component_install_dir" "${component_install_dir}.backup.$(date +%Y%m%d_%H%M%S)"
            fi
            mv "$extracted_dir" "$component_install_dir"
            log_success "  组件目录已保存: $component_install_dir"
            
            # 清理临时文件
            rm -rf "$component_temp_dir"
        done < "$TEMP_DIR/install_order.txt"
    fi
    
    log_success "所有组件安装完成"
}

# 创建安装记录
create_install_record() {
    log_info "创建安装记录..."
    
    # 等待一段时间确保所有进程都已启动
    log_info "等待进程启动..."
    sleep 3
    
    local install_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local install_record_file=".install_record"
    
    # 创建 JSON 格式的安装记录
    cat > "$install_record_file" << EOF
{
  "version": "$VERSION",
  "build_time": "$BUILD_TIME",
  "install_time": "$install_time",
  "install_dir": "$INSTALL_DIR",
  "install_pid": $$,
  "components": {
EOF

    # 添加组件信息
    local first_component=true
    if [[ -f "$TEMP_DIR/components.txt" ]]; then
        while IFS= read -r line; do
            component=$(echo "$line" | cut -d':' -f1)
            version=$(echo "$line" | cut -d':' -f2)
            
            # 获取组件的进程信息
            local component_pid=""
            
            # 根据组件名查找进程，使用多种方法确保能找到PID
            case "$component" in
                "node-exporter")
                    # 查找node_exporter进程
                    component_pid=$(pgrep -f "node_exporter" | head -1)
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(pgrep -f "node-exporter" | head -1)
                    fi
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(ps aux | grep -v grep | grep "node_exporter" | awk '{print $2}' | head -1)
                    fi
                    ;;
                "dcgm-exporter")
                    # 查找dcgm-exporter进程
                    component_pid=$(pgrep -f "dcgm-exporter" | head -1)
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(pgrep -f "dcgm_exporter" | head -1)
                    fi
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(ps aux | grep -v grep | grep "dcgm-exporter" | awk '{print $2}' | head -1)
                    fi
                    ;;
                "fluent-bit")
                    # 查找fluent-bit进程
                    component_pid=$(pgrep -f "fluent-bit" | head -1)
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(pgrep -f "fluent_bit" | head -1)
                    fi
                    if [[ -z "$component_pid" ]]; then
                        component_pid=$(ps aux | grep -v grep | grep "fluent-bit" | awk '{print $2}' | head -1)
                    fi
                    ;;
            esac
            
            # 记录找到的PID信息
            if [[ -n "$component_pid" ]]; then
                log_info "  找到 $component 进程 PID: $component_pid"
            else
                log_warning "  未找到 $component 进程"
            fi
            
            # 添加逗号分隔符
            if [[ "$first_component" == "true" ]]; then
                first_component=false
            else
                echo "," >> "$install_record_file"
            fi
            
            # 添加组件信息
            cat >> "$install_record_file" << EOF
    "$component": {
      "version": "$version",
      "pid": "$component_pid",
      "install_dir": "$INSTALL_DIR/$component"
    }
EOF
        done < "$TEMP_DIR/components.txt"
    fi
    
    # 结束 JSON
    cat >> "$install_record_file" << EOF
  }
}
EOF

    log_success "安装记录已创建: $install_record_file"
}

# 设置健康检查定时任务
setup_health_check_cron() {
    log_info "设置健康检查定时任务..."
    
    # 直接使用当前安装目录，不依赖current软链接
    # INSTALL_DIR 是 /opt/argus-metric/versions/1.34.0
    local check_health_script="$INSTALL_DIR/check_health.sh"
    
    # 检查健康检查脚本是否存在
    if [[ ! -f "$check_health_script" ]]; then
        log_error "健康检查脚本不存在: $check_health_script"
        return 1
    fi
    
    # 确保脚本有执行权限
    chmod +x "$check_health_script"
    
    # 创建临时crontab文件
    local temp_cron="/tmp/crontab_$$"
    
    # 获取当前用户的crontab（如果存在）
    crontab -l 2>/dev/null > "$temp_cron" || touch "$temp_cron"
    
    # 检查并删除旧的健康检查任务
    if grep -q "check_health.sh" "$temp_cron"; then
        log_info "发现旧的健康检查定时任务，正在更新..."
        # 删除所有包含check_health.sh的行
        grep -v "check_health.sh" "$temp_cron" > "$temp_cron.new"
        mv "$temp_cron.new" "$temp_cron"
        log_info "旧的健康检查定时任务已删除"
    fi
    
    # 添加新的定时任务（每5分钟执行一次）
    echo "# Argus-Metrics 健康检查定时任务" >> "$temp_cron"
    echo "*/5 * * * * $check_health_script >> $INSTALL_DIR/.health_cron.log 2>&1" >> "$temp_cron"
    
    # 安装新的crontab
    if crontab "$temp_cron"; then
        log_success "健康检查定时任务设置成功"
        log_info "  执行频率: 每5分钟"
        log_info "  日志文件: $INSTALL_DIR/.health_cron.log"
        log_info "  查看定时任务: crontab -l"
        log_info "  删除定时任务: crontab -e"
    else
        log_error "健康检查定时任务设置失败"
        rm -f "$temp_cron"
        return 1
    fi
    
    # 清理临时文件
    rm -f "$temp_cron"
    
    log_info "健康检查通过crontab自动执行"
}

# 显示安装信息
show_install_info() {
    log_success "Argus-Metrics All-in-One 安装完成！"
}

cleanup() {
    if [[ -d "$TEMP_DIR" ]]; then
        rm -rf "$TEMP_DIR"
    fi
}

trap cleanup EXIT

# 主函数
main() {
    echo "=========================================="
    echo "    Argus-Metrics All-in-One 安装脚本 v1.0"
    echo "=========================================="
    echo
    
    # 加载配置文件
    load_config
    
    log_info "安装目录: $INSTALL_DIR"
    echo
    
    check_root
    check_system
    find_version_file
    create_install_dirs
    parse_version_info
    verify_checksums
    install_system_deps
    install_components
    copy_config_files
    create_install_record
    setup_health_check_cron
    show_install_info
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi
