#!/bin/bash
#==============================================================================
# 系统清理脚本 - 带合理性判断的安全清理
# 遵循"先检查、后判断、再执行"原则
# 遵循阿里开发手册规范
#==============================================================================

set -euo pipefail

# 从环境变量获取敏感配置
if [ -z "${JENKINS_TOKEN:-}" ]; then
    echo "警告: JENKINS_TOKEN 环境变量未设置，将跳过Jenkins构建历史清理"
    readonly SKIP_JENKINS_CLEAN=true
else
    readonly SKIP_JENKINS_CLEAN=false
    readonly JENKINS_TOKEN="${JENKINS_TOKEN}"
fi

# 配置参数
readonly LOG_FILE="/var/log/system_cleanup.log"
readonly MAX_LOG_SIZE=10485760
readonly DISK_THRESHOLD=70
readonly JENKINS_HOME="/var/lib/jenkins"
readonly JENKINS_PODMAN_CACHE="${JENKINS_HOME}/.local/share/containers/storage"

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

#==============================================================================
# 日志管理
#==============================================================================
log() {
    local level="$1"
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo -e "[${timestamp}] [${level}] ${message}" | tee -a "${LOG_FILE}"
}

log_info() { log "${GREEN}INFO${NC}" "$1"; }
log_warn() { log "${YELLOW}WARN${NC}" "$1"; }
log_error() { log "${RED}ERROR${NC}" "$1"; }

rotate_log() {
    [[ -f "${LOG_FILE}" && $(stat -c %s "${LOG_FILE}" 2>/dev/null || echo 0) -gt ${MAX_LOG_SIZE} ]] && {
        mv "${LOG_FILE}" "${LOG_FILE}.$(date +%Y%m%d%H%M%S)"
        log_info "日志文件已轮转"
    }
}

#==============================================================================
# 环境检查
#==============================================================================
check_environment() {
    log_info "=== 开始环境检查 ==="
    
    # 检查是否为root用户
    if [[ $(id -u) -ne 0 ]]; then
        log_error "必须以root用户执行此脚本"
        exit 1
    fi
    log_info "✓ 运行用户检查通过"
    
    # 检查必要命令
    for cmd in df du podman su curl; do
        if ! command -v $cmd &>/dev/null; then
            log_error "缺少必要命令: $cmd"
            exit 1
        fi
    done
    log_info "✓ 必要命令检查通过"
    
    log_info "=== 环境检查完成 ==="
}

