#!/usr/bin/env bash
set -euo pipefail

# ============================================
# Xray VPS 一键部署脚本
# 支持模式：reality (VLESS-Reality) / fast (VLESS TCP 无 TLS)
# 适用于 Debian 11+ / Ubuntu 20.04+
# ============================================

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

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

log()   { echo -e "${GREEN}[INFO]${NC} $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
step()  { echo -e "\n${CYAN}========== $* ==========${NC}"; }

# ===== 使用说明 =====
usage() {
    echo "用法: bash deploy.sh [选项]"
    echo ""
    echo "选项:"
    echo "  --mode reality    VLESS-Reality 模式（默认，推荐，抗封锁）"
    echo "  --mode fast       VLESS TCP 模式（无 TLS，极速但易被检测）"
    echo "  -h, --help        显示帮助"
    exit 0
}

# ===== 解析参数 =====
MODE="reality"
while [[ $# -gt 0 ]]; do
    case $1 in
        --mode) MODE="$2"; shift 2 ;;
        -h|--help) usage ;;
        *) error "未知参数: $1"; usage ;;
    esac
done

if [[ "$MODE" != "reality" && "$MODE" != "fast" ]]; then
    error "无效模式: $MODE（支持 reality / fast）"
    exit 1
fi

# ===== 检查 root =====
if [ "$(id -u)" -ne 0 ]; then
    error "请使用 root 用户运行: sudo bash deploy.sh"
    exit 1
fi

# ===== 加载现有配置（如存在）=====
if [ -f .env ]; then
    sed -i 's/\r$//' .env
    set -a; source .env; set +a
fi

XRAY_PORT="${XRAY_PORT:-443}"

# ===== 1. 安装 Xray =====
install_xray() {
    step "1/5 安装 Xray"

    if command -v xray &>/dev/null || [ -x /usr/local/bin/xray ]; then
        log "Xray 已安装: $(/usr/local/bin/xray version | head -1)"
        log "将更新到最新版本..."
    fi

    bash <(curl -fsSL https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh)
    log "Xray 安装完成: $(/usr/local/bin/xray version | head -1)"
}

# ===== 2. 生成密钥 =====
generate_keys() {
    step "2/5 生成密钥"

    XRAY_UUID="${XRAY_UUID:-$(cat /proc/sys/kernel/random/uuid)}"
    log "UUID: ${XRAY_UUID}"

    if [ "$MODE" = "reality" ]; then
        if [ -z "${XRAY_PRIVATE_KEY:-}" ] || [ -z "${XRAY_PUBLIC_KEY:-}" ]; then
            local keys
            keys=$(/usr/local/bin/xray x25519 2>&1)
            XRAY_PRIVATE_KEY=$(echo "$keys" | grep -i 'private' | awk -F': ' '{print $2}' | tr -d '[:space:]')
            XRAY_PUBLIC_KEY=$(echo "$keys" | grep -i 'public' | awk -F': ' '{print $2}' | tr -d '[:space:]')
        fi
        XRAY_SHORT_ID="${XRAY_SHORT_ID:-$(openssl rand -hex 8)}"

        if [ -z "$XRAY_PRIVATE_KEY" ] || [ -z "$XRAY_PUBLIC_KEY" ]; then
            error "密钥生成失败！xray x25519 输出:"
            echo "$keys"
            exit 1
        fi
        log "x25519 密钥对已生成或已加载"
        log "ShortId: ${XRAY_SHORT_ID}"
    fi
}

# ===== 3. 选择 Reality 伪装目标 =====
select_reality_dest() {
    if [ "$MODE" != "reality" ]; then
        return
    fi

    step "3/5 选择 Reality 伪装目标"

    local candidates=("www.microsoft.com" "dl.google.com" "www.apple.com" "www.amazon.com")
    REALITY_DEST="${REALITY_DEST:-}"
    REALITY_SNI="${REALITY_SNI:-}"

    if [ -n "$REALITY_DEST" ] && [ -n "$REALITY_SNI" ]; then
        log "使用 .env 中指定的伪装目标: ${REALITY_DEST}"
        return
    fi

    local best_dest="www.microsoft.com"
    local best_ms=9999

    for site in "${candidates[@]}"; do
        local ms
        ms=$(curl -so /dev/null -w '%{time_connect}' --max-time 3 "https://${site}" 2>/dev/null \
            | awk '{printf "%d", $1*1000}') || true
        if [ -n "$ms" ] && [ "$ms" -lt "$best_ms" ] 2>/dev/null; then
            best_ms=$ms
            best_dest=$site
        fi
    done

    REALITY_DEST="$best_dest"
    REALITY_SNI="$best_dest"
    log "伪装目标: ${REALITY_DEST} (延迟 ${best_ms}ms)"
}

