#!/usr/bin/env bash
################################################################################
# OpenClaw + oGMemory 一键部署脚本
#
# 架构说明:
# 本脚本会启动三个容器(如果启用 openGauss):
# 1. openGauss 数据库容器(可选)
# 2. ogmemory 容器:独立的 oGMemory 服务(HTTP API,端口 8090)
# 3. openclaw-ogmemory 容器:OpenClaw Gateway(Web 界面,端口 18789)
#
# 用法:
#   1. 编辑 deploy.env 中的配置项
#   2. bash deploy.sh -password <密码>  — 部署(ENABLE_OPENGAUSS=true 时必须指定密码)
#   3. bash deploy.sh                   — 部署(ENABLE_OPENGAUSS=false 时无需密码)
#   4. bash deploy.sh --cleanup         — 清理所有已部署的容器
#   5. bash deploy.sh --status          — 查看部署状态
################################################################################
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/deploy.env"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

OG_PASSWORD=""
PARSED_ACTION=""
declare -a OPENCLAW_CONTAINER_NAMES=()
declare -a OPENCLAW_INSTANCE_DESCRIPTIONS=()

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

check_command() {
    if ! command -v "$1" &>/dev/null; then
        log_error "未找到命令: $1,请先安装后再运行此脚本"
        exit 1
    fi
}

