#!/usr/bin/env bash
# ============================================================
# install_frps_v2.sh - frp 服务端安装脚本（Linux only）
#
# 支持: Ubuntu / Debian / CentOS / RHEL / Anolis 等
#
# 角色:
#   公网 VPS (本脚本目标) → 装 frps，等待 frpc 连接
#   内网机器              → 装 frpc（用 install_frpc_v2.sh）
#
# 用法:
#   sudo bash install_frps_v2.sh
#
# 安装后:
#   systemctl start|stop|restart|status frps
#   Web 管理面板: http://<VPS_IP>:7500
# ============================================================

set -euo pipefail

# ============================================================
# ██████  宏定义 / 配置变量（按需修改）
# ██████
# ============================================================

# ---- frp 版本 & 安装路径 ----
FRP_VERSION="${FRP_VERSION:-}"                # 留空 = 自动获取最新版；也可手动指定如 "0.61.1"
INSTALL_DIR="/opt/frps"                       # 安装目录
SERVICE_NAME="frps"                           # 服务名称

# ---- frps 监听 & 认证 ----
FRPS_BIND_PORT="${FRPS_BIND_PORT:-7000}"      # frps 等待 frpc 连接的端口
FRPS_TOKEN="${FRPS_TOKEN:-}"                  # 认证令牌（留空 = 自动生成 32 位随机 hex）

# ---- Web 管理面板 ----
DASHBOARD_PORT="${DASHBOARD_PORT:-7500}"      # Web 管理面板端口
DASHBOARD_USER="${DASHBOARD_USER:-admin}"     # 管理面板用户名
DASHBOARD_PASS="${DASHBOARD_PASS:-}"          # 管理面板密码（留空 = 自动生成 16 位随机 hex）

# ---- 端口范围 ----
# frpc 可映射的端口范围，按需调整
ALLOW_PORTS_START="${ALLOW_PORTS_START:-2000}"
ALLOW_PORTS_END="${ALLOW_PORTS_END:-4000}"
MAX_PORTS_PER_CLIENT="${MAX_PORTS_PER_CLIENT:-20}"

# ---- 日志 ----
LOG_FILE="${INSTALL_DIR}/frps.log"            # 日志文件路径
LOG_LEVEL="${LOG_LEVEL:-info}"                # 日志级别: trace / debug / info / warn / error
LOG_MAX_DAYS="${LOG_MAX_DAYS:-7}"             # 日志保留天数

# ============================================================
# ██████  颜色 & 日志函数
# ██████
# ============================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

log_info()  { echo -e "${GREEN}[INFO]${NC}  $*"; }
log_warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
log_step()  { echo -e "\n${CYAN}>>>${NC} ${BOLD}$*${NC}"; }

# ============================================================
# ██████  0. 系统检测
# ██████
# ============================================================
detect_system() {
    if [ "$(uname -s)" != "Linux" ]; then
        log_error "frps 仅支持 Linux 系统，当前: $(uname -s)"
        log_error "如需在其他系统运行 frps，请手动下载: https://github.com/fatedier/frp/releases"
        exit 1
    fi

    case "$(uname -m)" in
        x86_64)      ARCH="amd64" ;;
        aarch64)     ARCH="arm64" ;;
        armv7l)      ARCH="arm"   ;;
        *)
            log_error "不支持的架构: $(uname -m)"
            exit 1
            ;;
    esac
}

# ============================================================
# ██████  辅助函数
# ██████
# ============================================================
get_latest_frp_version() {
    curl -s "https://api.github.com/repos/fatedier/frp/releases/latest" \
        | grep '"tag_name":' \
        | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/' \
        | sed 's/^v//'
}

