#!/bin/bash

# 配置部分 - 在这里设置目标月数
TARGET_MONTHS=120  # 例如36个月=3年

# 计算小时数(1个月按30天计算,1天=24小时)
HOURS_PER_MONTH=$((30 * 24))  # 720小时/月
TARGET_DURATION=$((TARGET_MONTHS * HOURS_PER_MONTH))"h"

# 创建日志文件
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="certificate_update_${TIMESTAMP}.log"
echo "===== 证书更新操作日志 - $(date) =====" > "$LOG_FILE"
echo "目标有效期: $TARGET_MONTHS 个月 ($TARGET_DURATION)" >> "$LOG_FILE"
echo "====================================" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"

# 函数:等待secret创建
wait_for_secret() {
    local ns=$1
    local secret=$2
    local timeout=30
    local interval=2
    local count=0
    
    echo "  等待secret $ns/$secret 生成..."
    while ! kubectl get secret "$secret" -n "$ns" >/dev/null 2>&1; do
        sleep $interval
        count=$((count + interval))
        if [ $count -ge $timeout ]; then
            echo "  ⚠️ 超时:secret $ns/$secret 未在 $timeout 秒内生成"
            echo "超时:secret $ns/$secret 未生成" >> "$LOG_FILE"
            return 1
        fi
    done
    echo "  ✅ secret $ns/$secret 已生成"
    return 0
}

# 函数:检查证书过期时间
check_cert_expiry() {
    local ns=$1
    local secret=$2
    
    # 提取并解码证书
    cert_data=$(kubectl get secret "$secret" -n "$ns" -o jsonpath='{.data.tls\.crt}')
    if [ -z "$cert_data" ]; then
        echo "  ❌ 无法从 $ns/$secret 获取证书数据"
        echo "错误:无法从 $ns/$secret 获取证书数据" >> "$LOG_FILE"
        return 1
    fi
    
    # 解码并检查有效期
    expiry_date=$(echo "$cert_data" | base64 -d | openssl x509 -noout -enddate | cut -d= -f2)
    if [ -z "$expiry_date" ]; then
        echo "  ❌ 无法解析 $ns/$secret 的证书过期时间"
        echo "错误:无法解析 $ns/$secret 的证书过期时间" >> "$LOG_FILE"
        return 1
    fi
    
    # 转换为时间戳以便计算
    expiry_timestamp=$(date -d "$expiry_date" +%s)
    current_timestamp=$(date +%s)
    days_remaining=$(( (expiry_timestamp - current_timestamp) / 86400 ))
    
    echo "  ******** 证书 $ns/$secret 过期时间: $expiry_date (约 $days_remaining 天)"
    echo "$ns/$secret 过期时间: $expiry_date (约 $days_remaining 天)" >> "$LOG_FILE"
    return 0
}

# 获取所有命名空间
namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')

# 记录总数统计
total_certs=0
updated_certs=0
failed_certs=0

echo "===== 开始证书更新流程 ====="
echo "目标有效期: $TARGET_MONTHS 个月 ($TARGET_DURATION)"
echo "日志将保存至: $LOG_FILE"
echo ""

# 遍历所有命名空间
for ns in $namespaces; do
    echo "处理命名空间: $ns"
    echo "处理命名空间: $ns" >> "$LOG_FILE"
    
    # 获取当前命名空间中的所有Certificate资源
    certs=$(kubectl get certificates -n "$ns" -o jsonpath='{.items[*].metadata.name}')
    
    if [ -z "$certs" ]; then
        echo "  未发现Certificate资源,跳过"
        echo "  未发现Certificate资源,跳过" >> "$LOG_FILE"
        echo ""
        continue
    fi
    
    # 遍历每个Certificate资源
    for cert in $certs; do
        total_certs=$((total_certs + 1))
        echo "  处理Certificate: $cert"
        echo "  处理Certificate: $cert" >> "$LOG_FILE"
        
        # 获取当前duration
        current_duration=$(kubectl get certificate "$cert" -n "$ns" -o jsonpath='{.spec.duration}')
        
        # 获取关联的secret名称
        secret_name=$(kubectl get certificate "$cert" -n "$ns" -o jsonpath='{.spec.secretName}')
        if [ -z "$secret_name" ]; then
            echo "  ❌ 无法获取 $ns/$cert 关联的secret名称"
            echo "  错误:无法获取关联的secret名称" >> "$LOG_FILE"
            failed_certs=$((failed_certs + 1))
            continue
        fi
        
        # 如果当前duration与目标不同,则进行更新
        if [ "$current_duration" != "$TARGET_DURATION" ]; then
            # 使用kubectl patch更新duration
            if kubectl patch certificate "$cert" -n "$ns" --type=merge -p "{\"spec\":{\"duration\":\"$TARGET_DURATION\"}}"; then
                echo "  ✅ 已更新 $ns/$cert: $current_duration -> $TARGET_DURATION"
                echo "  已更新: $current_duration -> $TARGET_DURATION" >> "$LOG_FILE"
                
                # 删除secret触发更新
                echo "  删除secret $secret_name 以触发证书更新..."
                if kubectl delete secret "$secret_name" -n "$ns" >/dev/null 2>&1; then
                    echo "  已删除secret $secret_name"
                    echo "  已删除secret: $secret_name" >> "$LOG_FILE"
                    
                    # 等待新secret生成
                    if wait_for_secret "$ns" "$secret_name"; then
                        # 检查新证书的过期时间
                        check_cert_expiry "$ns" "$secret_name"
                    fi
                    updated_certs=$((updated_certs + 1))
                else
                    echo "  ❌ 无法删除secret $secret_name"
                    echo "  错误:无法删除secret $secret_name" >> "$LOG_FILE"
                    failed_certs=$((failed_certs + 1))
                fi
            else
                echo "  ❌ 更新 $ns/$cert 失败"
                echo "  错误:更新Certificate失败" >> "$LOG_FILE"
                failed_certs=$((failed_certs + 1))
            fi
        else
            echo "  ⏭️ $ns/$cert 已为目标有效期,无需更新"
            echo "  无需更新:已为目标有效期" >> "$LOG_FILE"
            # 检查当前证书的过期时间
            check_cert_expiry "$ns" "$secret_name"
        fi
        echo ""
        echo "" >> "$LOG_FILE"
    done
done

# 输出总结信息
echo "===== 操作完成 ====="
echo "总处理Certificate资源: $total_certs"
echo "成功更新: $updated_certs"
echo "更新失败: $failed_certs"
echo "Certificate资源如下"
kubectl get certificates --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{" "}{.spec.duration}{"\n"}{end}'
echo "详细日志: $LOG_FILE"

echo ""
echo "更新总结:" >> "$LOG_FILE"
echo "总处理Certificate资源: $total_certs" >> "$LOG_FILE"
echo "成功更新: $updated_certs" >> "$LOG_FILE"
echo "更新失败: $failed_certs" >> "$LOG_FILE"
echo "操作完成时间: $(date)" >> "$LOG_FILE"