#!/bin/bash
##!name: 腾讯云多账号多域名证书统一下发 (正式生产版)
##!desc: 自动续签，自带4次失败重试机制，更新时下发宝塔并联动EdgeOne
##!cron: 30 3 * * *

# ================= 终极进程管控与断流 =================
set -euo pipefail

cleanup() {
    rm -f "/tmp/mail_$$.txt"
    rm -rf /tmp/ssl_output_* # 清理所有临时证书目录
    exec 1>&-
    exec 2>&-
    trap '' TERM
    kill -TERM -$$ 2>/dev/null || true
    sleep 1
    kill -9 -$$ 2>/dev/null || true
}
trap cleanup EXIT

# ================= 基础配置区域 =================
SSH_KEY_PATH="/ql/data/id_rsa_acme"
RECEIVER_EMAIL="admin@yourdomain.com" # 👈 【脱敏说明】换成了占位符邮箱
SSL_DIR="/etc/ssl/auto_renew" # 统一的缓冲目录
MAIL_TMP="/tmp/mail_$$.txt"

# 邮件全局汇总内容
EMAIL_REPORT="【执行明细】\n\n"
HAS_ERROR=0

# ================= 账号与服务器配置矩阵 =================
# 格式：域名 | 腾讯云SecretId | 腾讯云SecretKey | 目标服务器IP | 目标服务器用户名
DOMAINS_CONFIG=(
    # 账号 1 的域名 👈 【脱敏说明】IP和域名已全部打码
    "domain-a.com|${TC_ID_1:-}|${TC_KEY_1:-}|111.111.111.111|root"
    "domain-b.com|${TC_ID_1:-}|${TC_KEY_1:-}|111.111.111.111|root"
    # 账号 2 的域名
    "domain-c.org|${TC_ID_2:-}|${TC_KEY_2:-}|222.222.222.222|root"
    "domain-d.org|${TC_ID_2:-}|${TC_KEY_2:-}|222.222.222.222|root"
)
# ========================================================

# 定义发送邮件函数
send_email() {
    local status="$1"
    local content=$(echo -e "$2")
    local subject="【青龙】腾讯云多域名证书通知 - ${status}"
    
    echo "📧 正在发送汇总邮件..."
    if [ -z "${SMTP_SERVER:-}" ] || [ -z "${SMTP_EMAIL:-}" ]; then
        echo "❌ 邮件配置缺失，跳过发送。"
        return 1
    fi

    cat > "$MAIL_TMP" <<EOF
From: "证书监控中心" <$SMTP_EMAIL>
To: <$RECEIVER_EMAIL>
Subject: $subject
Content-Type: text/plain; charset=UTF-8

执行时间：$(date "+%Y-%m-%d %H:%M:%S")
当前状态：$status

$content

-------------------------
此邮件由青龙面板自动发送
EOF

    timeout -k 5s 30s curl --silent --show-error --ssl-reqd \
        --url "smtps://$SMTP_SERVER:465" \
        --user "$SMTP_EMAIL:$SMTP_PASSWORD" \
        --mail-from "$SMTP_EMAIL" \
        --mail-rcpt "$RECEIVER_EMAIL" \
        --upload-file "$MAIL_TMP" || true
}

# ================= 环境检查与安装 =================
if [ ! -f "$SSH_KEY_PATH" ]; then
    send_email "环境错误" "❌ 未找到持久化 SSH 密钥：$SSH_KEY_PATH" || true
    exit 1
fi

export ACME_DIR="/ql/data/acme"
if [ ! -f "$ACME_DIR/acme.sh" ]; then
    echo "⬇️ 安装 acme.sh..."
    rm -rf /tmp/acme.sh
    timeout -k 10s 120s git clone https://gitee.com/neilpang/acme.sh.git /tmp/acme.sh >/dev/null 2>&1
    cd /tmp/acme.sh && ./acme.sh --install --home "$ACME_DIR" --nocron -m "${SMTP_EMAIL:-default@example.com}" >/dev/null 2>&1
    cd ~
fi
export PATH="$ACME_DIR:$PATH"
timeout -k 5s 30s acme.sh --register-account --home "$ACME_DIR" -m "${SMTP_EMAIL:-default@example.com}" --server zerossl >/dev/null 2>&1 || true

# ================= 核心业务逻辑：遍历处理 =================

