#!/data/data/com.termux/files/usr/bin/bash
#
# forge-server.sh —— Termux 长期运行守护脚本
#
# 用法：
#   ./forge-server.sh start     启动
#   ./forge-server.sh stop      停止
#   ./forge-server.sh restart   重启
#   ./forge-server.sh status    查看状态
#   ./forge-server.sh log       查看日志
#   ./forge-server.sh notice    编辑公告
#   ./forge-server.sh stats     查看统计
#

set -u

# ==================== 配置 ====================

PORT=8080
TOKEN=forge123

# 脚本所在目录
DIR="$(cd "$(dirname "$0")" && pwd)"
SERVER="$DIR/server.php"
PIDFILE="$DIR/server.pid"
LOGFILE="$DIR/server.log"
NOTICEFILE="$DIR/notice.txt"

# ==================== 颜色 ====================

G='\033[32m'
R='\033[31m'
Y='\033[33m'
B='\033[36m'
N='\033[0m'

info()  { echo -e "${B}[*]${N} $*"; }
ok()    { echo -e "${G}[+]${N} $*"; }
err()   { echo -e "${R}[-]${N} $*"; }
warn()  { echo -e "${Y}[!]${N} $*"; }

# ==================== 检查环境 ====================

check_env() {
    if ! command -v php >/dev/null 2>&1; then
        err "未安装 PHP"
        echo "请执行: pkg install php"
        exit 1
    fi

    if [ ! -f "$SERVER" ]; then
        err "找不到 server.php"
        echo "期望路径: $SERVER"
        exit 1
    fi

    # 目录可写
    if ! touch "$DIR/.wtest" 2>/dev/null; then
        err "目录不可写: $DIR"
        exit 1
    fi
    rm -f "$DIR/.wtest"
}

# ==================== 获取 IP ====================

get_ip() {
    local ip

    # 优先用 ip 命令
    if command -v ip >/dev/null 2>&1; then
        ip=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K[0-9.]+' | head -1)
        if [ -n "$ip" ]; then
            echo "$ip"
            return
        fi
    fi

    # 退到 ifconfig
    if command -v ifconfig >/dev/null 2>&1; then
        ip=$(ifconfig 2>/dev/null | grep -oP 'inet \K192\.168\.[0-9.]+' | head -1)
        if [ -n "$ip" ]; then
            echo "$ip"
            return
        fi
    fi

    echo "127.0.0.1"
}

# ==================== 状态 ====================

is_running() {
    if [ -f "$PIDFILE" ]; then
        local pid
        pid=$(cat "$PIDFILE" 2>/dev/null)
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            return 0
        fi
    fi
    return 1
}

# ==================== 启动 ====================

do_start() {
    if is_running; then
        warn "服务已在运行 (PID $(cat "$PIDFILE"))"
        return
    fi

    check_env

    info "启动 PHP 内置服务器..."

    # nohup 后台运行，断开终端也不退出
    nohup php -S "0.0.0.0:$PORT" "$SERVER" >> "$LOGFILE" 2>&1 &

    local pid=$!
    echo "$pid" > "$PIDFILE"

    sleep 1.2

    if is_running; then
        local ip
        ip=$(get_ip)

        echo
        echo -e "${G}==================================${N}"
        echo -e "${G} 服务已启动${N}"
        echo -e "${G}==================================${N}"
        echo -e " PID     : $pid"
        echo -e " 监听    : 0.0.0.0:$PORT"
        echo -e " 地址    : ${B}http://$ip:$PORT${N}"
        echo -e " 密钥    : $TOKEN"
        echo -e " 日志    : $LOGFILE"
        echo -e "${G}==================================${N}"
        echo
        echo "App 里填写的地址："
        echo -e "  ${B}http://$ip:$PORT${N}"
        echo
        echo "常用命令："
        echo "  ./forge-server.sh notice    编辑公告"
        echo "  ./forge-server.sh stats     查看统计"
        echo "  ./forge-server.sh stop      停止"
        echo
    else
        err "启动失败，检查日志：$LOGFILE"
        tail -20 "$LOGFILE" 2>/dev/null
        rm -f "$PIDFILE"
    fi
}

# ==================== 停止 ====================

do_stop() {
    if ! is_running; then
        warn "服务未运行"
        rm -f "$PIDFILE"
        return
    fi

    local pid
    pid=$(cat "$PIDFILE" 2>/dev/null)

    info "停止服务 (PID $pid)..."

    kill "$pid" 2>/dev/null

    # 等 3 秒
    local i=0
    while [ $i -lt 30 ]; do
        if ! kill -0 "$pid" 2>/dev/null; then
            break
        fi
        sleep 0.1
        i=$((i + 1))
    done

    # 还没死就强杀
    if kill -0 "$pid" 2>/dev/null; then
        warn "强制结束"
        kill -9 "$pid" 2>/dev/null
    fi

    rm -f "$PIDFILE"
    ok "已停止"
}

