#!/bin/bash

#===============================================================================
# 新机部署: Docker + Docker Compose + AstrBot + NapCat (不含 Dockge)
#
# 适用系统: Ubuntu 20.04+ / Debian 11+ / CentOS 7+ / Rocky 8+ / Fedora 35+
#
# 使用方法:
#   chmod +x deploy-astrbot-napcat-standalone.sh && sudo ./deploy-astrbot-napcat-standalone.sh
#
# 部署内容:
#   1. Docker Engine      - 容器运行时 (如未安装)
#   2. Docker Compose     - 容器编排工具 (如未安装)
#   3. AstrBot + NapCat   - QQ 机器人 (使用官方 astrbot.yml)
#
# 部署完成后访问:
#   AstrBot WebUI : http://<服务器IP>:6185   (默认账号 astrbot / 密码见启动日志)
#   NapCat WebUI  : http://<服务器IP>:6099   (Token 见启动日志)
#===============================================================================

set -euo pipefail

#-------------------------------------------------------------------------------
# 颜色与输出
#-------------------------------------------------------------------------------
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'

info()  { echo -e "${GREEN}[INFO]${NC}  $1"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
step()  { echo -e "\n${BLUE}==>${NC} ${CYAN}$1${NC}"; }

#-------------------------------------------------------------------------------
# 默认配置
#-------------------------------------------------------------------------------
# AstrBot+NapCat 部署目录
# 如果用 sudo 运行, 使用实际用户的 home 目录而非 /root
if [[ -n "${SUDO_USER:-}" ]]; then
    ASTROBOT_DIR="$(eval echo ~${SUDO_USER})/astrbot-deploy"
else
    ASTROBOT_DIR="${HOME}/astrbot-deploy"
fi

# 官方 astrbot.yml (来自 NapCat-Docker 仓库, 已内置 AstrBot + NapCat 两个服务)
ASTROBOT_COMPOSE_URL="https://raw.githubusercontent.com/NapNeko/NapCat-Docker/main/compose/astrbot.yml"

#-------------------------------------------------------------------------------
# 系统检测
#-------------------------------------------------------------------------------
detect_os() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        OS_ID="${ID}"
        OS_NAME="${PRETTY_NAME:-${ID}}"
    else
        error "无法检测操作系统类型 (/etc/os-release 不存在)"
        exit 1
    fi

    case "$OS_ID" in
        ubuntu|debian|deepin|uos)
            PKG_TYPE="apt"
            ;;
        centos|rhel|rocky|almalinux|fedora|openEuler|anolis)
            if command -v dnf &>/dev/null; then
                PKG_TYPE="dnf"
            else
                PKG_TYPE="yum"
            fi
            ;;
        arch|manjaro)
            PKG_TYPE="pacman"
            ;;
        opensuse*|sles)
            PKG_TYPE="zypper"
            ;;
        *)
            warn "未识别的发行版: $OS_ID，将尝试使用通用方式安装 Docker"
            PKG_TYPE="generic"
            ;;
    esac

    info "检测到系统: $OS_NAME"
    info "包管理器类型: $PKG_TYPE"
}

detect_arch() {
    local arch
    arch=$(uname -m)
    case "$arch" in
        x86_64|amd64)  echo "amd64" ;;
        aarch64|arm64) echo "arm64" ;;
        armv7l)        echo "armv7" ;;
        *)
            error "不支持的 CPU 架构: $arch"
            exit 1
            ;;
    esac
}

#-------------------------------------------------------------------------------
# 小工具
#-------------------------------------------------------------------------------
command_exists() {
    command -v "$1" &>/dev/null
}

confirm() {
    local prompt="$1"
    local default="${2:-y}"
    local yn
    read -p "$prompt (y/n, 默认 $default): " yn
    yn="${yn:-$default}"
    [[ "$yn" == "y" || "$yn" == "Y" ]]
}

get_server_ip() {
    ip -4 addr show scope global 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 || echo "服务器IP"
}