# ===== 4. 写入 Xray 配置 =====
write_config() {
    if [ "$MODE" = "reality" ]; then
        write_config_reality
    else
        write_config_fast
    fi
}

write_config_reality() {
    step "3/5 写入 Xray 配置 (Reality)"

    cat > /usr/local/etc/xray/config.json << EOF
{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": ${XRAY_PORT},
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "${XRAY_UUID}",
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "${REALITY_DEST}:443",
          "xver": 0,
          "serverNames": [
            "${REALITY_SNI}"
          ],
          "privateKey": "${XRAY_PRIVATE_KEY}",
          "shortIds": [
            "${XRAY_SHORT_ID}"
          ]
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"],
        "routeOnly": true
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "direct"
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "outboundTag": "block",
        "protocol": ["bittorrent"]
      }
    ]
  }
}
EOF

    log "配置已写入: /usr/local/etc/xray/config.json"
}

write_config_fast() {
    step "3/5 写入 Xray 配置 (Fast TCP)"

    cat > /usr/local/etc/xray/config.json << EOF
{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": ${XRAY_PORT},
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "${XRAY_UUID}"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"],
        "routeOnly": true
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "direct"
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "outboundTag": "block",
        "protocol": ["bittorrent"]
      }
    ]
  }
}
EOF

    log "配置已写入: /usr/local/etc/xray/config.json"
}

# ===== 5. 防火墙 =====
configure_firewall() {
    step "4/5 配置防火墙"

    if command -v ufw &>/dev/null; then
        ufw allow "${XRAY_PORT}/tcp"
        ufw allow 22/tcp
        ufw --force enable
        log "ufw 已放行端口 ${XRAY_PORT}/tcp"
    elif command -v firewall-cmd &>/dev/null; then
        firewall-cmd --permanent --add-port="${XRAY_PORT}/tcp"
        firewall-cmd --reload
        log "firewalld 已放行端口 ${XRAY_PORT}/tcp"
    else
        warn "未检测到防火墙工具，请手动放行端口 ${XRAY_PORT}/tcp"
    fi
}

# ===== 6. BBR + 网络调优 =====
tune_network() {
    step "5/5 BBR + 网络调优"

    cat > /etc/sysctl.d/99-xray-turbo.conf << 'SYSEOF'
# BBR 拥塞控制
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

# TCP 缓冲区（提升大文件 / 视频流吞吐量）
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216

# 连接优化
net.ipv4.tcp_fastopen=3
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_mtu_probing=1
net.ipv4.tcp_fin_timeout=15
net.ipv4.tcp_keepalive_time=300
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_max_tw_buckets=262144
net.ipv4.tcp_max_syn_backlog=8192
net.core.somaxconn=8192
net.core.netdev_max_backlog=8192
SYSEOF

    sysctl --system > /dev/null 2>&1
    log "BBR 已启用，网络参数已优化"
}

# ===== 新增：系统与服务加固 =====
harden_system() {
    step "加固系统与服务"

    # 文件描述符上限
    if ! grep -q '99-xray-nofile' /etc/security/limits.conf 2>/dev/null; then
        cat >> /etc/security/limits.conf << 'EOF'
# 99-xray-nofile
* soft nofile 1000000
* hard nofile 1000000
root soft nofile 1000000
root hard nofile 1000000
EOF
    fi

    # systemd 服务加固
    mkdir -p /etc/systemd/system/xray.service.d
    cat > /etc/systemd/system/xray.service.d/override.conf << 'EOF'
[Service]
LimitNOFILE=1000000
Restart=always
RestartSec=3
EOF

    # 定时重启 timer（每日凌晨 4 点）
    cat > /etc/systemd/system/xray-restart.service << 'EOF'
[Unit]
Description=Daily restart of Xray
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/systemctl restart xray
EOF

    cat > /etc/systemd/system/xray-restart.timer << 'EOF'
[Unit]
Description=Daily restart Xray at 04:00 CST

[Timer]
OnCalendar=*-*-* 04:00:00
TimeZone=Asia/Shanghai
Persistent=true

[Install]
WantedBy=timers.target
EOF
}

