#!/usr/bin/env bash
# ════════════════════════════════════════════════════════════
# deploy_domain.sh — One-click deploy a new QA domain instance.
#
# Canonical location: /home/67/agentexample/qaagent67lambda/scripts/
#
# Usage:
#   ./deploy_domain.sh <domain>            # e.g. maritime, finance, customs
#   ./deploy_domain.sh <domain> --rebuild  # stop+remove existing, recreate
#
# Convention (everything is read from instance.yml — no other config needed):
#
#   /home/67/knowledge/<domain>/
#       ├── instance.yml          ← required, must have a `demo:` section
#       ├── rag_index.json        ← required (BM25 index)
#       ├── rag_vectors_v2.npy    ← required (vector index)
#       ├── search_unified.py     ← required (search module)
#       └── config.py             ← required (path resolver)
#
#   instance.yml MUST contain:
#       agent: <template-name>     # e.g. qaagent67lambda
#       knowledge:
#         baseDir: /home/67/knowledge/<domain>
#       demo:
#         title: ...
#         tagline: ...
#         placeholder: ...
#         domain: <domain>
#         port: <NNNN>            # unique per instance
#         bind: 127.0.0.1         # optional (default 0.0.0.0); use 127.0.0.1 + nginx in front
#         examples: [{q,label}, ...]
# ════════════════════════════════════════════════════════════
set -euo pipefail

DOMAIN="${1:-}"
REBUILD="${2:-}"

if [ -z "$DOMAIN" ]; then
    echo "usage: $0 <domain> [--rebuild]" >&2
    exit 1
fi

KNOW_DIR="/home/67/knowledge/$DOMAIN"
INSTANCE_YML="$KNOW_DIR/instance.yml"
APP_PY="/home/67/agentexample/qaagent67lambda/scripts/app.py"
IMAGE="lambdagentpaas:latest"
CONTAINER="${DOMAIN}-qa"

# ── 1. Pre-flight checks ─────────────────────────────────────
echo "[1/6] Validating $KNOW_DIR ..."
[ -d "$KNOW_DIR" ]                   || { echo "ERROR: $KNOW_DIR does not exist"; exit 2; }
[ -f "$INSTANCE_YML" ]               || { echo "ERROR: $INSTANCE_YML missing"; exit 2; }
[ -f "$KNOW_DIR/rag_index.json" ]    || { echo "ERROR: rag_index.json missing"; exit 2; }
[ -f "$KNOW_DIR/search_unified.py" ] || { echo "ERROR: search_unified.py missing"; exit 2; }
[ -f "$KNOW_DIR/config.py" ]         || { echo "ERROR: config.py missing"; exit 2; }
[ -f "$APP_PY" ]                     || { echo "ERROR: $APP_PY missing"; exit 2; }

# ── 2. Read demo.port + demo.bind + agent template from instance.yml ────
echo "[2/6] Parsing $INSTANCE_YML ..."
read AGENT_TEMPLATE PORT BIND << EOF
$(python3 -c "
import yaml
with open('$INSTANCE_YML') as f:
    cfg = yaml.safe_load(f)
agent = cfg.get('agent') or 'qaagent67lambda'
demo = cfg.get('demo') or {}
port = demo.get('port')
if not port:
    raise SystemExit('ERROR: instance.yml has no demo.port')
bind = demo.get('bind') or '0.0.0.0'
print(agent, port, bind)
")
EOF
AGENT_CFG="/home/67/agentexample/$AGENT_TEMPLATE/agent-config.yml"
[ -f "$AGENT_CFG" ] || { echo "ERROR: agent template config $AGENT_CFG missing"; exit 2; }
echo "       agent template: $AGENT_TEMPLATE"
echo "       port:           $PORT"
echo "       bind:           $BIND"
echo "       agent-config:   $AGENT_CFG"

# ── 3. Port conflict check ──────────────────────────────────
echo "[3/6] Checking port $PORT availability ..."
if ss -tlnp 2>/dev/null | grep -q ":$PORT "; then
    OWNER=$(ss -tlnp 2>/dev/null | grep ":$PORT " | head -1)
    if [ "$REBUILD" != "--rebuild" ] && ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
        echo "ERROR: port $PORT in use by another process: $OWNER"
        echo "       (and no existing $CONTAINER container to replace)"
        exit 3
    fi
fi

# ── 4. Stop + remove existing container if present ──────────
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
    echo "[4/6] Removing existing $CONTAINER ..."
    docker stop "$CONTAINER" >/dev/null 2>&1 || true
    docker rm "$CONTAINER" >/dev/null
else
    echo "[4/6] No existing $CONTAINER — fresh deploy"
fi

# ── 5. Run new container ────────────────────────────────────
echo "[5/6] Starting $CONTAINER on $BIND:$PORT ..."
docker run -d \
    --name "$CONTAINER" \
    --network host \
    --restart unless-stopped \
    -v /home/67:/home/67 \
    -e "PYTHONPATH=$KNOW_DIR:/app" \
    -e "AGENT_CONFIG=$AGENT_CFG" \
    -e "INSTANCE_CONFIG=$INSTANCE_YML" \
    -e "PORT=$PORT" \
    -e "BIND_HOST=$BIND" \
    -e "OLLAMA_EMBED_URL=http://127.0.0.1:11435/api/embed" \
    -e "PYTHONUNBUFFERED=1" \
    "$IMAGE" \
    bash -c "pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple -q 2>&1 | tail -1 && python $APP_PY" \
    >/dev/null

# ── 6. Health check ─────────────────────────────────────────
echo "[6/6] Waiting for http://127.0.0.1:$PORT/ to become ready ..."
for i in $(seq 1 30); do
    code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 "http://127.0.0.1:$PORT/" 2>/dev/null || echo "000")
    if [ "$code" = "200" ]; then
        echo
        echo "✅ $CONTAINER ready"
        if [ "$BIND" = "127.0.0.1" ]; then
            echo "   Internal:  http://127.0.0.1:$PORT/   (loopback only — set up nginx for external access)"
        else
            echo "   URL:       http://127.0.0.1:$PORT/   (公网: http://qa.lambdagent.cn:$PORT/)"
        fi
        echo "   Logs:      docker logs -f $CONTAINER"
        echo "   Knowledge: $KNOW_DIR"
        echo "   Instance:  $INSTANCE_YML"
        exit 0
    fi
    sleep 4
done
echo "⚠️  Container started but not responding on port $PORT after 120s. Check: docker logs $CONTAINER"
exit 4