#==============================================================================
# 磁盘使用检查
#==============================================================================
check_disk_usage() {
    local usage=$(df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//')
    echo "$usage"
}

check_disk_threshold() {
    local usage=$(check_disk_usage)
    if [[ $usage -lt ${DISK_THRESHOLD} ]]; then
        log_info "磁盘使用率: ${usage}% (低于阈值 ${DISK_THRESHOLD}%)，无需清理"
        return 1
    fi
    log_warn "磁盘使用率: ${usage}% (超过阈值 ${DISK_THRESHOLD}%)，建议清理"
    return 0
}

#==============================================================================
# 合理性判断函数 - Jenkins Podman缓存清理
#==============================================================================
check_jenkins_podman_resources() {
    log_info "=== Jenkins用户Podman资源检查 ==="
    
    local can_clean=true
    local issues=""
    
    # 检查1: Jenkins用户是否有运行中的容器
    local running_containers=$(su - jenkins -c 'podman ps -q 2>/dev/null || true')
    if [[ -n "$running_containers" ]]; then
        issues+="\n  ❌ Jenkins用户有运行中的容器: $running_containers"
        issues+="\n     → 跳过清理以避免影响构建任务"
        can_clean=false
    else
        log_info "  ✓ Jenkins用户没有运行中的容器"
    fi
    
    # 检查2: Jenkins用户是否有正在使用的镜像
    local running_images=$(su - jenkins -c 'podman ps --format "{{.Image}}" 2>/dev/null || true')
    if [[ -n "$running_images" ]]; then
        issues+="\n  ❌ Jenkins用户有正在使用的镜像: $running_images"
        issues+="\n     → 跳过清理以避免构建失败"
        can_clean=false
    else
        log_info "  ✓ Jenkins用户没有正在使用的镜像"
    fi
    
    # 检查3: overlay目录是否存在且有内容
    if [[ ! -d "${JENKINS_PODMAN_CACHE}/overlay" ]]; then
        issues+="\n  ℹ️  overlay目录不存在，无需清理"
        can_clean=false
    else
        local overlay_size=$(du -sh "${JENKINS_PODMAN_CACHE}/overlay" 2>/dev/null | awk '{print $1}')
        local overlay_count=$(find "${JENKINS_PODMAN_CACHE}/overlay" -maxdepth 1 -type d 2>/dev/null | wc -l)
        log_info "  ✓ overlay目录存在 (大小: $overlay_size, 子目录: $overlay_count)"
        
        if [[ $overlay_count -le 1 ]]; then
            issues+="\n  ℹ️  overlay目录为空，无需清理"
            can_clean=false
        fi
    fi
    
    # 输出检查结果
    if [[ -n "$issues" ]]; then
        echo -e "$issues"
    fi
    
    # 检查4: 缓存大小是否超过1GB（合理性判断）
    local cache_size=$(du -sm "${JENKINS_PODMAN_CACHE}" 2>/dev/null | awk '{print $1}')
    if [[ ${cache_size:-0} -lt 1024 ]]; then
        log_info "  ℹ️  缓存大小仅 ${cache_size}MB，小于1GB，跳过清理"
        can_clean=false
    else
        log_info "  ✓ 缓存大小 ${cache_size}MB，超过1GB阈值"
    fi
    
    if [[ "$can_clean" == "true" ]]; then
        log_info "=== 合理性判断通过：可以安全清理Jenkins Podman缓存 ==="
        return 0
    else
        log_info "=== 合理性判断未通过：跳过Jenkins Podman缓存清理 ==="
        return 1
    fi
}

#==============================================================================
# 清理Jenkins Podman缓存
#==============================================================================
clean_jenkins_podman_cache() {
    if ! check_jenkins_podman_resources; then
        return 1
    fi
    
    log_info "=== 开始清理Jenkins Podman缓存 ==="
    
    local before_size=$(du -sh "${JENKINS_PODMAN_CACHE}" 2>/dev/null | awk '{print $1}')
    
    # 记录将要删除的文件（合理性确认）
    log_info "准备清理以下目录:"
    log_info "  - ${JENKINS_PODMAN_CACHE}/overlay/*"
    log_info "  - ${JENKINS_PODMAN_CACHE}/overlay-images/*"
    log_info "  - ${JENKINS_PODMAN_CACHE}/overlay-layers/*"
    
    # 执行清理
    rm -rf "${JENKINS_PODMAN_CACHE}/overlay"/* 2>/dev/null || true
    rm -rf "${JENKINS_PODMAN_CACHE}/overlay-images"/* 2>/dev/null || true
    rm -rf "${JENKINS_PODMAN_CACHE}/overlay-layers"/* 2>/dev/null || true
    
    local after_size=$(du -sh "${JENKINS_PODMAN_CACHE}" 2>/dev/null | awk '{print $1}')
    
    log_info "清理完成: ${before_size} -> ${after_size}"
    log_info "✓ Jenkins Podman缓存清理成功"
}

#==============================================================================
# 合理性判断函数 - 系统Podman资源清理
#==============================================================================
check_system_podman_resources() {
    log_info "=== 系统Podman资源检查 ==="
    
    local can_clean=true
    
    # 检查1: 获取运行中的容器
    local running_containers=$(podman ps -q 2>/dev/null || true)
    if [[ -z "$running_containers" ]]; then
        log_info "  ℹ️  没有运行中的容器，跳过系统Podman清理"
        return 1
    fi
    log_info "  ✓ 检测到 $(echo "$running_containers" | wc -w) 个运行中的容器"
    
    # 检查2: 获取运行中的容器使用的镜像
    local used_images=$(podman inspect $(echo "$running_containers") --format '{{.Config.Image}}' 2>/dev/null | sort -u || true)
    log_info "  ✓ 运行中的容器使用以下镜像:"
    echo "$used_images" | while read -r img; do
        [[ -n "$img" ]] && log_info "     - $img"
    done
    
    # 检查3: 分析未使用的镜像
    local all_images=$(podman images --format '{{.ID}} {{.Repository}}:{{.Tag}}' 2>/dev/null || true)
    local unused_count=0
    local unused_images=""
    
    while IFS= read -r line; do
        [[ -z "$line" ]] && continue
        local img_id=$(echo "$line" | awk '{print $1}')
        local img_tag=$(echo "$line" | awk '{print $2}')
        
        # 检查镜像是否被任何运行中的容器使用
        if ! echo "$used_images" | grep -q "$img_tag" && ! echo "$used_images" | grep -q "$img_id"; then
            unused_count=$((unused_count + 1))
            unused_images+="  - $img_tag (ID: $img_id)\n"
        fi
    done <<< "$all_images"
    
    if [[ $unused_count -eq 0 ]]; then
        log_info "  ✓ 所有镜像都正在使用，无需清理"
        return 1
    fi
    
    log_info "  ✓ 发现 ${unused_count} 个未使用的镜像:"
    echo -e "$unused_images" | head -10
    
    # 合理性判断：只清理dangling镜像（tag为<none>的）
    local dangling_images=$(podman images -f dangling=true --format '{{.ID}}' 2>/dev/null || true)
    if [[ -z "$dangling_images" ]]; then
        log_info "  ℹ️  没有dangling镜像（tag为<none>）需要清理"
        log_info "  ✓ 为确保系统稳定性，仅清理dangling镜像"
        return 1
    fi
    
    log_info "  ✓ 发现 $(echo "$dangling_images" | wc -w) 个dangling镜像可以清理"
    return 0
}

#==============================================================================
# 清理系统Podman资源
#==============================================================================
clean_system_podman_resources() {
    if ! check_system_podman_resources; then
        return 1
    fi
    
    log_info "=== 开始清理系统Podman资源 ==="
    
    # 只清理dangling镜像（合理性限制）
    local dangling_images=$(podman images -f dangling=true --format '{{.ID}}' 2>/dev/null || true)
    if [[ -n "$dangling_images" ]]; then
        log_info "清理dangling镜像: $dangling_images"
        podman rmi $(echo "$dangling_images") 2>/dev/null || true
        log_info "✓ Dangling镜像清理完成"
    fi
    
    # 清理已停止的容器（保留最近1小时内停止的）
    local stopped_containers=$(podman ps -a -f status=exited --format '{{.ID}}' 2>/dev/null || true)
    if [[ -n "$stopped_containers" ]]; then
        log_info "清理已停止的容器: $(echo "$stopped_containers" | wc -w) 个"
        podman container prune -f 2>/dev/null || true
        log_info "✓ 已停止容器清理完成"
    else
        log_info "  ℹ️  没有已停止的容器需要清理"
    fi
    
    # 清理未使用的网络（不清理默认网络）
    local unused_networks=$(podman network ls --format '{{.Name}}' | grep -v -E '^(bridge|host|none|podman)$' 2>/dev/null || true)
    if [[ -n "$unused_networks" ]]; then
        log_info "清理未使用的网络: $unused_networks"
        podman network prune -f 2>/dev/null || true
        log_info "✓ 未使用网络清理完成"
    else
        log_info "  ℹ️  没有未使用的网络需要清理"
    fi
    
    log_info "✓ 系统Podman资源清理完成"
}

#==============================================================================
# 合理性判断 - Jenkins构建历史清理
#==============================================================================
check_jenkins_build_history() {
    log_info "=== Jenkins构建历史检查 ==="
    
    # 检查构建目录大小
    local build_size=$(du -sh "${JENKINS_HOME}/jobs" 2>/dev/null | awk '{print $1}')
    log_info "  ✓ Jenkins构建目录大小: $build_size"
    
    # 检查构建数量
    local build_count=0
    for job_dir in "${JENKINS_HOME}"/jobs/*/builds; do
        [[ -d "$job_dir" ]] && build_count+=$(ls -1 "$job_dir" 2>/dev/null | grep -E '^[0-9]+$' | wc -l)
    done
    log_info "  ✓ 总构建数量: $build_count"
    
    # 合理性判断：只建议清理超过阈值的构建
    if [[ $build_count -gt 20 ]]; then
        log_info "  ✓ 构建数量超过20，建议清理旧构建"
        return 0
    fi
    
    log_info "  ℹ️  构建数量在合理范围内，无需清理"
    return 1
}

#==============================================================================
# 清理旧构建（通过Jenkins API）
#==============================================================================
clean_old_builds() {
    if [[ "${SKIP_JENKINS_CLEAN}" == "true" ]]; then
        log_info "  ℹ️  JENKINS_TOKEN未设置，跳过Jenkins构建历史清理"
        return 1
    fi
    
    if ! check_jenkins_build_history; then
        return 1
    fi
    
    log_info "=== 开始清理Jenkins旧构建 ==="
    
    local jenkins_url="http://localhost:8080"
    local jenkins_user="admin"
    # 从环境变量获取Jenkins Token
    local jenkins_token="${JENKINS_TOKEN}"
    
    # 获取CSRF crumb
    local crumb=$(curl -s -u "${jenkins_user}:${jenkins_token}" \
        "${jenkins_url}/crumbIssuer/api/python" 2>/dev/null | \
        grep -o '"crumb":"[^"]*"' | cut -d'"' -f4)
    
    if [[ -z "$crumb" ]]; then
        log_warn "无法获取Jenkins crumb，跳过构建历史清理"
        return 1
    fi
    
    # 清理fzx-platform-build（保留最近10个）
    log_info "清理fzx-platform-build构建（保留最近10个）..."
    curl -s -u "${jenkins_user}:${jenkins_token}" \
        -H "Jenkins-Crumb:${crumb}" \
        "${jenkins_url}/job/fzx-platform-build/doDeleteOldBuilds?maxBuilds=10" || true
    
    # 清理fzx-platform-deploy（保留最近5个）
    log_info "清理fzx-platform-deploy构建（保留最近5个）..."
    curl -s -u "${jenkins_user}:${jenkins_token}" \
        -H "Jenkins-Crumb:${crumb}" \
        "${jenkins_url}/job/fzx-platform-deploy/doDeleteOldBuilds?maxBuilds=5" || true
    
    log_info "✓ Jenkins构建历史清理完成"
}

#==============================================================================
# 主函数
#==============================================================================
main() {
    rotate_log
    log_info "========================================"
    log_info "系统清理脚本开始执行"
    log_info "========================================"
    
    # 环境检查
    check_environment
    
    # 检查磁盘使用率
    if ! check_disk_threshold; then
        log_info "磁盘使用率在安全范围内，脚本退出"
        exit 0
    fi
    
    # 执行清理（按优先级）
    clean_jenkins_podman_cache
    clean_system_podman_resources
    clean_old_builds
    
    # 检查清理效果
    local after_usage=$(check_disk_usage)
    log_info "========================================"
    log_info "清理完成 - 磁盘使用率: ${after_usage}%"
    
    if [[ ${after_usage} -gt 80 ]]; then
        log_warn "磁盘使用率仍然超过80%，建议人工检查"
    fi
    
    log_info "========================================"
}

# 执行主函数
main "$@"