# ============================================================
# ██████  安装前确认
# ██████
# ============================================================
preflight_confirm() {
    # 自动生成未指定的值
    if [ -z "$FRP_VERSION" ]; then
        log_info "获取 frp 最新版本号..."
        FRP_VERSION=$(get_latest_frp_version)
        if [ -z "$FRP_VERSION" ] || [ "$FRP_VERSION" = "null" ]; then
            log_error "无法获取最新版本号，请手动设置: export FRP_VERSION=x.x.x"
            exit 1
        fi
    fi

    [ -z "$FRPS_TOKEN" ]    && FRPS_TOKEN=$(openssl rand -hex 16)
    [ -z "$DASHBOARD_PASS" ] && DASHBOARD_PASS=$(openssl rand -hex 8)

    # 打印安装摘要
    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║${NC}          ${BOLD}frps 服务端 — 安装前确认${NC}                  ${CYAN}║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════╣${NC}"
    echo -e "${CYAN}║${NC}                                                  ${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}目标系统:${NC}   $(uname -s) / $(uname -m) $(printf '%*s' $((38 - ${#ARCH})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}frp 版本:${NC}    v${FRP_VERSION} $(printf '%*s' $((40 - ${#FRP_VERSION})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}安装目录:${NC}    ${INSTALL_DIR} $(printf '%*s' $((38 - ${#INSTALL_DIR})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}配置文件:${NC}    ${INSTALL_DIR}/frps.toml $(printf '%*s' $((26 - ${#INSTALL_DIR})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}                                                  ${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}连接端口:${NC}    ${FRPS_BIND_PORT} (frpc 连接端口) $(printf '%*s' $((23 - ${#FRPS_BIND_PORT})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}认证令牌:${NC}    ${FRPS_TOKEN} $(printf '%*s' $((38 - ${#FRPS_TOKEN})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}                                                  ${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}管理面板:${NC}    http://<VPS_IP>:${DASHBOARD_PORT} $(printf '%*s' $((19 - ${#DASHBOARD_PORT})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}面板账号:${NC}    ${DASHBOARD_USER} / ${DASHBOARD_PASS} $(printf '%*s' $((26 - ${#DASHBOARD_USER} - ${#DASHBOARD_PASS})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}                                                  ${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}允许端口:${NC}    ${ALLOW_PORTS_START}–${ALLOW_PORTS_END} (每客户端最多 ${MAX_PORTS_PER_CLIENT} 个) $(printf '%*s' $((12)) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}  ${BOLD}日志文件:${NC}    ${LOG_FILE} (保留 ${LOG_MAX_DAYS} 天) $(printf '%*s' $((21 - ${#LOG_FILE} - ${#LOG_MAX_DAYS})) '')${CYAN}║${NC}"
    echo -e "${CYAN}║${NC}                                                  ${CYAN}║${NC}"
    echo -e "${CYAN}╚══════════════════════════════════════════════════╝${NC}"
    echo ""

    # 用户确认
    read -r -p "确认以上信息无误，继续安装？[Y/n] " confirm
    case "${confirm:-Y}" in
        [Yy]|[Yy][Ee][Ss]) ;;
        *)
            log_warn "用户取消安装"
            exit 0
            ;;
    esac
    echo ""
}

# ============================================================
# ██████  1. 下载 frps
# ██████
# ============================================================
download_frps() {
    log_step "下载 frps v${FRP_VERSION}"

    FRP_TAR="frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
    FRP_URL="https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/${FRP_TAR}"
    TMP_DIR="/tmp/frp_install_$$"

    log_info "下载地址: $FRP_URL"
    mkdir -p "$TMP_DIR"

    if ! curl -fSL "$FRP_URL" -o "${TMP_DIR}/${FRP_TAR}"; then
        log_error "下载失败！检查网络或版本号: $FRP_VERSION"
        log_error "  curl -I $FRP_URL"
        rm -rf "$TMP_DIR"
        exit 1
    fi

    log_info "解压安装到 ${INSTALL_DIR}..."
    sudo mkdir -p "$INSTALL_DIR"
    tar -xzf "${TMP_DIR}/${FRP_TAR}" -C "$TMP_DIR"

    local extract_dir="${TMP_DIR}/frp_${FRP_VERSION}_linux_${ARCH}"
    sudo cp "${extract_dir}/frps" "$INSTALL_DIR/"
    sudo chmod +x "$INSTALL_DIR/frps"
    rm -rf "$TMP_DIR"

    log_info "frps 已安装到: ${INSTALL_DIR}/frps"
    log_info "版本信息: $("$INSTALL_DIR/frps" --version 2>&1 || true)"
}

# ============================================================
# ██████  2. 生成配置文件
# ██████
# ============================================================
generate_config() {
    log_step "生成 frps 配置"

    FRPS_CONF="$INSTALL_DIR/frps.toml"

    if [ -f "$FRPS_CONF" ]; then
        log_warn "配置文件已存在: $FRPS_CONF"
        read -r -p "覆盖现有配置？[y/N] " overwrite
        case "${overwrite:-N}" in
            [Yy]|[Yy][Ee][Ss]) ;;
            *)
                log_info "保留现有配置"
                return 0
                ;;
        esac
    fi

    sudo tee "$FRPS_CONF" > /dev/null <<EOF
# ============================================================
# frps 配置文件 (TOML 格式, frp >= v0.52.0)
# 文档: https://gofrp.org/docs/
# ============================================================

# [必填] 等待 frpc 连接的端口
bindPort = ${FRPS_BIND_PORT}

# [推荐] 认证令牌，frpc 必须提供相同 token
auth.token = "${FRPS_TOKEN}"

# [可选] Web 管理面板
webServer.addr = "0.0.0.0"
webServer.port = ${DASHBOARD_PORT}
webServer.user = "${DASHBOARD_USER}"
webServer.password = "${DASHBOARD_PASS}"

# [可选] 日志
log.to = "${LOG_FILE}"
log.level = "${LOG_LEVEL}"
log.maxDays = ${LOG_MAX_DAYS}

# [可选] 允许 frpc 映射的端口范围
allowPorts = [
    { start = ${ALLOW_PORTS_START}, end = ${ALLOW_PORTS_END} },
]

maxPortsPerClient = ${MAX_PORTS_PER_CLIENT}
EOF

    log_info "配置已生成: $FRPS_CONF"
}