for config in "${DOMAINS_CONFIG[@]}"; do
    # 解析配置
    IFS='|' read -r DOMAIN TC_ID TC_KEY HOST_IP HOST_USER <<< "$config"
    
    echo "=================================================="
    echo "🚀 正在处理域名: $DOMAIN"
    echo "=================================================="
    
    export Tencent_SecretId="$TC_ID"
    export Tencent_SecretKey="$TC_KEY"
    
    # 屏蔽 ssh/scp 的警告信息，让日志更干净
    SSH_OPTS="-i $SSH_KEY_PATH -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o LogLevel=ERROR"
    
    # ================= 核心：4次重试机制 =================
    MAX_RETRIES=4
    ATTEMPT=1
    ISSUE_SUCCESS=false
    IS_SKIPPED=false
    CLEAN_LOG=""

    while [ $ATTEMPT -le $MAX_RETRIES ]; do
        if [ $ATTEMPT -gt 1 ]; then
            echo "⏳ 正在发起第 $ATTEMPT/$MAX_RETRIES 次重新申请..."
        fi

        ISSUE_EXIT_CODE=0
        ISSUE_LOG=$(timeout -k 10s 600s bash "$ACME_DIR/acme.sh" --issue --home "$ACME_DIR" --dns dns_tencent --dnssleep 120 -d "$DOMAIN" -d "*.$DOMAIN" 2>&1) || ISSUE_EXIT_CODE=$?
        CLEAN_LOG=$(echo "$ISSUE_LOG" | grep -v "integer expected" | grep -v "out of range" || true)

        if [[ "$ISSUE_LOG" == *"Skipping"* ]] || [[ "$ISSUE_LOG" == *"Domains not changed"* ]]; then
            IS_SKIPPED=true
            ISSUE_SUCCESS=true
            break
        elif [ $ISSUE_EXIT_CODE -eq 0 ]; then
            ISSUE_SUCCESS=true
            break
        else
            echo "⚠️ 第 $ATTEMPT 次申请失败，遭遇报错！"
            ATTEMPT=$((ATTEMPT + 1))
            if [ $ATTEMPT -le $MAX_RETRIES ]; then
                echo "💤 触发保护机制，等待 60 秒后进行下一次尝试..."
                sleep 60
            fi
        fi
    done

    # ================= 结果判断与拦截 =================
    if [ "$ISSUE_SUCCESS" = false ]; then
        echo "❌ [$DOMAIN] 连续 $MAX_RETRIES 次申请均失败，放弃当前域名。"
        EMAIL_REPORT="${EMAIL_REPORT}❌ [${DOMAIN}]: 连续 $MAX_RETRIES 次申请失败，最终错误日志片段：\n$(echo "$CLEAN_LOG" | tail -n 5)\n"
        HAS_ERROR=1
        continue
    fi

    if [ "$IS_SKIPPED" = true ]; then
        echo "✅ [$DOMAIN] 证书仍在有效期内，无需更新 (Skipped)，不触发下发。"
        EMAIL_REPORT="${EMAIL_REPORT}✅ [${DOMAIN}]: 证书仍在有效期内，已跳过分发与重载。\n"
        continue
    fi
    # ========================================================

    # 4. 提取与推送 (SCP)
    echo "✅ [$DOMAIN] 申请成功！准备提取推送..."
    LOCAL_SSL_DIR="/tmp/ssl_output_$DOMAIN"
    mkdir -p "$LOCAL_SSL_DIR"

    # acme.sh 提取新证书
    acme.sh --install-cert --home "$ACME_DIR" -d "$DOMAIN" \
        --key-file       "$LOCAL_SSL_DIR/$DOMAIN.key.pem"  \
        --fullchain-file "$LOCAL_SSL_DIR/$DOMAIN.pem" >/dev/null 2>&1

    DEPLOY_EXIT_CODE=0
    
    # 直接在远端创建缓冲目录，防止目录不存在报错
    ssh $SSH_OPTS "$HOST_USER@$HOST_IP" "mkdir -p $SSL_DIR" 2>&1 || true

    echo "📤 正在上传文件至 $HOST_IP 缓冲目录 $SSL_DIR ..."
    scp $SSH_OPTS "$LOCAL_SSL_DIR/$DOMAIN.key.pem" "$HOST_USER@$HOST_IP:$SSL_DIR/$DOMAIN.key.pem" 2>&1 || DEPLOY_EXIT_CODE=$?
    scp $SSH_OPTS "$LOCAL_SSL_DIR/$DOMAIN.pem" "$HOST_USER@$HOST_IP:$SSL_DIR/$DOMAIN.pem" 2>&1 || DEPLOY_EXIT_CODE=$?

    # 5. 推送结果、覆盖及重载
    if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
        echo "🔄 [$DOMAIN] 推送至缓冲目录成功！"
        
        # ================= 多站点覆盖逻辑 =================
        OVERWRITE_SITES=""
        
        # 👈 【脱敏说明】所有的子域名均已脱敏处理
        if [ "$DOMAIN" == "domain-d.org" ]; then
            OVERWRITE_SITES="domain-d.org"
        elif [ "$DOMAIN" == "domain-c.org" ]; then
            OVERWRITE_SITES="domain-c.org,test.domain-c.org"
        elif [ "$DOMAIN" == "domain-a.com" ]; then
            OVERWRITE_SITES="lab.domain-a.com,domain-a.com.11,tool.domain-a.com,api1.domain-a.com,api2.domain-a.com,api3.domain-a.com,domain-a.com,www.domain-a.com"
        elif [ "$DOMAIN" == "domain-b.com" ]; then
            OVERWRITE_SITES="sub1.domain-b.com,sub2.domain-b.com,sub3.domain-b.com"
        fi

        if [ -n "$OVERWRITE_SITES" ]; then
            echo "🎯 检测到目标域名 $DOMAIN，正在覆盖以下宝塔默认证书目录: $OVERWRITE_SITES"
            
            SITES=(${OVERWRITE_SITES//,/ })
            OVERWRITE_CMD=""
            
            for site in "${SITES[@]}"; do
                if [ -n "$site" ]; then
                    BT_CERT_DIR="/www/server/panel/vhost/cert/$site"
                    OVERWRITE_CMD="${OVERWRITE_CMD}mkdir -p ${BT_CERT_DIR} && cp -f ${SSL_DIR}/${DOMAIN}.pem ${BT_CERT_DIR}/fullchain.pem && cp -f ${SSL_DIR}/${DOMAIN}.key.pem ${BT_CERT_DIR}/privkey.pem; "
                fi
            done
            
            ssh $SSH_OPTS "$HOST_USER@$HOST_IP" "$OVERWRITE_CMD" 2>&1 || true
            echo "✅ [$DOMAIN] 宝塔目录文件覆盖完成！"
        fi
        # ====================================================

        echo "🔄 准备重载 Nginx..."
        # 三重容错机制 (Systemd -> SysVinit -> Nginx Binary)
        RELOAD_CMD="systemctl reload nginx 2>/dev/null || /etc/init.d/nginx reload 2>/dev/null || /www/server/nginx/sbin/nginx -s reload"
        INSTALL_LOG=$(ssh $SSH_OPTS "$HOST_USER@$HOST_IP" "$RELOAD_CMD" 2>&1) || DEPLOY_EXIT_CODE=$?
        
        if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
            echo "🎉 [$DOMAIN] 部署与重载全部完成！"
            if [ -n "$OVERWRITE_SITES" ]; then
                EMAIL_REPORT="${EMAIL_REPORT}🎉 [${DOMAIN}]: 新证书下发成功，已更新宝塔面板路径并重载服务！\n"
            else
                EMAIL_REPORT="${EMAIL_REPORT}🎉 [${DOMAIN}]: 新证书下发成功，已存入缓冲目录。\n"
            fi
        else
            echo "❌ [$DOMAIN] Nginx 重载失败"
            EMAIL_REPORT="${EMAIL_REPORT}⚠️ [${DOMAIN}]: 新证书推送成功，但服务重载失败，日志：${INSTALL_LOG}\n"
            HAS_ERROR=1
        fi
    else
        echo "❌ [$DOMAIN] SCP推送失败"
        EMAIL_REPORT="${EMAIL_REPORT}❌ [${DOMAIN}]: 新证书 SCP 推送至 ${HOST_IP} 失败。\n"
        HAS_ERROR=1
    fi
done

# ================= 联动 EdgeOne 同步脚本 =================
# 青龙面板环境下，使用绝对路径定位子脚本
EO_SCRIPT="/ql/data/scripts/renew_edgeone.sh"

# 增加一个兼容老版本青龙的备用路径
if [ ! -f "$EO_SCRIPT" ]; then
    EO_SCRIPT="/ql/scripts/renew_edgeone.sh"
fi

if [ -f "$EO_SCRIPT" ]; then
    echo -e "\n=================================================="
    echo "🚀 源站处理完毕，开始调用 EdgeOne 同步脚本..."
    echo "=================================================="
    
    EO_EXIT_CODE=0
    # 执行子脚本
    bash "$EO_SCRIPT" || EO_EXIT_CODE=$?
    
    # 读取子脚本产生的临时日志文件，拼接到主邮件报告中
    if [ -f "/tmp/eo_sync_report.txt" ]; then
        EMAIL_REPORT="${EMAIL_REPORT}\n$(cat /tmp/eo_sync_report.txt)\n"
        rm -f "/tmp/eo_sync_report.txt"
    fi
    
    if [ $EO_EXIT_CODE -ne 0 ]; then
        HAS_ERROR=1
    fi
else
    echo -e "\n⚠️ 未找到 EdgeOne 同步脚本 ($EO_SCRIPT)，已跳过边缘同步环节。"
fi

# ================= 任务结束发送总计邮件 =================
if [ $HAS_ERROR -eq 1 ]; then
    send_email "存在异常(Warning/Error)" "$EMAIL_REPORT"
    exit 1
else
    send_email "全部完成(Success)" "$EMAIL_REPORT"
    exit 0
fi