#-------------------------------------------------------------------------------
# 步骤 1: 安装 Docker Engine
# 参考: https://docs.docker.com/engine/install/
#-------------------------------------------------------------------------------
install_docker() {
    step "步骤 1/4: 安装 Docker Engine"

    if command_exists docker; then
        info "Docker 已安装: $(docker --version)"
        return 0
    fi

    if ! confirm "Docker 未安装，是否安装？"; then
        warn "已跳过 Docker 安装 (后续步骤会失败)"
        return 0
    fi

    info "开始安装 Docker Engine..."

    case "$PKG_TYPE" in
        #--- Ubuntu / Debian ---
        apt)
            info "卸载旧版本 (如有)..."
            for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
                apt-get remove -y "$pkg" 2>/dev/null || true
            done

            info "安装依赖..."
            apt-get update -qq
            apt-get install -y -qq ca-certificates curl

            info "添加 Docker 官方 GPG 密钥..."
            install -m 0755 -d /etc/apt/keyrings
            curl -fsSL "https://download.docker.com/linux/${OS_ID}/gpg" -o /etc/apt/keyrings/docker.asc
            chmod a+r /etc/apt/keyrings/docker.asc

            info "添加 Docker APT 源..."
            echo "deb [arch=$(detect_arch) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/${OS_ID} $(lsb_release -cs 2>/dev/null || echo "bookworm") stable" \
                > /etc/apt/sources.list.d/docker.list

            apt-get update -qq
            apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
            ;;

        #--- CentOS / RHEL / Fedora (dnf) ---
        dnf)
            info "卸载旧版本 (如有)..."
            dnf remove -y docker docker-client docker-client-latest docker-common \
                docker-latest docker-latest-logrotate docker-logrotate docker-engine 2>/dev/null || true

            info "添加 Docker 官方仓库..."
            dnf config-manager --add-repo "https://download.docker.com/linux/${OS_ID}/docker-ce.repo" 2>/dev/null || \
                { dnf install -y dnf-plugins-core && dnf config-manager --add-repo "https://download.docker.com/linux/${OS_ID}/docker-ce.repo"; }

            info "安装 Docker Engine..."
            dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
            ;;

        #--- CentOS / RHEL (yum) ---
        yum)
            info "卸载旧版本 (如有)..."
            yum remove -y docker docker-client docker-client-latest docker-common \
                docker-latest docker-latest-logrotate docker-logrotate docker-engine 2>/dev/null || true

            info "安装依赖..."
            yum install -y yum-utils

            info "添加 Docker 官方仓库..."
            yum-config-manager --add-repo "https://download.docker.com/linux/${OS_ID}/docker-ce.repo" 2>/dev/null || true

            info "安装 Docker Engine..."
            yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
            ;;

        #--- Arch Linux ---
        pacman)
            info "安装 Docker..."
            pacman -S --noconfirm docker docker-compose 2>/dev/null || true
            ;;

        #--- openSUSE ---
        zypper)
            info "安装 Docker..."
            zypper --non-interactive install docker docker-compose 2>/dev/null || true
            ;;

        #--- 通用兜底 ---
        generic)
            warn "未识别的包管理器，使用 Docker 官方安装脚本..."
            curl -fsSL https://get.docker.com | bash
            ;;
    esac

    info "启动 Docker 并设为开机自启..."
    systemctl enable docker --now 2>/dev/null || service docker start 2>/dev/null || true

    if command_exists docker; then
        info "Docker 安装完成: $(docker --version)"
    else
        error "Docker 安装失败，请手动安装后重试"
        error "参考: https://docs.docker.com/engine/install/"
        exit 1
    fi
}