validate_password() {
    local pwd="$1"
    local categories=0

    if [[ ${#pwd} -lt 8 ]]; then
        log_error "密码长度不足 8 个字符"
        return 1
    fi

    [[ "$pwd" =~ [A-Z] ]] && (( categories += 1 ))
    [[ "$pwd" =~ [a-z] ]] && (( categories += 1 ))
    [[ "$pwd" =~ [0-9] ]] && (( categories += 1 ))
    [[ "$pwd" =~ [\#\?\!\@\$\%\^\&\*] ]] && (( categories += 1 ))

    if (( categories < 3 )); then
        log_error "密码复杂度不够:必须包含大写字母、小写字母、数字、特殊符号(#?!@\$%^&*)中的至少三种"
        return 1
    fi

    return 0
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -password)
                if [[ -z "${2:-}" ]]; then
                    log_error "-password 参数需要指定密码值"
                    exit 1
                fi
                OG_PASSWORD="$2"
                shift 2
                ;;
            --cleanup|--status)
                PARSED_ACTION="$1"
                shift
                ;;
            *)
                log_error "未知参数: $1"
                echo "用法: bash deploy.sh [-password <密码>] [--cleanup|--status]"
                exit 1
                ;;
        esac
    done
}

append_openclaw_instance() {
    local instance_name="$1"
    local gateway_port="$2"
    local gateway_token="$3"
    local auth_api_key="$4"
    local auth_account_id="$5"
    local home_dir="$6"

    OPENCLAW_CONTAINER_NAMES+=("$instance_name")
    OPENCLAW_INSTANCE_DESCRIPTIONS+=(
        "${instance_name}|${gateway_port}|${gateway_token}|${auth_api_key}|${auth_account_id}|${home_dir}"
    )
}

container_exists() {
    local name="$1"
    docker ps -a --format '{{.Names}}' 2>/dev/null | grep -Fxq "${name}"
}

container_is_running() {
    local name="$1"
    docker ps --format '{{.Names}}' 2>/dev/null | grep -Fxq "${name}"
}

get_target_container_names() {
    local names=("${OGMEM_CONTAINER_NAME}")
    local name

    if [[ "${ENABLE_OPENGAUSS}" == "true" ]]; then
        names=("${OG_CONTAINER_NAME}" "${names[@]}")
    fi

    for name in "${OPENCLAW_CONTAINER_NAMES[@]}"; do
        names+=("${name}")
    done

    printf '%s\n' "${names[@]}"
}

build_openclaw_instances() {
    OPENCLAW_CONTAINER_NAMES=()
    OPENCLAW_INSTANCE_DESCRIPTIONS=()

    if [[ -n "${OPENCLAW_INSTANCES:-}" ]]; then
        local raw_instance instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir
        IFS=';' read -r -a raw_instances <<< "${OPENCLAW_INSTANCES}"

        for raw_instance in "${raw_instances[@]}"; do
            [[ -z "${raw_instance//[[:space:]]/}" ]] && continue

            IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${raw_instance}"

            instance_name="$(echo "${instance_name:-}" | xargs)"
            gateway_port="$(echo "${gateway_port:-}" | xargs)"
            gateway_token="$(echo "${gateway_token:-}" | xargs)"
            auth_api_key="$(echo "${auth_api_key:-}" | xargs)"
            auth_account_id="$(echo "${auth_account_id:-}" | xargs)"
            home_dir="$(echo "${home_dir:-}" | xargs)"

            if [[ -z "${instance_name}" || -z "${gateway_port}" || -z "${gateway_token}" || -z "${auth_api_key}" || -z "${auth_account_id}" ]]; then
                log_error "OPENCLAW_INSTANCES 格式错误: ${raw_instance}"
                log_error "期望格式: container_name|gateway_port|gateway_token|auth_api_key|auth_account_id|openclaw_home_dir"
                exit 1
            fi

            append_openclaw_instance "${instance_name}" "${gateway_port}" "${gateway_token}" "${auth_api_key}" "${auth_account_id}" "${home_dir}"
        done
    else
        append_openclaw_instance \
            "${OPENCLAW_CONTAINER_NAME}" \
            "${GATEWAY_PORT}" \
            "${OPENCLAW_GATEWAY_TOKEN}" \
            "${OG_AUTH_API_KEY:-${OG_ROOT_API_KEY:-}}" \
            "${OG_AUTH_ACCOUNT_ID:-${OG_ACCOUNT_ID:-}}" \
            "${OPENCLAW_HOME_DIR}"
    fi

    if [[ ${#OPENCLAW_CONTAINER_NAMES[@]} -eq 0 ]]; then
        log_error "未找到 OpenClaw 实例配置"
        exit 1
    fi
}

load_config() {
    if [[ ! -f "$ENV_FILE" ]]; then
        log_error "配置文件不存在: $ENV_FILE"
        log_error "请先复制并编辑 deploy.env 文件"
        exit 1
    fi

    set -a
    # shellcheck source=/dev/null
    source "$ENV_FILE"
    set +a

    GATEWAY_PORT="${GATEWAY_PORT:-18789}"
    OPENCLAW_GATEWAY_TOKEN="${OPENCLAW_GATEWAY_TOKEN:-ogmem-default-token}"
    OPENCLAW_BIND_MODE="${OPENCLAW_BIND_MODE:-lan}"
    OGMEM_URL="${OGMEM_URL:-http://127.0.0.1:8090}"
    OG_AUTH_API_KEY="${OG_AUTH_API_KEY:-}"
    OG_AUTH_ACCOUNT_ID="${OG_AUTH_ACCOUNT_ID:-}"

    OGMEM_HTTP_PORT="${OGMEM_HTTP_PORT:-8090}"
    AGFS_DATA_DIR="${AGFS_DATA_DIR:-}"
    OG_ROOT_API_KEY="${OG_ROOT_API_KEY:-}"
    OG_ACCOUNT_ID="${OG_ACCOUNT_ID:-}"

    OG_IMAGE_REPO="${OG_IMAGE_REPO:-swr.cn-north-4.myhuaweicloud.com/kunpeng-ai/opengauss-distributed}"
    OG_IMAGE_TAG="${OG_IMAGE_TAG:-0328}"
    OG_IMAGE="${OG_IMAGE_REPO}:${OG_IMAGE_TAG}"
    OG_CONTAINER_NAME="${OG_CONTAINER_NAME:-opengauss}"
    OG_NODE_NAME="${OG_NODE_NAME:-gaussdb}"
    OG_USERNAME="${OG_USERNAME:-gaussdb}"
    OG_DB_NAME="${OG_DB_NAME:-postgres}"
    OG_PORT="${OG_PORT:-5432}"
    OG_CPUSET_CPUS="${OG_CPUSET_CPUS:-}"
    OG_WAIT_TIMEOUT="${OG_WAIT_TIMEOUT:-120}"

    OGMEM_CONTAINER_NAME="${OGMEM_CONTAINER_NAME:-ogmem}"
    OGMEM_IMAGE="${OGMEM_IMAGE:-swr.cn-north-4.myhuaweicloud.com/kunpeng-ai/ogmemory:v0.8}"

    OPENCLAW_CONTAINER_NAME="${OPENCLAW_CONTAINER_NAME:-openclaw_ogmem}"
    OPENCLAW_IMAGE="${OPENCLAW_IMAGE:-swr.cn-north-4.myhuaweicloud.com/kunpeng-ai/openclaw-ogmemory:v0.2}"
    OPENCLAW_HOME_DIR="${OPENCLAW_HOME_DIR:-}"
    OPENCLAW_INSTANCES="${OPENCLAW_INSTANCES:-}"

    OGMEM_IMAGE="$(echo "${OGMEM_IMAGE}" | xargs)"
    OPENCLAW_IMAGE="$(echo "${OPENCLAW_IMAGE}" | xargs)"

    ENABLE_OPENGAUSS="${ENABLE_OPENGAUSS:-true}"
    AUTO_HEALTH_CHECK="${AUTO_HEALTH_CHECK:-true}"
    SKIP_PULL="${SKIP_PULL:-false}"

    build_openclaw_instances

    log_info "OpenClaw Gateway 配置: provider=${LLM_PROVIDER:-}, model=${LLM_MODEL:-}, port=${GATEWAY_PORT}"
    log_info "oGMemory 服务配置: port=${OGMEM_HTTP_PORT}, yaml=${SCRIPT_DIR}/ogmemory.yaml"
    log_info "openGauss 镜像: ${OG_IMAGE}"
    log_info "ogmemory 镜像: ${OGMEM_IMAGE}"
    log_info "openclaw-ogmemory 镜像: ${OPENCLAW_IMAGE}"
    log_info "OpenClaw 实例数: ${#OPENCLAW_CONTAINER_NAMES[@]}"
}

validate_required_config() {
    local required_vars=(
        OPENGAUSS_HOST_IP
        OPENCLAW_HOST_IP
        OG_HOST_PORT
        LLM_PROVIDER
        LLM_API_KEY
        LLM_BASE_URL
        LLM_MODEL
    )
    local var
    for var in "${required_vars[@]}"; do
        if [[ -z "${!var:-}" || "${!var}" == your_* ]]; then
            log_error "必填配置项 $var 未设置或仍为模板值,请在 deploy.env 中修改"
            exit 1
        fi
    done

    if [[ ! -f "${SCRIPT_DIR}/ogmemory.yaml" ]]; then
        if [[ -f "${SCRIPT_DIR}/ogmemory.example.yaml" ]]; then
            log_warn "oG-Memory 配置文件不存在: ${SCRIPT_DIR}/ogmemory.yaml"
            log_warn "自动从模板复制: cp ${SCRIPT_DIR}/ogmemory.example.yaml ${SCRIPT_DIR}/ogmemory.yaml"
            log_warn "如需自定义 LLM/Embedding/向量库等配置,请部署后编辑 ${SCRIPT_DIR}/ogmemory.yaml 并重启容器"
            cp "${SCRIPT_DIR}/ogmemory.example.yaml" "${SCRIPT_DIR}/ogmemory.yaml"
        else
            log_error "oG-Memory 配置文件不存在: ${SCRIPT_DIR}/ogmemory.yaml"
            log_error "模板也未找到: ${SCRIPT_DIR}/ogmemory.example.yaml"
            log_error "请重新运行 install.sh 或手动从仓库下载模板"
            exit 1
        fi
    fi

    if [[ -z "${OPENCLAW_INSTANCES:-}" ]]; then
        local role_control_enabled=""
        role_control_enabled="$(python3 -c "import yaml; d=yaml.safe_load(open('${SCRIPT_DIR}/ogmemory.yaml')); print(str(bool(d.get('auth',{}).get('role_control_enabled', False))).lower())" 2>/dev/null || true)"
        if [[ "${role_control_enabled}" == "true" ]]; then
            if [[ -z "${OG_AUTH_API_KEY:-${OG_ROOT_API_KEY:-}}" ]]; then
                log_error "检测到 ogmemory.yaml 已启用多租认证(auth.role_control_enabled=true),但 deploy.env 中未设置 OG_AUTH_API_KEY 或 OG_ROOT_API_KEY"
                log_error "请在 deploy.env 中显式配置 OpenClaw 访问 oGMemory 使用的认证 Key"
                exit 1
            fi
            if [[ -z "${OG_AUTH_ACCOUNT_ID:-${OG_ACCOUNT_ID:-}}" ]]; then
                log_error "检测到 ogmemory.yaml 已启用多租认证(auth.role_control_enabled=true),但 deploy.env 中未设置 OG_AUTH_ACCOUNT_ID 或 OG_ACCOUNT_ID"
                log_error "请在 deploy.env 中显式配置 OpenClaw 默认访问的 account_id"
                exit 1
            fi
        fi
    fi
}

preflight_check() {
    log_step "前置检查"
    check_command docker

    if ! docker info &>/dev/null; then
        log_error "Docker 服务未运行或当前用户无权限"
        exit 1
    fi
    log_info "Docker 环境正常"

    if ! command -v curl &>/dev/null; then
        log_warn "未找到 curl 命令,健康检查将不可用"
    fi
}

pull_images() {
    if [[ "${SKIP_PULL}" == "true" ]]; then
        log_info "已跳过镜像拉取(SKIP_PULL=true)"
        return
    fi

    log_step "拉取 Docker 镜像"

    if [[ "${ENABLE_OPENGAUSS}" == "true" ]]; then
        log_info "拉取 openGauss 镜像: ${OG_IMAGE}"
        docker pull "${OG_IMAGE}"
    fi

    log_info "拉取 ogmemory 镜像: ${OGMEM_IMAGE}"
    docker pull "${OGMEM_IMAGE}"

    log_info "拉取 openclaw-ogmemory 镜像: ${OPENCLAW_IMAGE}"
    docker pull "${OPENCLAW_IMAGE}"
}

deploy_opengauss() {
    log_step "部署 openGauss 数据库"

    if docker ps -a --format '{{.Names}}' | grep -q "^${OG_CONTAINER_NAME}$"; then
        log_warn "容器 ${OG_CONTAINER_NAME} 已存在"
        if docker ps --format '{{.Names}}' | grep -q "^${OG_CONTAINER_NAME}$"; then
            log_info "容器正在运行,跳过创建"
            return
        fi
        log_info "容器已停止,尝试启动..."
        docker start "${OG_CONTAINER_NAME}"
        return
    fi

    local docker_run_args=(
        docker run --name "${OG_CONTAINER_NAME}" --privileged=true -d
        --label ogmem.managed=true
        -e "GS_PASSWORD=${OG_PASSWORD}"
        -e "GS_USER_PASSWORD=${OG_PASSWORD}"
        -p "${OG_HOST_PORT}:${OG_PORT}"
    )

    [[ "${OG_NODE_NAME}" != "gaussdb" ]] && docker_run_args+=(-e "GS_NODENAME=${OG_NODE_NAME}")
    [[ "${OG_USERNAME}" != "gaussdb" ]] && docker_run_args+=(-e "GS_USERNAME=${OG_USERNAME}")
    [[ "${OG_PORT}" != "5432" ]] && docker_run_args+=(-e "GS_PORT=${OG_PORT}")
    [[ "${OG_DB_NAME}" != "postgres" ]] && docker_run_args+=(-e "GS_DB=${OG_DB_NAME}")
    [[ -n "${OG_CPUSET_CPUS}" ]] && docker_run_args+=(--cpuset-cpus="${OG_CPUSET_CPUS}")

    docker_run_args+=("${OG_IMAGE}")

    log_info "启动 openGauss 容器..."
    "${docker_run_args[@]}"
    log_info "openGauss 容器已启动"
}

wait_opengauss_ready() {
    log_info "等待 openGauss 就绪(最多 ${OG_WAIT_TIMEOUT} 秒)..."
    local elapsed=0
    local interval=3

    while (( elapsed < OG_WAIT_TIMEOUT )); do
        if docker exec "${OG_CONTAINER_NAME}" su - omm -c "gsql -d ${OG_DB_NAME} -p ${OG_PORT} -c 'SELECT 1;'" &>/dev/null; then
            log_info "openGauss 已就绪(耗时 ${elapsed} 秒)"
            return 0
        fi
        if (( elapsed > 0 && elapsed % 15 == 0 )); then
            log_warn "已等待 ${elapsed} 秒,数据库仍未就绪..."
            log_warn "可手动测试: docker exec ${OG_CONTAINER_NAME} su - omm -c \"gsql -d ${OG_DB_NAME} -p ${OG_PORT} -c 'SELECT 1;'\""
        fi
        sleep "${interval}"
        elapsed=$(( elapsed + interval ))
    done

    log_error "openGauss 在 ${OG_WAIT_TIMEOUT} 秒内未就绪"
    log_error "请手动检查:"
    log_error "  docker logs ${OG_CONTAINER_NAME}"
    log_error "  docker exec ${OG_CONTAINER_NAME} su - omm -c \"gsql -l\""
    exit 1
}

deploy_ogmem() {
    log_step "部署 oGMemory 服务"

    if docker ps -a --format '{{.Names}}' | grep -q "^${OGMEM_CONTAINER_NAME}$"; then
        log_warn "容器 ${OGMEM_CONTAINER_NAME} 已存在"
        if docker ps --format '{{.Names}}' | grep -q "^${OGMEM_CONTAINER_NAME}$"; then
            log_info "容器正在运行,跳过创建"
            return
        fi
        log_info "容器已停止,尝试启动..."
        docker start "${OGMEM_CONTAINER_NAME}"
        return
    fi

    local yaml_path="${SCRIPT_DIR}/ogmemory.yaml"
    if [[ ! -f "${yaml_path}" ]]; then
        if [[ -f "${SCRIPT_DIR}/ogmemory.example.yaml" ]]; then
            log_warn "配置文件不存在: ${yaml_path},自动从模板复制"
            cp "${SCRIPT_DIR}/ogmemory.example.yaml" "${yaml_path}"
        else
            log_error "配置文件不存在: ${yaml_path}"
            log_error "模板 ogmemory.example.yaml 也未找到,请重新运行 install.sh"
            exit 1
        fi
    fi

    local docker_run_args=(
        docker run -d --name "${OGMEM_CONTAINER_NAME}"
        --network host
        --label ogmem.managed=true
        -v "${yaml_path}:/etc/ogmem/config.yaml:ro"
    )

    if [[ -n "${AGFS_DATA_DIR}" ]]; then
        mkdir -p "${AGFS_DATA_DIR}"
        chmod 777 "${AGFS_DATA_DIR}"
        docker_run_args+=(-v "${AGFS_DATA_DIR}:/data/agfs")
        log_info "挂载 AGFS 数据目录: ${AGFS_DATA_DIR}"
    fi

    if [[ -n "${PERF_LOGS_HOST_DIR:-}" ]]; then
        mkdir -p "${PERF_LOGS_HOST_DIR}"
        chmod 755 "${PERF_LOGS_HOST_DIR}"
        docker_run_args+=(-v "${PERF_LOGS_HOST_DIR}:/opt/ogmem/perf_logs")
        log_info "挂载 perf 日志目录: ${PERF_LOGS_HOST_DIR} -> /opt/ogmem/perf_logs"
    fi

    if [[ "${ENABLE_OPENGAUSS}" == "true" ]]; then
        docker_run_args+=(-e "OPENGAUSS_HOST=${OPENGAUSS_HOST_IP}")
        docker_run_args+=(-e "OPENGAUSS_PORT=${OG_HOST_PORT}")
        docker_run_args+=(-e "OPENGAUSS_DBNAME=${OG_DB_NAME}")
        docker_run_args+=(-e "OPENGAUSS_USER=${OG_USERNAME}")
        docker_run_args+=(-e "OPENGAUSS_PASSWORD=${OG_PASSWORD}")
        log_info "openGauss 连接信息已通过环境变量传入: ${OPENGAUSS_HOST_IP}:${OG_HOST_PORT}/${OG_DB_NAME}"
    fi

    local env_vars_for_yaml=(
        "LLM_PROVIDER"
        "LLM_API_KEY"
        "LLM_BASE_URL"
        "LLM_MODEL"
        "OGMEM_HTTP_PORT"
        "OGMEM_WORKERS"
        "OGMEM_GUNICORN_TIMEOUT"
        "OG_ACCOUNT_ID"
        "OG_USER_ID"
        "OG_AGENT_ID"
        "OG_ROLE_CONTROL_ENABLED"
        "OG_ROOT_API_KEY"
        "OG_ADMIN_API_KEYS"
        "OG_AGENT_SHARED_MODE"
        "OG_AGENT_SHARED_LIST"
        "OG_HTTP_IP_ALLOWLIST"
        "OG_HTTP_IP_ALLOWLIST_TRUST_PROXY"
        "OG_HTTP_TRUSTED_PROXIES"
        "INDEX_INTERVAL"
        "INDEX_WORKERS"
    )
    for var in "${env_vars_for_yaml[@]}"; do
        if [[ -n "${!var:-}" ]]; then
            docker_run_args+=(-e "${var}=${!var}")
        fi
    done

    # Pass perf monitoring vars through when set in deploy.env
    local perf_vars=("OGMEM_PERF_ENABLED" "OGMEM_PERF_OUT" "OGMEM_PERF_HTTP_URL" "OGMEM_PERF_RUN_ID")
    for var in "${perf_vars[@]}"; do
        if [[ -n "${!var:-}" ]]; then
            docker_run_args+=(-e "${var}=${!var}")
        fi
    done

    docker_run_args+=(-e "no_proxy=*")
    docker_run_args+=(-e "NO_PROXY=*")
    docker_run_args+=("${OGMEM_IMAGE}")

    log_info "启动 ogmemory 容器(配置通过 YAML 文件传入)..."
    "${docker_run_args[@]}"
    log_info "ogmemory 容器已启动"
}

deploy_openclaw_instance() {
    local instance_name="$1"
    local gateway_port="$2"
    local gateway_token="$3"
    local auth_api_key="$4"
    local auth_account_id="$5"
    local home_dir="$6"

    if docker ps -a --format '{{.Names}}' | grep -q "^${instance_name}$"; then
        log_warn "容器 ${instance_name} 已存在"
        if docker ps --format '{{.Names}}' | grep -q "^${instance_name}$"; then
            log_info "容器正在运行,跳过创建"
            return
        fi
        log_info "容器已停止,尝试启动..."
        docker start "${instance_name}"
        return
    fi

    local docker_run_args=(
        docker run -d --name "${instance_name}"
        --network host
        --label ogmem.managed=true
    )

    if [[ -n "${home_dir}" ]]; then
        mkdir -p "${home_dir}"
        chmod 777 "${home_dir}"
        docker_run_args+=(-v "${home_dir}:/home/node/.openclaw")
        log_info "挂载 OpenClaw 状态目录: ${home_dir}"
    fi

    docker_run_args+=(
        -e "LLM_PROVIDER=${LLM_PROVIDER}"
        -e "LLM_API_KEY=${LLM_API_KEY}"
        -e "LLM_BASE_URL=${LLM_BASE_URL}"
        -e "LLM_MODEL=${LLM_MODEL}"
        -e "GATEWAY_PORT=${gateway_port}"
        -e "OGMEM_URL=${OGMEM_URL}"
        -e "OG_AUTH_API_KEY=${auth_api_key}"
        -e "OG_AUTH_ACCOUNT_ID=${auth_account_id}"
        -e "OPENCLAW_GATEWAY_TOKEN=${gateway_token}"
    )

    [[ -n "${OPENCLAW_BIND_MODE:-}" ]] && docker_run_args+=(-e "OPENCLAW_BIND_MODE=${OPENCLAW_BIND_MODE}")
    docker_run_args+=(-e "no_proxy=*")
    docker_run_args+=(-e "NO_PROXY=*")
    docker_run_args+=("${OPENCLAW_IMAGE}")

    log_info "启动 openclaw-ogmemory 容器..."
    "${docker_run_args[@]}"
    log_info "openclaw-ogmemory 容器已启动: ${instance_name} -> account=${auth_account_id}, port=${gateway_port}"
}

deploy_openclaw() {
    log_step "部署 OpenClaw Gateway 服务"
    local spec instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir
    for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
        IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
        deploy_openclaw_instance "${instance_name}" "${gateway_port}" "${gateway_token}" "${auth_api_key}" "${auth_account_id}" "${home_dir}"
    done
}

print_container_table() {
    local docker_ps_args=(docker ps --filter "name=${OG_CONTAINER_NAME}" --filter "name=${OGMEM_CONTAINER_NAME}")
    local name
    for name in "${OPENCLAW_CONTAINER_NAMES[@]}"; do
        docker_ps_args+=(--filter "name=${name}")
    done
    docker_ps_args+=(--format "table {{.Names}}\t{{.Status}}\t{{.Ports}}")
    "${docker_ps_args[@]}" 2>/dev/null || true
}

cleanup_current_env() {
    log_step "Cleanup containers for current deploy.env"

    local name found_any=false
    while IFS= read -r name; do
        [[ -z "${name}" ]] && continue
        if container_exists "${name}"; then
            found_any=true
            log_info "Removing container: ${name}"
            docker rm -f "${name}"
        else
            log_info "Skip missing container from current deploy.env: ${name}"
        fi
    done < <(get_target_container_names)

    if [[ "${found_any}" != "true" ]]; then
        log_warn "No containers defined by current deploy.env were found"
    fi

    log_info "Cleanup finished"
}

show_status_current_env() {
    log_step "Status for current deploy.env"

    local name found_any=false
    while IFS= read -r name; do
        [[ -z "${name}" ]] && continue
        if container_exists "${name}"; then
            found_any=true
        fi

        if container_is_running "${name}"; then
            log_info "${name}: running"
        elif container_exists "${name}"; then
            log_warn "${name}: stopped"
        else
            log_warn "${name}: not found"
        fi
    done < <(get_target_container_names)

    if [[ "${found_any}" != "true" ]]; then
        log_warn "No containers defined by current deploy.env were found"
        return
    fi

    echo ""
    print_container_table

    if command -v curl &>/dev/null; then
        echo ""
        log_info "Health checks"
        if container_is_running "${OGMEM_CONTAINER_NAME}"; then
            log_info "oGMemory: $(curl -sf "http://127.0.0.1:${OGMEM_HTTP_PORT}/api/v1/health" 2>/dev/null || echo "unreachable")"
        fi
        local spec instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir
        for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
            IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
            if container_is_running "${instance_name}"; then
                log_info "OpenClaw ${instance_name}: $(curl -sf "http://127.0.0.1:${gateway_port}/health" 2>/dev/null || echo "unreachable")"
            fi
        done
    fi
}

health_check() {
    if [[ "${AUTO_HEALTH_CHECK}" != "true" ]]; then
        return
    fi

    log_step "服务健康检查"

    local elapsed=0
    local max_wait=30
    local interval=3

    log_info "等待 oGMemory 服务就绪..."
    while (( elapsed < max_wait )); do
        if curl -sf "http://127.0.0.1:${OGMEM_HTTP_PORT}/api/v1/health" &>/dev/null 2>&1; then
            log_info "oGMemory 健康检查通过"
            break
        fi
        sleep "${interval}"
        elapsed=$(( elapsed + interval ))
    done

    if (( elapsed >= max_wait )); then
        log_warn "oGMemory 健康检查未在 ${max_wait} 秒内通过,请手动确认:"
        log_warn "  curl http://${OPENCLAW_HOST_IP}:${OGMEM_HTTP_PORT}/api/v1/health"
        log_warn "  docker logs ${OGMEM_CONTAINER_NAME}"
    fi

    local spec instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir
    for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
        IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
        log_info "等待 OpenClaw 服务就绪: ${instance_name}..."
        elapsed=0
        while (( elapsed < max_wait )); do
            if curl -sf "http://127.0.0.1:${gateway_port}/health" &>/dev/null 2>&1; then
                log_info "OpenClaw 健康检查通过: ${instance_name}"
                break
            fi
            sleep "${interval}"
            elapsed=$(( elapsed + interval ))
        done
        if (( elapsed >= max_wait )); then
            log_warn "OpenClaw 健康检查未在 ${max_wait} 秒内通过: ${instance_name},请手动确认:"
            log_warn "  curl http://${OPENCLAW_HOST_IP}:${gateway_port}/health"
            log_warn "  docker logs ${instance_name}"
        fi
    done

    echo ""
    log_info "容器运行状态:"
    print_container_table
}

cleanup() {
    cleanup_current_env
    return

    log_step "清理部署的容器"

    local name found_any=false
    while IFS= read -r name; do
        [[ -z "${name}" ]] && continue
        log_info "停止并删除容器: ${name}"
        if container_exists "${name}"; then
            found_any=true
            log_info "Removing container: ${name}"
            docker rm -f "${name}"
        else
            log_info "Skip missing container from current deploy.env: ${name}"
        fi
    done < <(get_target_container_names)

    log_info "清理完成"
    if [[ "${found_any}" != "true" ]]; then
        log_warn "No containers defined by current deploy.env were found"
    fi

    log_info "Cleanup finished"
}

show_status() {
    show_status_current_env
    return

    log_step "部署状态"

    local name found_any=false

    if [[ -z "${managed}" ]]; then
        log_warn "未发现由本脚本管理的容器"
        return
    fi

    while IFS= read -r name; do
        [[ -z "${name}" ]] && continue
        if docker ps --format '{{.Names}}' | grep -q "^${name}$"; then
            log_info "${name}: 运行中"
        else
            log_warn "${name}: 已停止"
        fi
    done <<< "${managed}"

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

    if command -v curl &>/dev/null; then
        echo ""
        log_info "服务健康检查:"
        log_info "oGMemory: $(curl -sf "http://127.0.0.1:${OGMEM_HTTP_PORT}/api/v1/health" 2>/dev/null || echo "未响应")"
        local spec instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir
        for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
            IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
            log_info "OpenClaw ${instance_name}: $(curl -sf "http://127.0.0.1:${gateway_port}/health" 2>/dev/null || echo "未响应")"
        done
    fi
}

print_summary() {
    log_step "部署完成"

    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║                  部署成功!                                  ║${NC}"
    echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    echo -e "${GREEN}容器列表:${NC}"
    echo -e "  - openGauss: ${OG_CONTAINER_NAME} (端口: ${OG_HOST_PORT})"
    echo -e "  - oGMemory: ${OGMEM_CONTAINER_NAME} (端口: ${OGMEM_HTTP_PORT})"
    local spec instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir idx=1
    for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
        IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
        echo -e "  - OpenClaw #${idx}: ${instance_name} (端口: ${gateway_port}, 账户: ${auth_account_id})"
        idx=$(( idx + 1 ))
    done
    echo ""
    echo -e "${GREEN}访问地址:${NC}"
    echo -e "  oGMemory API:  http://${OPENCLAW_HOST_IP}:${OGMEM_HTTP_PORT}"
    for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
        IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
        echo -e "  OpenClaw Web:   http://${OPENCLAW_HOST_IP}:${gateway_port}  (token: ${gateway_token})"
    done
    echo ""
    echo -e "${GREEN}首次访问:${NC}"
    echo -e "  1. 浏览器打开上述地址"
    echo -e "  2. 输入 Gateway Token"
    echo -e "  3. 配对成功后即可使用"
    echo ""
    echo -e "${GREEN}常用命令:${NC}"
    echo -e "  查看 oGMemory 日志:  docker logs ${OGMEM_CONTAINER_NAME} -f"
    for spec in "${OPENCLAW_INSTANCE_DESCRIPTIONS[@]}"; do
        IFS='|' read -r instance_name gateway_port gateway_token auth_api_key auth_account_id home_dir <<< "${spec}"
        echo -e "  查看 OpenClaw 日志:   docker logs ${instance_name} -f"
    done
    echo -e "  重启所有服务:         docker restart ${OGMEM_CONTAINER_NAME} ${OPENCLAW_CONTAINER_NAMES[*]}"
    echo -e "  进入 oGMemory 容器:  docker exec -it ${OGMEM_CONTAINER_NAME} bash"
    echo ""
}

main() {
    parse_args "$@"

    echo -e "${CYAN}"
    echo "╔══════════════════════════════════════════════════════════════╗"
    echo "║        OpenClaw + oGMemory 一键部署脚本                    ║"
    echo "╚══════════════════════════════════════════════════════════════╝"
    echo -e "${NC}"

    load_config
    preflight_check

    case "${PARSED_ACTION}" in
        --cleanup)
            cleanup_current_env
            return
            ;;
        --status)
            show_status_current_env
            return
            ;;
    esac

    validate_required_config

    if [[ "${ENABLE_OPENGAUSS}" == "true" ]]; then
        if [[ -z "${OG_PASSWORD}" ]]; then
            log_error "启用 openGauss 时必须通过 -password 参数指定数据库密码"
            echo "用法: bash deploy.sh -password <密码>"
            echo ""
            echo "密码要求:"
            echo "  - 长度至少 8 个字符"
            echo "  - 包含大写字母、小写字母、数字、特殊符号(#?!@\$%^&*)中的至少三种"
            exit 1
        fi
        if ! validate_password "${OG_PASSWORD}"; then
            exit 1
        fi
        log_info "密码复杂度校验通过"
        log_info "部署模式: openGauss + ogmemory + openclaw-ogmemory"
    else
        log_info "部署模式: ogmemory + openclaw-ogmemory(ENABLE_OPENGAUSS=false)"
    fi

    pull_images

    if [[ "${ENABLE_OPENGAUSS}" == "true" ]]; then
        deploy_opengauss
        wait_opengauss_ready
    fi

    deploy_ogmem
    deploy_openclaw
    health_check
    print_summary
}

main "$@"