# ==================== 状态 ====================

do_status() {
    echo
    if is_running; then
        local pid ip
        pid=$(cat "$PIDFILE" 2>/dev/null)
        ip=$(get_ip)

        echo -e "${G}● 运行中${N}"
        echo "  PID     : $pid"
        echo "  端口    : $PORT"
        echo -e "  地址    : ${B}http://$ip:$PORT${N}"
        echo "  日志    : $LOGFILE"

        # 公告状态
        if [ -f "$NOTICEFILE" ] && [ -s "$NOTICEFILE" ]; then
            local size
            size=$(wc -c < "$NOTICEFILE")
            echo -e "  公告    : ${G}已发布${N} ($size 字节)"
        else
            echo -e "  公告    : ${R}未发布${N}"
        fi

        # 统计
        if [ -f "$DIR/stats.json" ]; then
            local total
            total=$(grep -o '"total":[0-9]*' "$DIR/stats.json" 2>/dev/null | head -1 | cut -d: -f2)
            if [ -n "$total" ]; then
                echo "  使用次数 : $total"
            fi
        fi

    else
        echo -e "${R}● 未运行${N}"
    fi
    echo
}

# ==================== 日志 ====================

do_log() {
    if [ ! -f "$LOGFILE" ]; then
        warn "日志文件不存在"
        return
    fi

    info "实时日志（Ctrl+C 退出）"
    echo
    tail -f "$LOGFILE"
}

# ==================== 编辑公告 ====================

do_notice() {
    echo
    echo "当前公告："
    echo "----------------------------------------"
    if [ -f "$NOTICEFILE" ] && [ -s "$NOTICEFILE" ]; then
        cat "$NOTICEFILE"
    else
        echo "(未发布)"
    fi
    echo "----------------------------------------"
    echo

    echo "1) 发布新公告"
    echo "2) 删除公告（禁用 App）"
    echo "3) 返回"
    echo
    read -p "选择: " choice

    case "$choice" in
        1)
            echo
            echo "请输入公告内容，输入 EOF 单独一行结束："
            echo "----------------------------------------"

            local tmp="$DIR/.notice.tmp"
            > "$tmp"

            while IFS= read -r line; do
                if [ "$line" = "EOF" ]; then
                    break
                fi
                echo "$line" >> "$tmp"
            done

            if [ ! -s "$tmp" ]; then
                err "内容为空，已取消"
                rm -f "$tmp"
                return
            fi

            mv "$tmp" "$NOTICEFILE"
            ok "公告已发布"
            echo
            cat "$NOTICEFILE"
            ;;

        2)
            if [ -f "$NOTICEFILE" ]; then
                rm -f "$NOTICEFILE"
                ok "公告已删除，App 将被禁用"
            else
                warn "公告本来就不存在"
            fi
            ;;

        *)
            return
            ;;
    esac
}

# ==================== 统计 ====================

do_stats() {
    local ip
    ip=$(get_ip)

    echo
    info "使用统计"
    echo "========================================"

    if command -v curl >/dev/null 2>&1; then
        curl -s "http://127.0.0.1:$PORT/api/stats?token=$TOKEN" | \
            php -r '$d=json_decode(file_get_contents("php://stdin"),true);
if(!is_array($d)){echo "解析失败\n";exit;}
if(empty($d["ok"])){echo "未授权或服务异常\n";exit;}
echo "总次数  : ".$d["total"]."\n";
echo "独立IP  : ".$d["unique"]."\n\n";
echo "按 IP 明细:\n";
foreach($d["by_ip"] as $k=>$v){
  echo sprintf("  %-16s %3d 次  %s  %s\n",$k,$v["count"],$v["last"],$v["device"]);
}'
    else
        err "未安装 curl"
        echo "请执行: pkg install curl"
    fi

    echo "========================================"
    echo
}

# ==================== 主入口 ====================

case "${1:-}" in
    start)   do_start   ;;
    stop)    do_stop    ;;
    restart) do_stop; sleep 0.5; do_start ;;
    status)  do_status  ;;
    log)     do_log     ;;
    notice)  do_notice  ;;
    stats)   do_stats   ;;
    *)
        echo "FORGE 服务端管理"
        echo
        echo "用法: $0 {start|stop|restart|status|log|notice|stats}"
        echo
        echo "  start    启动服务"
        echo "  stop     停止服务"
        echo "  restart  重启服务"
        echo "  status   查看状态"
        echo "  log      实时日志"
        echo "  notice   编辑/删除公告"
        echo "  stats    查看使用统计"
        echo
        ;;
esac