#-------------------------------------------------------------------------------
# 步骤 2: 确保 Docker Compose 可用
#-------------------------------------------------------------------------------
install_docker_compose() {
    step "步骤 2/4: 检查 Docker Compose"

    # Plugin 形式 (v2): docker compose
    if docker compose version &>/dev/null; then
        info "Docker Compose (Plugin v2) 已就绪: $(docker compose version)"
        return 0
    fi

    # 独立二进制 (v1): docker-compose
    if command_exists docker-compose; then
        info "docker-compose (v1) 已安装: $(docker-compose --version)"
        warn "建议升级到 Docker Compose v2 Plugin"
        return 0
    fi

    if ! confirm "Docker Compose 未安装，是否安装？"; then
        warn "已跳过 Docker Compose 安装"
        return 0
    fi

    info "安装 Docker Compose Plugin..."

    case "$PKG_TYPE" in
        apt)
            apt-get update -qq && apt-get install -y -qq docker-compose-plugin 2>/dev/null || true
            ;;
        dnf|yum)
            dnf install -y docker-compose-plugin 2>/dev/null || \
            yum install -y docker-compose-plugin 2>/dev/null || true
            ;;
        *)
            local arch
            arch=$(detect_arch)
            mkdir -p /usr/local/lib/docker/cli-plugins
            curl -fsSL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-${arch}" \
                -o /usr/local/lib/docker/cli-plugins/docker-compose
            chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
            ;;
    esac

    if docker compose version &>/dev/null; then
        info "Docker Compose (Plugin v2) 安装完成 ✓"
    else
        # 兜底: 独立二进制
        warn "Plugin 安装失败，使用独立二进制..."
        local arch
        arch=$(detect_arch)
        curl -fsSL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-${arch}" \
            -o /usr/local/bin/docker-compose
        chmod +x /usr/local/bin/docker-compose
        if command_exists docker-compose; then
            info "docker-compose (独立版) 安装完成: $(docker-compose --version)"
        else
            error "Docker Compose 安装失败"
            exit 1
        fi
    fi
}

#-------------------------------------------------------------------------------
# 步骤 3: 下载官方 astrbot.yml 并启动
#
# 官方 compose 文件:
#   https://raw.githubusercontent.com/NapNeko/NapCat-Docker/main/compose/astrbot.yml
#
# 该文件内置了两个服务:
#   astrbot  — AI 聊天机器人核心 (:6185 WebUI, :6199 OneBot WS)
#   napcat   — QQ 协议适配器 (:6099 WebUI, :3000-3001 WS/HTTP)
#
# 两个容器在同一 compose 网络内, NapCat 可通过 ws://astrbot:6199/ws 直连
#-------------------------------------------------------------------------------
deploy_astrbot() {
    step "步骤 3/4: 部署 AstrBot + NapCat"

    # 询问部署目录
    echo ""
    read -p "请输入部署目录 (默认: ${ASTROBOT_DIR}): " user_dir
    ASTROBOT_DIR="${user_dir:-$ASTROBOT_DIR}"   # 覆写全局变量, 后续 guide 用到
    mkdir -p "$ASTROBOT_DIR"
    info "部署目录: $ASTROBOT_DIR"

    # 下载官方 astrbot.yml
    info "下载官方 astrbot.yml..."
    info "来源: $ASTROBOT_COMPOSE_URL"

    if wget -q --show-progress "$ASTROBOT_COMPOSE_URL" -O "${ASTROBOT_DIR}/astrbot.yml"; then
        info "下载完成 → ${ASTROBOT_DIR}/astrbot.yml"
    else
        info "wget 失败, 尝试 curl..."
        if curl -fsSL "$ASTROBOT_COMPOSE_URL" -o "${ASTROBOT_DIR}/astrbot.yml"; then
            info "下载完成 → ${ASTROBOT_DIR}/astrbot.yml"
        else
            error "无法下载官方 astrbot.yml, 请检查网络后手动执行:"
            error "  mkdir -p ${ASTROBOT_DIR}"
            error "  wget ${ASTROBOT_COMPOSE_URL} -O ${ASTROBOT_DIR}/astrbot.yml"
            error "  cd ${ASTROBOT_DIR} && sudo docker compose -f astrbot.yml up -d"
            return 0
        fi
    fi

    # 国内镜像加速
    if confirm "是否使用国内镜像加速 (DaoCloud 代理)？"; then
        info "替换镜像为国内代理..."
        sed -i 's|image: soulter/astrbot:latest|image: m.daocloud.io/docker.io/soulter/astrbot:latest|g' \
            "${ASTROBOT_DIR}/astrbot.yml" 2>/dev/null || true
        sed -i 's|image: mlikiowa/napcat-docker:latest|image: m.daocloud.io/docker.io/mlikiowa/napcat-docker:latest|g' \
            "${ASTROBOT_DIR}/astrbot.yml" 2>/dev/null || true
    fi

    # 拉取镜像并启动
    if ! confirm "是否立即拉取镜像并启动容器？"; then
        info "已跳过。稍后可手动执行:"
        info "  cd ${ASTROBOT_DIR} && sudo docker compose -f astrbot.yml up -d"
        return 0
    fi

    cd "$ASTROBOT_DIR"

    info "拉取镜像 (可能需要几分钟)..."
    docker compose -f astrbot.yml pull || {
        warn "镜像拉取失败，可能是 Docker Hub 连接问题"
        warn "国内服务器可尝试: 配置镜像加速 或 重跑脚本选择 DaoCloud 代理"
        warn "手动重试: cd ${ASTROBOT_DIR} && sudo docker compose -f astrbot.yml pull && sudo docker compose -f astrbot.yml up -d"
        return 0
    }

    info "启动容器..."
    docker compose -f astrbot.yml up -d
    info "AstrBot + NapCat 部署完成 ✓"
}

