#!/bin/bash
# ═══════════════════════════════════════════════
# 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
# 📜 Copyright: 国作登字-2026-A-00037559
# ═══════════════════════════════════════════════
# server/proxy/deploy-proxy.sh
# 🚀 铸渊专线V1 · 一键部署脚本
#
# ⚠️ [DEPRECATED · D58] V1节点已停用
# 铸渊专线2.0已测试通过并正式启用，V1节点不再使用。
# V2部署脚本: deploy-brain-proxy.sh (大脑服务器·共享流量池2000GB/月)
# 此文件保留作为V1历史参考，不再部署运行。
#
# 在SG服务器上执行，完成代理服务的完整部署:
#   1. 安装Xray-core + BBR
#   2. 生成密钥
#   3. 配置Xray (从环境变量或密钥文件读取)
#   4. 配置Nginx反代
#   5. 启动PM2服务
#   6. 健康检查
#
# 用法:
#   bash deploy-proxy.sh install    — 首次安装
#   bash deploy-proxy.sh update     — 更新配置
#   bash deploy-proxy.sh status     — 检查状态
#   bash deploy-proxy.sh restart    — 重启所有服务
# ═══════════════════════════════════════════════

set -uo pipefail
# 注意: 不使用 set -e，关键步骤手动检查错误

PROXY_DIR="/opt/zhuyuan/proxy"
REPO_PROXY_DIR="$(dirname "$0")"
ACTION="${1:-status}"

echo "════════════════════════════════════════"
echo "🌐 铸渊专线 · 部署 · action=$ACTION"
echo "════════════════════════════════════════"

# ── 共用: 确保Xray以root运行 (修复User=nobody问题) ──
ensure_xray_root_user() {
    if [ ! -f /etc/systemd/system/xray.service.d/override.conf ]; then
        mkdir -p /etc/systemd/system/xray.service.d
        cat > /etc/systemd/system/xray.service.d/override.conf <<EOF
[Service]
User=root
EOF
        systemctl daemon-reload
        echo "  ✅ Xray服务已配置为root用户运行"
    fi
}

# ── 共用: 确保日志目录权限正确 ──
ensure_log_permissions() {
    mkdir -p "$PROXY_DIR/logs"
    chmod 755 "$PROXY_DIR/logs"
}