# ===== 7. 启动服务 =====
start_service() {
    systemctl daemon-reload
    systemctl restart xray
    systemctl enable xray
    systemctl enable --now xray-restart.timer

    sleep 2
    if systemctl is-active --quiet xray; then
        log "Xray 服务已启动 ✅"
    else
        error "Xray 启动失败，请检查: journalctl -u xray -f"
        exit 1
    fi
}

# ===== 8. 保存配置到 .env =====
save_env() {
    cat > "$SCRIPT_DIR/.env" << EOF
# Xray 部署配置（由 deploy.sh 自动生成）
# 生成时间: $(date '+%Y-%m-%d %H:%M:%S')

XRAY_MODE=${MODE}
XRAY_PORT=${XRAY_PORT}
XRAY_UUID=${XRAY_UUID}
EOF

    if [ "$MODE" = "reality" ]; then
        cat >> "$SCRIPT_DIR/.env" << EOF
XRAY_PRIVATE_KEY=${XRAY_PRIVATE_KEY}
XRAY_PUBLIC_KEY=${XRAY_PUBLIC_KEY}
XRAY_SHORT_ID=${XRAY_SHORT_ID}
REALITY_DEST=${REALITY_DEST}
REALITY_SNI=${REALITY_SNI}
EOF
    fi

    chmod 600 "$SCRIPT_DIR/.env"
    log "配置已保存到 .env（权限 600）"
}

# ===== 9. 输出连接信息 =====
print_result() {
    local server_ip
    server_ip=$(curl -s --max-time 5 ipv4.ip.sb || curl -s --max-time 5 ifconfig.me || echo "获取失败")

    echo ""
    echo "=========================================================="

    if [ "$MODE" = "reality" ]; then
        echo "    Xray VLESS-Reality 部署完成 ✅"
        echo "=========================================================="
        echo ""
        echo "  IP          : ${server_ip}"
        echo "  端口        : ${XRAY_PORT}"
        echo "  协议        : VLESS"
        echo "  UUID        : ${XRAY_UUID}"
        echo "  流控        : xtls-rprx-vision"
        echo "  传输        : tcp"
        echo "  安全        : reality"
        echo "  SNI         : ${REALITY_SNI}"
        echo "  Fingerprint : chrome"
        echo "  PublicKey   : ${XRAY_PUBLIC_KEY}"
        echo "  ShortId     : ${XRAY_SHORT_ID}"
        echo ""
        echo "=========================================================="
        echo ""
        echo ">>> VLESS 分享链接（可直接导入客户端）:"
        echo ""
        echo "vless://${XRAY_UUID}@${server_ip}:${XRAY_PORT}?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SNI}&fp=chrome&pbk=${XRAY_PUBLIC_KEY}&sid=${XRAY_SHORT_ID}&type=tcp#VPS-Reality"
    else
        echo "    Xray VLESS TCP 部署完成 ✅"
        echo "=========================================================="
        echo ""
        echo "  IP     : ${server_ip}"
        echo "  端口   : ${XRAY_PORT}"
        echo "  协议   : VLESS"
        echo "  UUID   : ${XRAY_UUID}"
        echo "  传输   : tcp"
        echo "  安全   : none"
    fi

    echo ""
    echo "=========================================================="
    echo ""
    echo "⚠️  请妥善保存以上信息！"
    echo "    配置文件: /usr/local/etc/xray/config.json"
    echo "    凭据备份: ${SCRIPT_DIR}/.env"
    echo "    查看日志: journalctl -u xray -f"
    echo "    重启服务: systemctl restart xray"
    echo "=========================================================="
}

# ===== 主流程 =====
main() {
    echo ""
    log "部署模式: ${MODE}"
    [ "$MODE" = "reality" ] && log "VLESS-Reality（推荐，抗封锁）" || log "VLESS TCP（极速，无 TLS）"
    echo ""

    install_xray
    generate_keys
    select_reality_dest
    write_config
    configure_firewall
    tune_network
    harden_system
    start_service
    save_env
    print_result
}

main