#-------------------------------------------------------------------------------
# 步骤 4: 状态检查
#-------------------------------------------------------------------------------
check_status() {
    step "步骤 4/4: 检查容器状态"

    echo ""
    if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "astrbot"; then
        info "AstrBot   ✓ 运行中"
    else
        warn "AstrBot   ✗ 未运行 (docker logs astrbot 查看日志)"
    fi

    if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "napcat"; then
        info "NapCat    ✓ 运行中"
    else
        warn "NapCat    ✗ 未运行 (docker logs napcat 查看日志)"
    fi

    echo ""
    docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || true
    echo ""
}

#-------------------------------------------------------------------------------
# 部署后指引
#-------------------------------------------------------------------------------
show_guide() {
    local server_ip
    server_ip=$(get_server_ip)

    echo ""
    echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BLUE}║${NC}                                                              ${BLUE}║${NC}"
    echo -e "${BLUE}║${NC}       ${GREEN}🎉 部署完成！请按以下步骤初始化${NC}                          ${BLUE}║${NC}"
    echo -e "${BLUE}║${NC}                                                              ${BLUE}║${NC}"
    echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"

    #--- NapCat ---
    echo ""
    echo -e "${YELLOW}━━━ ① NapCat: 获取 Token 并扫码登录 QQ ━━━${NC}"
    echo ""
    echo -e "  ${GREEN}docker logs napcat 2>&1 | grep -i 'token\|WebUiToken'${NC}"
    echo ""
    echo -e "  浏览器打开: ${GREEN}http://${server_ip}:6099/webui/${NC}"
    echo -e "  输入 Token → 手机 QQ 扫码 → 登录机器人 QQ 号"
    echo ""

    #--- WebSocket ---
    echo -e "${YELLOW}━━━ ② NapCat: 配置反向 WebSocket → AstrBot ━━━${NC}"
    echo ""
    echo -e "  NapCat WebUI → 网络配置 → 新建 → WebSocket 客户端:"
    echo -e "    URL:      ${GREEN}ws://astrbot:6199/ws${NC}"
    echo -e "    消息格式: ${GREEN}Array${NC}"
    echo -e "    心跳间隔: ${GREEN}5000${NC}"
    echo -e "    重连间隔: ${GREEN}5000${NC}"
    echo ""

    #--- AstrBot ---
    echo -e "${YELLOW}━━━ ③ AstrBot: 登录 WebUI 配置适配器 ━━━${NC}"
    echo ""
    echo -e "  ${GREEN}docker logs astrbot 2>&1 | grep -i password${NC}"
    echo ""
    echo -e "  浏览器打开: ${GREEN}http://${server_ip}:6185${NC}"
    echo -e "  用户名: ${GREEN}astrbot${NC}"
    echo -e "  密码: 上面命令输出的随机密码"
    echo ""
    echo -e "  → 机器人 → 创建 → OneBot v11 (QQ个人号)"
    echo -e "    反向 WS 主机: ${GREEN}0.0.0.0${NC}"
    echo -e "    反向 WS 端口: ${GREEN}6199${NC}"
    echo ""

    #--- AI ---
    echo -e "${YELLOW}━━━ ④ 接入 AI 模型 + 设置管理员 ━━━${NC}"
    echo ""
    echo -e "  模型提供商 → 新增 → 选择 DeepSeek:"
    echo -e "    API Key:     填入 DeepSeek 官网获取的 API Key"
    echo -e "    API Base:    ${GREEN}https://api.deepseek.com${NC}  (官方) 或用代理地址"
    echo -e "    模型:        ${GREEN}deepseek-chat${NC}  或  ${GREEN}deepseek-reasoner${NC}"
    echo -e "  配置 → 其他配置 → 管理员 ID → 填写你自己的 QQ 号"
    echo ""

    #--- 注意事项 ---
    echo -e "${YELLOW}━━━ ⚠️  注意事项 ━━━${NC}"
    echo ""
    echo -e "  防火墙放行端口: ${GREEN}6185 6099 6199 3000 3001${NC}"
    echo -e "  不要用常用大号跑机器人，建议用小号"
    echo -e "  新号/异地登录容易风控，建议用有等级的老号"
    echo ""

    echo -e "${YELLOW}━━━ 📋 常用命令 ━━━${NC}"
    echo ""
    echo -e "  ${GREEN}docker compose -f ${ASTROBOT_DIR}/astrbot.yml ps${NC}         # 查看状态"
    echo -e "  ${GREEN}docker compose -f ${ASTROBOT_DIR}/astrbot.yml logs -f${NC}    # 实时日志"
    echo -e "  ${GREEN}docker compose -f ${ASTROBOT_DIR}/astrbot.yml restart${NC}    # 重启"
    echo -e "  ${GREEN}docker compose -f ${ASTROBOT_DIR}/astrbot.yml down${NC}       # 停止"
    echo ""
}