# ============================================================
# ██████  3. 注册系统服务（交互确认）
# ██████
# ============================================================
install_service() {
    log_step "注册系统服务"

    echo ""
    echo -e "是否将 frps 注册为${BOLD} systemd 系统服务${NC}？"
    echo "  注册后: 开机自启、异常自动重启"
    echo "  管理:   systemctl start|stop|restart|status frps"
    echo "  配置:   /etc/systemd/system/${SERVICE_NAME}.service"
    echo ""

    read -r -p "注册为系统服务？[Y/n] " svc_confirm
    case "${svc_confirm:-Y}" in
        [Yy]|[Yy][Ee][Ss]) ;;
        *)
            log_warn "跳过系统服务注册，你可以稍后手动运行:"
            echo "  ${INSTALL_DIR}/frps -c ${FRPS_CONF}"
            return 0
            ;;
    esac

    _install_systemd
}

_install_systemd() {
    local svc_file="/etc/systemd/system/${SERVICE_NAME}.service"

    if [ -f "$svc_file" ]; then
        log_warn "服务文件已存在: $svc_file"
        read -r -p "覆盖现有服务文件？[y/N] " overwrite
        case "${overwrite:-N}" in
            [Yy]|[Yy][Ee][Ss]) ;;
            *)
                log_info "保留现有服务文件，仅重启服务"
                sudo systemctl daemon-reload
                sudo systemctl enable "$SERVICE_NAME"
                sudo systemctl restart "$SERVICE_NAME"
                _check_service
                return 0
                ;;
        esac
    fi

    sudo tee "$svc_file" > /dev/null <<SVC_EOF
[Unit]
Description=frp Server (frps)
Documentation=https://gofrp.org/docs/
After=network.target network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
ExecStart=${INSTALL_DIR}/frps -c ${FRPS_CONF}
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=15s

# 安全加固
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=${INSTALL_DIR}

[Install]
WantedBy=multi-user.target
SVC_EOF

    sudo systemctl daemon-reload
    sudo systemctl enable "$SERVICE_NAME"
    sudo systemctl restart "$SERVICE_NAME"

    _check_service
}

_check_service() {
    sleep 1
    if sudo systemctl is-active --quiet "$SERVICE_NAME"; then
        log_info "frps 系统服务运行正常 ✅"
    else
        log_error "frps 启动失败，请检查:"
        echo "  sudo systemctl status $SERVICE_NAME"
        echo "  sudo journalctl -u $SERVICE_NAME -n 50"
        return 1
    fi

    echo ""
    echo -e "  ${CYAN}管理命令:${NC}"
    echo "    systemctl start   frps    # 启动"
    echo "    systemctl stop    frps    # 停止"
    echo "    systemctl restart frps    # 重启"
    echo "    systemctl status  frps    # 状态"
    echo "    journalctl -u frps -f     # 实时日志"
}

# ============================================================
# ██████  主流程
# ██████
# ============================================================
main() {
    echo ""
    echo -e "${GREEN}╔══════════════════════════════════════════════════╗${NC}"
    echo -e "${GREEN}║${NC}              ${BOLD}frps 服务端安装脚本${NC}                    ${GREEN}║${NC}"
    echo -e "${GREEN}╚══════════════════════════════════════════════════╝${NC}"

    if [ "$EUID" -ne 0 ]; then
        log_warn "当前非 root 用户，脚本内的 sudo 可能需要输入密码"
    fi

    detect_system
    preflight_confirm
    download_frps
    generate_config
    install_service

    # ---- 完成 ----
    echo ""
    echo -e "${GREEN}╔══════════════════════════════════════════════════╗${NC}"
    echo -e "${GREEN}║${NC}              ${BOLD}frps 安装完成 ✅${NC}                        ${GREEN}║${NC}"
    echo -e "${GREEN}╚══════════════════════════════════════════════════╝${NC}"
    echo ""
    echo -e "  ${CYAN}文件位置:${NC}"
    echo "    二进制:   ${INSTALL_DIR}/frps"
    echo "    配置:     ${FRPS_CONF}"
    echo "    日志:     ${LOG_FILE}"
    echo ""
    echo -e "  ${CYAN}管理面板:${NC}"
    echo "    地址: http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo '<VPS_IP>'):${DASHBOARD_PORT}"
    echo "    账号: ${DASHBOARD_USER} / ${DASHBOARD_PASS}"
    echo ""
    echo -e "  ${CYAN}frpc 客户端配置参考 (内网机器):${NC}"
    echo "    serverAddr = \"$(hostname -I 2>/dev/null | awk '{print $1}' || echo '<VPS_IP>')\""
    echo "    serverPort = ${FRPS_BIND_PORT}"
    echo "    auth.token = \"${FRPS_TOKEN}\""
    echo ""
    echo -e "  ${CYAN}手动运行（未注册服务时）:${NC}"
    echo "    ${INSTALL_DIR}/frps -c ${FRPS_CONF}"
    echo ""
}

main
