#!/bin/bash
# ============================================================
# VLESS + WebSocket + TLS + Cloudflare CDN 一键部署脚本
# 专为 Debian 系统优化
# ============================================================

set -e

# 自检：去除 Windows CRLF 换行符
if grep -qP '\r' "$0" 2>/dev/null; then
    sed -i 's/\r//' "$0"
    exec bash "$0" "$@"
fi

# 预设标准化配置（直接回车使用以下默认值）
PRESET_UUID="0ad7d003-8e79-4529-8b55-09610947c09b"
PRESET_WS_PATH="/stickrouter"
PRESET_SING_PORT="10000"
PRESET_NGINX_PORT="2053"
PRESET_EMAIL="a79376464@gmail.com"
BASE_DOMAIN="stickrouter.com"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

info()    { echo -e "${CYAN}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warning() { echo -e "${YELLOW}[!]${NC} $1"; }
error()   { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

ask() {
    echo -e "${BLUE}[?]${NC} $1"
    read INPUT_VAR
    eval "$2=\$INPUT_VAR"
}

ask_enter() {
    echo -e "${BLUE}[?]${NC} $1"
    read DUMMY
}

# ============================================================
# 检查 root 权限
# ============================================================
check_root() {
    if [ "$EUID" -ne 0 ]; then
        error "请使用 root 用户运行此脚本"
    fi
}

# ============================================================
# 检查 Debian 系统
# ============================================================
check_debian() {
    if [ ! -f /etc/debian_version ]; then
        error "此脚本仅支持 Debian 系统"
    fi
    DEBIAN_VER=$(cat /etc/debian_version | cut -d. -f1)
    info "检测到 Debian 版本：$(cat /etc/debian_version)"
    if [ "$DEBIAN_VER" -lt 10 ] 2>/dev/null; then
        warning "建议使用 Debian 10 或更高版本，当前版本可能存在兼容性问题"
    fi
}

# ============================================================
# 欢迎信息
# ============================================================
print_banner() {
    clear
    echo -e "${CYAN}"
    echo "======================================================"
    echo "   VLESS + WebSocket + TLS + Cloudflare CDN"
    echo "          一键部署脚本 (Debian 专版)"
    echo "======================================================"
    echo -e "${NC}"
    echo ""
    warning "部署前请确认："
    echo "  1. 子域名已在 Cloudflare 添加 A 记录指向本机 IP"
    echo "  2. Cloudflare 代理已关闭（灰色云朵）用于申请证书"
    echo "  3. Cloudflare SSL/TLS 模式已设为 完全(Full) 或 完全严格"
    echo ""
    ask_enter "确认以上条件已满足？按 Enter 继续，Ctrl+C 退出..."
}

# ============================================================
# 收集用户输入
# ============================================================
collect_info() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "开始收集配置信息..."
    echo ""

    # 子域名输入（只需输入前缀）
    while true; do
        ask "请输入子域名前缀（例如输入 hk01，域名将为 hk01.${BASE_DOMAIN}）：" SUBDOMAIN
        if echo "$SUBDOMAIN" | grep -qE '^[a-zA-Z0-9-]+$'; then
            DOMAIN="${SUBDOMAIN}.${BASE_DOMAIN}"
            info "完整域名：$DOMAIN"
            break
        else
            warning "子域名只能包含字母、数字和连字符，请重新输入"
        fi
    done

    # 邮箱（回车使用默认值）
    echo ""
    ask "请输入邮箱地址（直接回车使用预设值：${PRESET_EMAIL}）：" INPUT_EMAIL
    EMAIL=${INPUT_EMAIL:-$PRESET_EMAIL}
    info "使用邮箱：$EMAIL"

    # UUID
    echo ""
    ask "请输入 UUID（直接回车使用预设值：${PRESET_UUID}）：" INPUT_UUID
    UUID=${INPUT_UUID:-$PRESET_UUID}

    # WS 路径
    ask "请输入 WebSocket 路径（直接回车使用预设值：${PRESET_WS_PATH}）：" INPUT_WS_PATH
    if [ -z "$INPUT_WS_PATH" ]; then
        WS_PATH="$PRESET_WS_PATH"
    else
        WS_PATH="$INPUT_WS_PATH"
        case "$WS_PATH" in
            /*) ;;
            *) WS_PATH="/$WS_PATH" ;;
        esac
    fi

    # sing-box 内部端口
    ask "请输入 sing-box 本地监听端口（直接回车使用预设值：${PRESET_SING_PORT}）：" INPUT_PORT
    SING_PORT=${INPUT_PORT:-$PRESET_SING_PORT}

    # 对外端口
    ask "请输入对外监听端口（直接回车使用预设值：${PRESET_NGINX_PORT}）：" INPUT_NGINX_PORT
    NGINX_PORT=${INPUT_NGINX_PORT:-$PRESET_NGINX_PORT}

    # 确认信息
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "配置信息确认："
    echo ""
    echo "  完整域名：      $DOMAIN"
    echo "  邮箱：          $EMAIL"
    echo "  UUID：          $UUID"
    echo "  WS 路径：       $WS_PATH"
    echo "  sing-box 端口： $SING_PORT (本地内部)"
    echo "  对外端口：      $NGINX_PORT (客户端连接)"
    echo ""
    ask "确认以上信息正确？直接回车继续，输入 n 重新填写：" CONFIRM
    if [ "$CONFIRM" = "n" ] || [ "$CONFIRM" = "N" ]; then
        collect_info
    fi
}

# ============================================================
# 修复 APT 源（兼容 Debian 11/12）
# ============================================================
fix_apt_sources() {
    echo ""
    info "检查并修复 APT 源..."

    DEBIAN_VER=$(cat /etc/debian_version | cut -d. -f1)

    if [ "$DEBIAN_VER" = "11" ]; then
        warning "检测到 Debian 11，修复 backports 源..."
        # 修复 sources.list 里的 backports
        sed -i 's|deb.debian.org/debian bullseye-backports|archive.debian.org/debian bullseye-backports|g' \
            /etc/apt/sources.list 2>/dev/null || true
        # 注释掉 sources.list.d 里失效的 backports
        if ls /etc/apt/sources.list.d/*.list >/dev/null 2>&1; then
            sed -i '/bullseye-backports/s/^/#/' /etc/apt/sources.list.d/*.list 2>/dev/null || true
        fi
        success "Debian 11 源修复完成"
    elif [ "$DEBIAN_VER" = "12" ]; then
        success "Debian 12 源正常，无需修复"
    else
        info "Debian 版本：$DEBIAN_VER，跳过源修复"
    fi
}

# ============================================================
# 安装依赖（Debian 专用）
# ============================================================
install_deps() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "更新系统并安装依赖..."

    rm -f /var/lib/dpkg/lock-frontend
    rm -f /var/lib/apt/lists/lock

    apt-get update -qq
    apt-get install -y -qq \
        nginx \
        curl \
        wget \
        openssl \
        socat \
        cron

    systemctl enable cron
    systemctl start cron

    success "依赖安装完成"
}

# ============================================================
# 安装 sing-box
# ============================================================
install_singbox() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "安装 sing-box..."

    if command -v sing-box >/dev/null 2>&1; then
        CURRENT_VER=$(sing-box version | head -1)
        warning "sing-box 已安装：$CURRENT_VER"
        ask "是否重新安装最新版？(y/N)：" REINSTALL
        if [ "$REINSTALL" != "y" ] && [ "$REINSTALL" != "Y" ]; then
            success "跳过安装，使用现有版本"
            return
        fi
    fi

    ARCH=$(uname -m)
    case "$ARCH" in
        x86_64)  SB_ARCH="amd64" ;;
        aarch64) SB_ARCH="arm64" ;;
        armv7l)  SB_ARCH="armv7" ;;
        *)       SB_ARCH="amd64" ;;
    esac

    SB_VER=$(curl -fsSL https://api.github.com/repos/SagerNet/sing-box/releases/latest \
        | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')

    if [ -z "$SB_VER" ]; then
        error "无法获取 sing-box 最新版本，请检查网络连接"
    fi

    info "下载 sing-box v${SB_VER} (${SB_ARCH})..."
    DEB_URL="https://github.com/SagerNet/sing-box/releases/download/v${SB_VER}/sing-box_${SB_VER}_linux_${SB_ARCH}.deb"
    TMP_DEB="/tmp/sing-box.deb"

    if ! curl -fsSL -o "$TMP_DEB" "$DEB_URL"; then
        error "sing-box 下载失败，请检查网络或手动安装"
    fi

    dpkg -i "$TMP_DEB"
    rm -f "$TMP_DEB"

    if command -v sing-box >/dev/null 2>&1; then
        success "sing-box 安装成功：$(sing-box version | head -1)"
    else
        error "sing-box 安装失败，请检查网络连接"
    fi
}

# ============================================================
# 配置 sing-box
# ============================================================
configure_singbox() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "配置 sing-box..."

    mkdir -p /etc/sing-box

    cat > /etc/sing-box/config.json << EOF
{
  "log": {
    "level": "error",
    "timestamp": true
  },
  "inbounds": [
    {
      "type": "vless",
      "listen": "127.0.0.1",
      "listen_port": ${SING_PORT},
      "users": [
        {
          "uuid": "${UUID}"
        }
      ],
      "transport": {
        "type": "ws",
        "path": "${WS_PATH}"
      }
    }
  ],
  "outbounds": [
    {
      "type": "direct"
    }
  ]
}
EOF

    if sing-box check -c /etc/sing-box/config.json; then
        success "sing-box 配置验证通过"
    else
        error "sing-box 配置有误，请检查"
    fi

    systemctl enable sing-box
    systemctl restart sing-box
    sleep 2

    if systemctl is-active --quiet sing-box; then
        success "sing-box 启动成功，监听 127.0.0.1:${SING_PORT}"
    else
        error "sing-box 启动失败：$(systemctl status sing-box | tail -3)"
    fi
}

# ============================================================
# 安装 acme.sh 并申请 SSL 证书（纯 Shell，无需 Python）
# ============================================================
request_cert() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "申请 SSL 证书（使用 acme.sh）..."

    SERVER_IP=$(curl -4 -s --connect-timeout 5 ifconfig.me 2>/dev/null)
    DOMAIN_IP=$(getent hosts "$DOMAIN" 2>/dev/null | awk '{print $1}' | head -1)

    info "本机 IP：${SERVER_IP:-获取失败}"
    info "域名解析 IP：${DOMAIN_IP:-解析失败}"

    if [ -z "$SERVER_IP" ] || [ -z "$DOMAIN_IP" ]; then
        warning "IP 获取失败，请检查网络连接"
    elif [ "$SERVER_IP" != "$DOMAIN_IP" ]; then
        warning "IP 不一致！请确认："
        warning "  1. Cloudflare 中 $DOMAIN 的 A 记录已指向 ${SERVER_IP}"
        warning "  2. Cloudflare 已切换为灰色云朵（仅DNS）"
        ask "是否仍然继续申请？(y/N)：" FORCE
        if [ "$FORCE" != "y" ] && [ "$FORCE" != "Y" ]; then
            error "请修复域名解析后重新运行脚本"
        fi
    else
        success "域名解析验证通过：$DOMAIN → $SERVER_IP"
    fi

    # 安装 acme.sh
    if [ ! -f /root/.acme.sh/acme.sh ]; then
        info "安装 acme.sh..."
        curl -fsSL https://get.acme.sh | sh -s email="$EMAIL"
        source /root/.bashrc 2>/dev/null || true
    else
        success "acme.sh 已安装，跳过"
    fi

    ACME=/root/.acme.sh/acme.sh

    # 停止 nginx 释放 80 端口
    systemctl stop nginx 2>/dev/null || true
    sleep 1

    # 申请证书（standalone 模式）
    "$ACME" --issue -d "$DOMAIN" --standalone --email "$EMAIL" \
        --key-file   /etc/ssl/private/${DOMAIN}.key \
        --fullchain-file /etc/ssl/certs/${DOMAIN}.pem \
        --force || true

    # 检查证书是否成功
    if [ ! -f "/etc/ssl/certs/${DOMAIN}.pem" ]; then
        error "证书申请失败，请检查：1.域名解析 2.80端口是否开放 3.Cloudflare是否灰色云朵"
    fi

    CERT_EXPIRY=$(openssl x509 -enddate -noout -in "/etc/ssl/certs/${DOMAIN}.pem" | cut -d= -f2)
    success "SSL 证书申请成功！有效期至：$CERT_EXPIRY"

    # 设置证书路径变量供 nginx 使用
    CERT_FULLCHAIN="/etc/ssl/certs/${DOMAIN}.pem"
    CERT_KEY="/etc/ssl/private/${DOMAIN}.key"

    systemctl start nginx 2>/dev/null || true
}

# ============================================================
# 配置 Nginx
# ============================================================
configure_nginx() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "配置 Nginx 反向代理..."

    cat > /var/www/html/index.html << 'HTMLEOF'
<!DOCTYPE html>
<html>
<head>
  <title>Welcome to nginx!</title>
  <style>
    body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
  </style>
</head>
<body>
  <h1>Welcome to nginx!</h1>
  <p>If you see this page, the nginx web server is successfully installed and working.</p>
</body>
</html>
HTMLEOF

    rm -f /etc/nginx/sites-enabled/default

    cat > /etc/nginx/sites-available/sing-box << EOF
server {
    listen 80;
    server_name ${DOMAIN};
    return 301 https://\$host\$request_uri;
}

server {
    listen ${NGINX_PORT} ssl;
    server_name ${DOMAIN};

    ssl_certificate ${CERT_FULLCHAIN};
    ssl_certificate_key ${CERT_KEY};
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 伪装页面
    location / {
        root /var/www/html;
        index index.html;
    }

    # WebSocket 代理
    location ${WS_PATH} {
        proxy_pass http://127.0.0.1:${SING_PORT};
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        proxy_buffering off;
    }
}
EOF

    ln -sf /etc/nginx/sites-available/sing-box /etc/nginx/sites-enabled/

    if nginx -t 2>/dev/null; then
        success "Nginx 配置验证通过"
    else
        nginx -t
        error "Nginx 配置有误"
    fi

    systemctl enable nginx
    systemctl start nginx

    if systemctl is-active --quiet nginx; then
        success "Nginx 启动成功，监听端口 ${NGINX_PORT}"
    else
        error "Nginx 启动失败：$(systemctl status nginx | tail -3)"
    fi
}

# ============================================================
# 配置证书自动续期（acme.sh 自带 cron）
# ============================================================
setup_auto_renew() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "配置证书自动续期..."

    # acme.sh 安装时已自动写入 crontab，这里额外配置续期后重载 nginx
    ACME=/root/.acme.sh/acme.sh
    "$ACME" --install-cronjob 2>/dev/null || true

    # 配置续期钩子：证书更新后自动重载 nginx
    "$ACME" --install-cert -d "$DOMAIN" \
        --key-file   /etc/ssl/private/${DOMAIN}.key \
        --fullchain-file /etc/ssl/certs/${DOMAIN}.pem \
        --reloadcmd  "systemctl reload nginx" 2>/dev/null || true

    success "已配置自动续期（acme.sh 内置定时任务，证书到期前自动续期）"
}

# ============================================================
# 最终验证
# ============================================================
verify_services() {
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    info "验证服务状态..."

    if systemctl is-active --quiet sing-box; then
        success "sing-box 运行中 ✓"
    else
        warning "sing-box 未运行，尝试重启..."
        systemctl restart sing-box
    fi

    if systemctl is-active --quiet nginx; then
        success "nginx 运行中 ✓"
    else
        warning "nginx 未运行，尝试重启..."
        systemctl restart nginx
    fi

    if ss -tlnp | grep -q ":${NGINX_PORT}"; then
        success "端口 ${NGINX_PORT} 监听正常 ✓"
    else
        warning "端口 ${NGINX_PORT} 未监听，请检查 nginx 配置"
    fi

    if ss -tlnp | grep -q "127.0.0.1:${SING_PORT}"; then
        success "sing-box 端口 ${SING_PORT} 监听正常 ✓"
    else
        warning "sing-box 端口 ${SING_PORT} 未监听，请检查配置"
    fi
}

# ============================================================
# 打印最终结果
# ============================================================
print_result() {
    # URL encode WS path（纯 shell 实现，不依赖 python3）
    WS_PATH_ENCODED=$(printf '%s' "$WS_PATH" | od -An -tx1 | tr ' ' '\n' | \
        grep -v '^$' | while read hex; do
            case "$hex" in
                2f) printf '/' ;;  # 保留斜杠
                41|42|43|44|45|46|47|48|49|4a|4b|4c|4d|4e|4f|50|51|52|53|54|55|56|57|58|59|5a) printf "\\x$hex" | xxd -r -p ;;
                61|62|63|64|65|66|67|68|69|6a|6b|6c|6d|6e|6f|70|71|72|73|74|75|76|77|78|79|7a) printf "\\x$hex" | xxd -r -p ;;
                30|31|32|33|34|35|36|37|38|39) printf "\\x$hex" | xxd -r -p ;;
                2d|5f|2e|7e) printf "\\x$hex" | xxd -r -p ;;
                *) printf '%%%s' "$hex" ;;
            esac
        done)
    [ -z "$WS_PATH_ENCODED" ] && WS_PATH_ENCODED="$WS_PATH"
    VLESS_LINK="vless://${UUID}@${DOMAIN}:${NGINX_PORT}?encryption=none&security=tls&sni=${DOMAIN}&fp=chrome&type=ws&host=${DOMAIN}&path=${WS_PATH_ENCODED}#VLESS-WS-TLS"

    echo ""
    echo -e "${GREEN}"
    echo "======================================================"
    echo "                  部署完成！"
    echo "======================================================"
    echo -e "${NC}"

    echo -e "${CYAN}------------------------------------------------------${NC}"
    echo -e "${GREEN}客户端配置参数：${NC}"
    echo ""
    echo "  协议：          VLESS"
    echo "  地址：          $DOMAIN"
    echo "  端口：          $NGINX_PORT"
    echo "  UUID：          $UUID"
    echo "  传输方式：      WebSocket (ws)"
    echo "  WS 路径：       $WS_PATH"
    echo "  WS Host：       $DOMAIN"
    echo "  TLS：           开启"
    echo "  SNI：           $DOMAIN"
    echo "  指纹：          chrome"
    echo "  REALITY：       关闭"
    echo "  允许不安全：    关闭"
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    echo -e "${YELLOW}VLESS 链接（可直接导入客户端）：${NC}"
    echo ""
    echo "$VLESS_LINK"
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    echo -e "${YELLOW}请在 Cloudflare 确认：${NC}"
    echo "  1. 橙色云朵已开启（已代理）"
    echo "  2. SSL/TLS 模式：完全(Full) 或 完全严格"
    echo ""
    echo -e "${CYAN}------------------------------------------------------${NC}"
    echo -e "${YELLOW}常用管理命令：${NC}"
    echo "  查看 sing-box 状态：  systemctl status sing-box"
    echo "  查看 nginx 状态：     systemctl status nginx"
    echo "  查看 sing-box 日志：  journalctl -u sing-box -f"
    echo "  手动续期证书：        ~/.acme.sh/acme.sh --renew -d $DOMAIN"
    echo "  配置文件位置："
    echo "    sing-box:  /etc/sing-box/config.json"
    echo "    nginx:     /etc/nginx/sites-available/sing-box"
    echo "    证书：     /etc/ssl/certs/${DOMAIN}.pem"
    echo "    续期任务： crontab -l"
    echo ""

    CONFIG_FILE="/root/vless-config.txt"
    cat > "$CONFIG_FILE" << EOF
VLESS + WebSocket + TLS + Cloudflare CDN 配置
生成时间：$(date)
系统：Debian $(cat /etc/debian_version)

域名：          $DOMAIN
端口：          $NGINX_PORT
UUID：          $UUID
WS 路径：       $WS_PATH
TLS：           开启
SNI：           $DOMAIN
指纹：          chrome

VLESS 链接：
$VLESS_LINK

文件路径：
  sing-box 配置：/etc/sing-box/config.json
  nginx 配置：   /etc/nginx/sites-available/sing-box
  证书：         /etc/ssl/certs/${DOMAIN}.pem
  续期任务：     crontab -l
EOF
    success "配置已保存至 $CONFIG_FILE"
}

# ============================================================
# 主流程
# ============================================================
main() {
    check_root
    check_debian
    print_banner
    collect_info
    fix_apt_sources
    install_deps
    install_singbox
    configure_singbox
    request_cert
    configure_nginx
    setup_auto_renew
    verify_services
    print_result
}

main