#-------------------------------------------------------------------------------
# 主流程
#-------------------------------------------------------------------------------
main() {
    if [[ $EUID -ne 0 ]]; then
        error "请使用 sudo 运行: sudo ./deploy-astrbot-napcat-standalone.sh"
        exit 1
    fi

    echo ""
    echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BLUE}║${NC}                                                              ${BLUE}║${NC}"
    echo -e "${BLUE}║${NC}   ${GREEN}AstrBot + NapCat QQ 机器人 一键部署${NC}                        ${BLUE}║${NC}"
    echo -e "${BLUE}║${NC}   Docker → AstrBot + NapCat (官方 astrbot.yml)              ${BLUE}║${NC}"
    echo -e "${BLUE}║${NC}                                                              ${BLUE}║${NC}"
    echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""

    detect_os
    echo ""

    warn "本脚本将依次执行:"
    echo "  1. 安装 Docker Engine  (如未安装)"
    echo "  2. 安装 Docker Compose (如未安装)"
    echo "  3. 下载官方 astrbot.yml + 拉取镜像 + 启动 AstrBot + NapCat"
    echo "  4. 检查运行状态 + 输出配置指引"
    echo ""

    if ! confirm "是否开始部署？"; then
        info "已取消"
        exit 0
    fi

    install_docker
    install_docker_compose
    deploy_astrbot
    check_status
    show_guide
}

main