# ── 共用: 保存环境变量到.env.keys ──
save_server_host() {
    KEYS_FILE="$PROXY_DIR/.env.keys"
    if [ -n "${ZY_SERVER_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then
        # 检查是否已存在
        if grep -q "^ZY_SERVER_HOST=" "$KEYS_FILE" 2>/dev/null; then
            # 更新已有的值
            sed -i "s|^ZY_SERVER_HOST=.*|ZY_SERVER_HOST=${ZY_SERVER_HOST}|" "$KEYS_FILE"
        else
            # 追加新行
            echo "" >> "$KEYS_FILE"
            echo "# 服务器地址 (部署时自动写入)" >> "$KEYS_FILE"
            echo "ZY_SERVER_HOST=${ZY_SERVER_HOST}" >> "$KEYS_FILE"
        fi
        echo "  ✅ ZY_SERVER_HOST 已保存到 .env.keys"
    elif [ -n "${ZY_SERVER_HOST:-}" ] && [ ! -f "$KEYS_FILE" ]; then
        echo "  ⚠️ .env.keys 不存在，创建并写入 ZY_SERVER_HOST"
        echo "# 服务器地址 (部署时自动写入)" > "$KEYS_FILE"
        echo "ZY_SERVER_HOST=${ZY_SERVER_HOST}" >> "$KEYS_FILE"
        chmod 600 "$KEYS_FILE"
    fi

    # 保存CN中转地址 (如果有)
    if [ -n "${ZY_CN_RELAY_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then
        if grep -q "^ZY_CN_RELAY_HOST=" "$KEYS_FILE" 2>/dev/null; then
            sed -i "s|^ZY_CN_RELAY_HOST=.*|ZY_CN_RELAY_HOST=${ZY_CN_RELAY_HOST}|" "$KEYS_FILE"
        else
            echo "" >> "$KEYS_FILE"
            echo "# CN中转服务器地址 (部署时自动写入)" >> "$KEYS_FILE"
            echo "ZY_CN_RELAY_HOST=${ZY_CN_RELAY_HOST}" >> "$KEYS_FILE"
        fi
        echo "  ✅ ZY_CN_RELAY_HOST 已保存到 .env.keys"
    fi

    # 保存SMTP凭据 (如果有) — 使守护Agent和流量监控可发送告警邮件
    # 注: 使用删除+追加方式避免sed特殊字符问题 (密码常含|&/$等)
    if [ -n "${ZY_SMTP_USER:-}" ] && [ -f "$KEYS_FILE" ]; then
        if grep -q "^ZY_SMTP_USER=" "$KEYS_FILE" 2>/dev/null; then
            grep -v "^ZY_SMTP_USER=" "$KEYS_FILE" > "${KEYS_FILE}.tmp" && mv "${KEYS_FILE}.tmp" "$KEYS_FILE"
        else
            echo "" >> "$KEYS_FILE"
            echo "# SMTP凭据 (部署时自动写入·守护Agent告警用)" >> "$KEYS_FILE"
        fi
        printf '%s\n' "ZY_SMTP_USER=${ZY_SMTP_USER}" >> "$KEYS_FILE"
        chmod 600 "$KEYS_FILE"
        echo "  ✅ ZY_SMTP_USER 已保存到 .env.keys"
    fi
    if [ -n "${ZY_SMTP_PASS:-}" ] && [ -f "$KEYS_FILE" ]; then
        if grep -q "^ZY_SMTP_PASS=" "$KEYS_FILE" 2>/dev/null; then
            grep -v "^ZY_SMTP_PASS=" "$KEYS_FILE" > "${KEYS_FILE}.tmp" && mv "${KEYS_FILE}.tmp" "$KEYS_FILE"
        fi
        printf '%s\n' "ZY_SMTP_PASS=${ZY_SMTP_PASS}" >> "$KEYS_FILE"
        chmod 600 "$KEYS_FILE"
        echo "  ✅ ZY_SMTP_PASS 已保存到 .env.keys"
    fi
}

# ── install: 首次完整安装 ─────────────────────
install() {
    echo ""
    echo "═══ [1/7] 安装Xray-core + BBR ═══"
    bash "$REPO_PROXY_DIR/setup/install-xray.sh"

    echo ""
    echo "═══ [2/7] 配置Xray ═══"
    if ! configure_xray; then
        echo "❌ Xray配置失败，安装中止"
        exit 1
    fi

    echo ""
    echo "═══ [3/7] 启动Xray服务 ═══"
    ensure_xray_root_user
    ensure_log_permissions

    systemctl enable xray
    systemctl restart xray
    sleep 2
    if systemctl is-active --quiet xray; then
        echo "✅ Xray运行中"
    else
        echo "❌ Xray启动失败"
        journalctl -u xray --no-pager -n 20
        exit 1
    fi

    echo ""
    echo "═══ [4/7] 部署代理服务代码 ═══"
    deploy_services
    save_server_host

    echo ""
    echo "═══ [5/7] 配置Nginx ═══"
    configure_nginx

    echo ""
    echo "═══ [6/7] 启动PM2服务 ═══"
    start_pm2_services

    echo ""
    echo "═══ [7/7] 健康检查 ═══"
    health_check

    echo ""
    echo "════════════════════════════════════════"
    echo "✅ 铸渊专线安装完成"
    echo ""
    echo "下一步:"
    echo "  1. 将生成的密钥添加到GitHub Secrets"
    echo "  2. 运行 'send-subscription' 工作流发送订阅链接"
    echo "════════════════════════════════════════"
}

# ── 配置Xray ──────────────────────────────────
configure_xray() {
    # 读取密钥 (优先环境变量, 其次密钥文件)
    KEYS_FILE="$PROXY_DIR/.env.keys"
    if [ -z "${ZY_PROXY_UUID:-}" ] && [ -f "$KEYS_FILE" ]; then
        # shellcheck source=/dev/null
        source "$KEYS_FILE"
    fi

    # 验证关键变量
    if [ -z "${ZY_PROXY_UUID:-}" ]; then
        echo "❌ 缺少 ZY_PROXY_UUID"
        echo "  请先运行 install 生成密钥，或设置环境变量"
        return 1
    fi

    if [ -z "${ZY_PROXY_REALITY_PRIVATE_KEY:-}" ]; then
        echo "❌ 缺少 ZY_PROXY_REALITY_PRIVATE_KEY"
        return 1
    fi

    if [ -z "${ZY_PROXY_REALITY_SHORT_ID:-}" ]; then
        echo "❌ 缺少 ZY_PROXY_REALITY_SHORT_ID"
        return 1
    fi

    # 用环境变量替换模板
    CONFIG_TEMPLATE="$REPO_PROXY_DIR/config/xray-config-template.json"
    CONFIG_OUTPUT="/usr/local/etc/xray/config.json"

    sed -e "s|{{ZY_PROXY_UUID}}|${ZY_PROXY_UUID}|g" \
        -e "s|{{ZY_PROXY_REALITY_PRIVATE_KEY}}|${ZY_PROXY_REALITY_PRIVATE_KEY}|g" \
        -e "s|{{ZY_PROXY_REALITY_SHORT_ID}}|${ZY_PROXY_REALITY_SHORT_ID}|g" \
        "$CONFIG_TEMPLATE" > "$CONFIG_OUTPUT"

    # 验证配置
    if xray run -test -c "$CONFIG_OUTPUT" 2>/dev/null; then
        echo "✅ Xray配置验证通过"
    else
        echo "⚠️ Xray配置验证失败，查看详情:"
        xray run -test -c "$CONFIG_OUTPUT" 2>&1 || true
        echo "  配置文件: $CONFIG_OUTPUT"
        return 1
    fi
}

# ── 部署服务代码 ──────────────────────────────
deploy_services() {
    mkdir -p "$PROXY_DIR"/{service,data,logs,dashboard}

    # 复制服务文件
    cp "$REPO_PROXY_DIR"/service/*.js "$PROXY_DIR/service/"
    cp "$REPO_PROXY_DIR"/dashboard/*.js "$PROXY_DIR/dashboard/"
    cp "$REPO_PROXY_DIR"/ecosystem.proxy.config.js "$PROXY_DIR/"

    echo "✅ 服务代码已部署到 $PROXY_DIR"
}

# ── 配置Nginx ─────────────────────────────────
configure_nginx() {
    # 查找正确的Nginx配置文件 (zhuyuan.conf 优先于 default)
    NGINX_CONF=""
    for candidate in /etc/nginx/sites-enabled/zhuyuan.conf /etc/nginx/sites-enabled/default; do
        if [ -f "$candidate" ]; then
            NGINX_CONF="$candidate"
            break
        fi
    done

    if [ -z "$NGINX_CONF" ]; then
        echo "  ⚠️ 未找到Nginx站点配置文件"
        return 0
    fi

    echo "  使用Nginx配置: $NGINX_CONF"

    # 移除默认配置文件，避免 duplicate default_server 冲突
    # zhuyuan.conf 已声明 default_server，不能与 default 文件共存
    if [ "$NGINX_CONF" = "/etc/nginx/sites-enabled/zhuyuan.conf" ] && [ -e "/etc/nginx/sites-enabled/default" ]; then
        rm -f /etc/nginx/sites-enabled/default
        echo "  ✅ 已移除冲突的 default 配置 (避免 duplicate default_server)"
    fi

    if ! grep -q "proxy-sub" "$NGINX_CONF" 2>/dev/null; then
        echo "  添加Nginx代理订阅反向代理配置..."
        # 在第一个 location = /health 之前插入 proxy-sub location
        sed -i '/# ─── 健康探针 ───/{
            # 只在第一次匹配时插入
            i\    # ─── 铸渊专线订阅服务 (端口 3802) ───\n    location /api/proxy-sub/ {\n        proxy_pass http://127.0.0.1:3802/;\n        proxy_http_version 1.1;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_connect_timeout 10s;\n        proxy_read_timeout 30s;\n        proxy_send_timeout 30s;\n        add_header X-Content-Type-Options nosniff always;\n        add_header Cache-Control "no-store, no-cache, must-revalidate" always;\n    }\n
        }' "$NGINX_CONF" || true
        echo "  ✅ Nginx proxy-sub配置已注入"
    else
        echo "  Nginx proxy-sub配置已存在"
    fi

    # 确保主服务器块是default_server (修复localhost/127.0.0.1健康检查匹配问题)
    if ! grep -q "default_server" "$NGINX_CONF" 2>/dev/null; then
        # 匹配 "listen 80;" 并添加 default_server（兼容不同空白格式）
        sed -i '0,/listen[[:space:]]\+80[[:space:]]*;/{s/listen[[:space:]]\+80[[:space:]]*;/listen 80 default_server;/}' "$NGINX_CONF" || true
        echo "  ✅ 已设置为默认服务器 (default_server)"
    fi

    # 确保server_name包含localhost (使内部健康检查可匹配)
    # 先检查server_name行中是否已有localhost，避免重复添加
    if ! grep "server_name" "$NGINX_CONF" | head -1 | grep -q "localhost" 2>/dev/null; then
        sed -i '0,/server_name /{s/server_name /server_name localhost 127.0.0.1 /}' "$NGINX_CONF" || true
        echo "  ✅ 已添加localhost到server_name"
    fi

    if nginx -t 2>/dev/null; then
        nginx -s reload || true
        echo "  ✅ Nginx配置验证通过并已重载"
    else
        echo "  ⚠️ Nginx配置验证失败:"
        nginx -t 2>&1 || true
    fi
}

# ── 启动/重启PM2服务 ──────────────────────────
# 使用 pm2 startOrRestart 统一处理（已注册→重启，未注册→启动）
start_pm2_services() {
    cd "$PROXY_DIR" || { echo "❌ 无法进入 $PROXY_DIR"; return 1; }

    # 加载密钥作为环境变量
    if [ -f "$PROXY_DIR/.env.keys" ]; then
        set -a
        # shellcheck source=/dev/null
        source "$PROXY_DIR/.env.keys"
        set +a
    fi

    pm2 startOrRestart ecosystem.proxy.config.js --update-env
    pm2 save
    echo "✅ PM2代理服务已就绪"
    pm2 list
}

# ── 健康检查 ──────────────────────────────────
health_check() {
    echo "检查服务状态..."

    # Xray
    if systemctl is-active --quiet xray; then
        echo "  ✅ Xray: 运行中"
    else
        echo "  ❌ Xray: 未运行"
    fi

    # 443端口 (应由Xray占用)
    if ss -tlnp | grep -q ":443 "; then
        echo "  ✅ 端口443: 监听中"
        # 检查是谁占用443
        PORT443_PROC=$(ss -tlnp | grep ":443 " | head -1)
        if echo "$PORT443_PROC" | grep -q "xray"; then
            echo "     → Xray占用443 (正确·VPN模式)"
            echo "     → dest回落: www.microsoft.com:443 (Reality反探测)"
        elif echo "$PORT443_PROC" | grep -q "nginx"; then
            echo "     ⚠️ Nginx占用443 (应由Xray占用·VPN可能不工作)"
            echo "     → 请先停止Nginx的443监听，再启动Xray"
        fi
    else
        echo "  ❌ 端口443: 未监听"
    fi

    # UFW防火墙 — 验证端口443已开放
    if command -v ufw &>/dev/null; then
        if ufw status | grep -q "443/tcp.*ALLOW"; then
            echo "  ✅ UFW防火墙: 端口443已开放"
        else
            echo "  ❌ UFW防火墙: 端口443未开放!"
            echo "     → 自动修复: 正在添加UFW规则..."
            if ufw allow 443/tcp comment "Xray VLESS+Reality" 2>/dev/null; then
                echo "     → ✅ 已添加UFW规则"
            else
                echo "     → ❌ UFW规则添加失败 (可能需要root权限)"
            fi
        fi
    fi

    # 订阅服务 (直接访问)
    if curl -sf http://127.0.0.1:3802/health >/dev/null 2>&1; then
        echo "  ✅ 订阅服务: 正常 (直连3802)"
    else
        echo "  ❌ 订阅服务: 端口3802无响应"
    fi

    # 订阅服务 (通过Nginx反代)
    # 使用ZY_SERVER_HOST作为Host头，确保Nginx server_name匹配
    HEALTH_HOST="${ZY_SERVER_HOST:-}"
    if [ -z "$HEALTH_HOST" ] && [ -f "$PROXY_DIR/.env.keys" ]; then
        HEALTH_HOST=$(grep "^ZY_SERVER_HOST=" "$PROXY_DIR/.env.keys" 2>/dev/null | sed 's/^ZY_SERVER_HOST=//;s/#.*//;s/^[[:space:]]*//;s/[[:space:]]*$//')
    fi
    if curl -sf -H "Host: ${HEALTH_HOST:-localhost}" http://127.0.0.1/api/proxy-sub/health >/dev/null 2>&1; then
        echo "  ✅ Nginx反代: 正常 (/api/proxy-sub/ → 3802)"
    else
        echo "  ⚠️ Nginx反代: /api/proxy-sub/ 未响应 (Nginx配置可能缺失)"
        echo "     → 检查: /etc/nginx/sites-enabled/zhuyuan.conf 是否包含 proxy-sub location"
        echo "     → 检查: Nginx是否有default_server指令或server_name包含localhost"
    fi

    # PM2
    pm2 list 2>/dev/null || echo "  ⚠️ PM2: 未配置"

    # ── 云防火墙诊断 (腾讯云轻量应用服务器) ──
    echo ""
    echo "  ═══ 云防火墙诊断 ═══"
    echo "  ⚠️ 腾讯云有两层防火墙:"
    echo "     1. UFW (操作系统层) — 已在上方检查"
    echo "     2. 腾讯云控制台防火墙 — 需要冰朔手动确认"
    echo ""
    echo "  如果服务端一切正常但客户端仍然连接超时 (i/o timeout):"
    echo "     → 问题在腾讯云控制台的防火墙规则"
    echo "     → 冰朔操作: 腾讯云控制台 → 轻量应用服务器 → 防火墙"
    echo "     → 确认规则: TCP 443 端口 允许所有来源 (0.0.0.0/0)"
    echo "     → 确认规则: TCP 80 端口 允许所有来源 (0.0.0.0/0)"
    echo ""

    # 外部连通性自检 (从服务器内部测试443端口是否可达)
    if timeout 5 bash -c "echo >/dev/tcp/127.0.0.1/443" 2>/dev/null; then
        echo "  ✅ 本地443端口自检: 可达"
    else
        echo "  ❌ 本地443端口自检: 不可达"
    fi
}

# ── update: 更新配置 ──────────────────────────
update() {
    echo "更新代理服务..."
    deploy_services
    save_server_host
    configure_xray
    configure_nginx

    ensure_xray_root_user
    ensure_log_permissions

    # 确保443端口在UFW中开放 (Xray VLESS+Reality必需)
    if command -v ufw &>/dev/null; then
        if ! ufw status | grep -q "443/tcp.*ALLOW" 2>/dev/null; then
            if ufw allow 443/tcp comment "Xray VLESS+Reality" 2>/dev/null; then
                echo "  ✅ 已添加UFW端口443规则"
            else
                echo "  ⚠️ UFW端口443规则添加失败 (请手动检查)"
            fi
        fi
    fi

    # 关闭3802外部端口 (订阅服务改为通过Nginx反代访问)
    if ufw status | grep -q "3802/tcp" 2>/dev/null; then
        ufw delete allow 3802/tcp || true
        echo "  ✅ 已移除3802端口外部访问规则"
    fi

    # 检查并修复443端口冲突
    # 如果Nginx占用了443端口(旧SSL配置)，需要移除以让Xray接管
    if ss -tlnp | grep ":443 " | grep -q "nginx"; then
        echo "⚠️ 检测到Nginx占用443端口 (旧SSL配置冲突)"
        echo "  修复: 移除Nginx的443监听配置以让Xray接管..."

        # 移除旧的SSL配置 (不再通过Xray回落提供HTTPS)
        for conf in /etc/nginx/sites-enabled/ssl-*.conf; do
            [ -e "$conf" ] || continue
            if grep -q "listen.*443\|listen.*8443" "$conf" 2>/dev/null; then
                echo "  移除旧SSL配置: $conf"
                rm -f "$conf"
            fi
        done

        nginx -t 2>/dev/null && nginx -s reload 2>/dev/null || true
        echo "  ✅ Nginx旧SSL配置已清理"
    fi

    systemctl restart xray

    # PM2代理服务
    start_pm2_services

    health_check
    echo "✅ 更新完成"
}

# ── status: 检查状态 ──────────────────────────
status() {
    health_check
}

# ── restart: 重启所有 ─────────────────────────
restart() {
    echo "重启所有代理服务..."
    systemctl restart xray
    # PM2代理服务
    start_pm2_services
    sleep 3
    health_check
}

# ── 执行 ──────────────────────────────────────
case "$ACTION" in
    install)  install ;;
    update)   update ;;
    status)   status ;;
    restart)  restart ;;
    *)
        echo "用法: bash deploy-proxy.sh {install|update|status|restart}"
        exit 1
        ;;
esac
