#!/bin/bash
# https://github.com/sky22333/shell
# macOS 兼容版本 - 修复了 BSD grep 和 launchctl 兼容性问题

set -e

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

# 检测操作系统与架构
OS_TYPE=$(uname -s)
ARCH=$(uname -m)
if [[ "$OS_TYPE" == "Darwin" ]]; then
    # macOS 配置
    if [[ "$ARCH" == "arm64" ]]; then
        CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/download/2025.11.1/cloudflared-darwin-arm64.tgz"
    else
        CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/download/2025.11.1/cloudflared-darwin-amd64.tgz"
    fi
    CLOUDFLARED_BIN="/usr/local/bin/cloudflared"
    SERVICE_PATH="$HOME/Library/LaunchAgents/com.cloudflare.cloudflared.plist"
    LOG_PATH="$HOME/Library/Logs/cloudflared.log"
    USE_LAUNCHCTL=true
else
    # Linux 配置
    if [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
        CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/download/2025.11.1/cloudflared-linux-arm64"
    else
        CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/download/2025.11.1/cloudflared-linux-amd64"
    fi
    CLOUDFLARED_BIN="/usr/local/bin/cloudflared"
    SERVICE_PATH="/etc/systemd/system/cloudflared-tunnel.service"
    LOG_PATH="/var/log/cloudflared.log"
    USE_LAUNCHCTL=false
fi

# 检查 cloudflared 是否已存在
if [[ -f "$CLOUDFLARED_BIN" ]]; then
    echo -e "${GREEN}已存在文件，跳过下载。${NC}"
else
    echo -e "${BLUE}正在下载 cloudflared...${NC}"
    if [[ "$OS_TYPE" == "Darwin" ]]; then
        # macOS: 下载 tgz 包并解压出可执行文件
        TMP_TGZ=$(mktemp /tmp/cloudflared.XXXXXX.tgz)
        if ! curl -L "$CLOUDFLARED_URL" -o "$TMP_TGZ"; then
            echo -e "${RED}下载失败，请检查网络连接或 URL。${NC}"
            exit 1
        fi
        tar -xzf "$TMP_TGZ" -C /tmp
        # 解压后通常得到 cloudflared 可执行文件
        if [[ -f "/tmp/cloudflared" ]]; then
            sudo mv /tmp/cloudflared "$CLOUDFLARED_BIN"
        else
            # 有些发布包会包含子目录
            FOUND=$(find /tmp -maxdepth 2 -type f -name cloudflared 2>/dev/null | head -n1)
            if [[ -n "$FOUND" ]]; then
                sudo mv "$FOUND" "$CLOUDFLARED_BIN"
            else
                echo -e "${RED}未能在压缩包中找到 cloudflared 可执行文件${NC}"
                exit 1
            fi
        fi
        rm -f "$TMP_TGZ"
    else
        # Linux: 直接下载二进制
        if ! curl -L "$CLOUDFLARED_URL" -o "$CLOUDFLARED_BIN"; then
            echo -e "${RED}下载失败，请检查网络连接或 URL。${NC}"
            exit 1
        fi
    fi
    chmod +x "$CLOUDFLARED_BIN"
fi

# 检查服务是否存在（根据系统选择 launchctl 或 systemd）
SERVICE_EXISTS=false
if [[ "$USE_LAUNCHCTL" == true ]]; then
    if launchctl list | grep -q 'com.cloudflare.cloudflared'; then
        SERVICE_EXISTS=true
        echo -e "${YELLOW}已检测到 cloudflared launchctl 服务${NC}"
        read -p "是否要卸载旧服务？(y/n): " UNINSTALL
        if [[ "$UNINSTALL" == "y" || "$UNINSTALL" == "Y" ]]; then
            echo -e "${BLUE}正在卸载旧服务...${NC}"
            launchctl unload "$SERVICE_PATH" 2>/dev/null || true
            rm -f "$SERVICE_PATH"
            rm -f "$LOG_PATH"
            SERVICE_EXISTS=false
            echo -e "${GREEN}服务卸载完成${NC}"
        else
            echo -e "${YELLOW}将保留旧服务配置，仅修改穿透地址${NC}"
        fi
    fi
else
    if sudo systemctl list-units --full --all | grep -q 'cloudflared-tunnel.service'; then
        SERVICE_EXISTS=true
        echo -e "${YELLOW}已检测到 cloudflared-tunnel systemd 服务${NC}"
        read -p "是否要卸载旧服务？(y/n): " UNINSTALL
        if [[ "$UNINSTALL" == "y" || "$UNINSTALL" == "Y" ]]; then
            echo -e "${BLUE}正在卸载旧服务...${NC}"
            sudo systemctl stop cloudflared-tunnel || true
            sudo systemctl disable cloudflared-tunnel || true
            sudo rm -f "$SERVICE_PATH"
            sudo rm -f "$LOG_PATH"
            sudo systemctl daemon-reload
            SERVICE_EXISTS=false
            echo -e "${GREEN}服务卸载完成${NC}"
        else
            echo -e "${YELLOW}将保留旧服务配置，仅修改穿透地址${NC}"
        fi
    fi
fi

# 用户选择运行模式
echo ""
echo -e "${YELLOW}请选择运行模式：${NC}"
echo "1) 临时运行（前台运行并显示临时访问域名）"
echo "2) 后台运行（自动配置后台服务并显示访问域名）"
read -p "请输入 1 或 2: " MODE

# 输入内网地址
read -p "请输入要穿透的本地地址（例如 127.0.0.1:8080）: " LOCAL_ADDR

if [[ "$MODE" == "1" ]]; then
    echo -e "${BLUE}正在前台运行 cloudflared...${NC}"

    LOGFILE=$(mktemp)
    # macOS 无 stdbuf，用 script 捕获输出（同时兼容 Linux）
    if command -v stdbuf >/dev/null 2>&1; then
        stdbuf -oL "$CLOUDFLARED_BIN" tunnel --url "$LOCAL_ADDR" 2>&1 | tee "$LOGFILE" &
    else
        "$CLOUDFLARED_BIN" tunnel --url "$LOCAL_ADDR" 2>&1 | tee "$LOGFILE" &
    fi
    PID=$!

    echo -e "${YELLOW}等待 cloudflared 输出访问域名...${NC}"

    for i in {1..60}; do
        # BSD grep 无 -P，用 -E 实现扩展正则
        DOMAIN=$(grep -Eo 'https://[A-Za-z0-9-]+\.trycloudflare\.com' "$LOGFILE" | head -n1)
        if [[ -n "$DOMAIN" ]]; then
            echo ""
            echo -e "${GREEN}成功获取公网临时访问域名：$DOMAIN${NC}"
            echo ""
            wait $PID
            exit 0
        fi
        sleep 1
    done

    echo -e "${RED}超时未能获取临时域名，日志保存在：$LOGFILE${NC}"
    kill $PID 2>/dev/null || true
    exit 1

elif [[ "$MODE" == "2" ]]; then
    if [[ "$USE_LAUNCHCTL" == true ]]; then
        echo -e "${BLUE}正在配置 launchctl 服务...${NC}"
        mkdir -p "$(dirname "$SERVICE_PATH")" "$(dirname "$LOG_PATH")"
        cat > "$SERVICE_PATH" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.cloudflare.cloudflared</string>
    <key>ProgramArguments</key>
    <array>
        <string>$CLOUDFLARED_BIN</string>
        <string>tunnel</string>
        <string>--url</string>
        <string>$LOCAL_ADDR</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardOutPath</key>
    <string>$LOG_PATH</string>
    <key>StandardErrorPath</key>
    <string>$LOG_PATH</string>
</dict>
</plist>
EOF
        launchctl unload "$SERVICE_PATH" 2>/dev/null || true
        launchctl load "$SERVICE_PATH"
        launchctl start com.cloudflare.cloudflared || true
    else
        echo -e "${BLUE}正在配置 systemd 服务...${NC}"

        if [[ "$SERVICE_EXISTS" == false ]]; then
            sudo bash -c "cat > $SERVICE_PATH" <<EOF
[Unit]
Description=Cloudflared Tunnel Service
After=network.target

[Service]
ExecStart=$CLOUDFLARED_BIN tunnel --url $LOCAL_ADDR
Restart=always
StandardOutput=append:$LOG_PATH
StandardError=append:$LOG_PATH

[Install]
WantedBy=multi-user.target
EOF
            sudo systemctl daemon-reload
            sudo systemctl enable --now cloudflared-tunnel
        else
            echo -e "${YELLOW}更新 systemd 服务配置中的穿透地址...${NC}"
            sudo truncate -s 0 "$LOG_PATH" || sudo bash -c "> $LOG_PATH"
            sudo sed -i "s|ExecStart=.*|ExecStart=$CLOUDFLARED_BIN tunnel --url $LOCAL_ADDR|" "$SERVICE_PATH"
            sudo systemctl daemon-reload
            sudo systemctl restart cloudflared-tunnel
        fi
    fi

    echo -e "${GREEN}服务已启动，日志保存在 $LOG_PATH${NC}"
    echo -e "${YELLOW}等待 cloudflared 输出访问域名...${NC}"

    # 等待日志文件创建
    for i in {1..10}; do
        if [[ -f "$LOG_PATH" ]]; then
            break
        fi
        sleep 1
    done

    # 如果日志文件仍不存在，尝试创建
    if [[ ! -f "$LOG_PATH" ]]; then
        mkdir -p "$(dirname "$LOG_PATH")"
        touch "$LOG_PATH" 2>/dev/null || true
    fi

    for i in {1..60}; do
        if [[ -f "$LOG_PATH" ]]; then
            DOMAIN=$(grep -Eo 'https://[A-Za-z0-9-]+\.trycloudflare\.com' "$LOG_PATH" 2>/dev/null | head -n1)
            if [[ -n "$DOMAIN" ]]; then
                echo ""
                echo -e "${GREEN}成功获取公网访问域名：$DOMAIN${NC}"
                echo ""
                exit 0
            fi
        fi
        sleep 1
    done

    echo -e "${RED}超时未能获取公网访问域名，请稍后手动查看：$LOG_PATH${NC}"
    if [[ "$USE_LAUNCHCTL" == true ]]; then
        echo -e "${YELLOW}您也可以使用以下命令查看服务状态：${NC}"
        echo "launchctl list | grep cloudflared"
        echo "tail -f $LOG_PATH"
    fi
    exit 1

else
    echo -e "${RED}无效输入，请输入 1 或 2${NC}"
    exit 1
fi
