#!/usr/bin/env bash
# =============================================================================
# stop-docker.sh — return to HOST MODE. Exact inverse of start-docker.sh.
#
#     sudo docker/scripts/stop-docker.sh
#     sudo docker/scripts/stop-docker.sh --dry-run
#
# 1. stop the compose stack (volumes ALWAYS kept)
# 2. RE-ENABLE and start apache2 + php7.4-fpm, then restore
#    /etc/apache2/ports.conf and 000-default.conf from the backups
#    start-docker.sh made, putting host Apache back on :80
# 3. restart host redis-server
# 4. put .env.docker back to the side-by-side ports so a later `up -d` works
# 5. verify the host application answers on :80
#
# THE RE-ENABLE IN STEP 2 IS THE WHOLE POINT OF THIS SCRIPT NOW. Docker-only mode
# `systemctl disable`s the host web units, so a rollback that only started them
# would work until the next reboot and then hand :80 back to nobody — the site
# down with every config file looking correct. Enabling is not optional here.
#
# NEVER uses `docker compose down -v`. That deletes the named volumes — the vector
# index (~25 min to rebuild) and the 274 MB embedding model (needs network, and is
# unrecoverable offline). Data loss is not a rollback, so the flag is refused.
# =============================================================================
set -uo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")/../.." || exit 1
REPO_ROOT="$(pwd)"
ENV_FILE="$REPO_ROOT/.env.docker"
PORTS_CONF=/etc/apache2/ports.conf
VHOST_CONF=/etc/apache2/sites-available/000-default.conf
BAK_SUFFIX=.trakop-pre-docker.bak

DRY=0
for a in "$@"; do
    case "$a" in
        --dry-run) DRY=1 ;;
        -v|--volumes)
            printf 'REFUSED: this script never deletes volumes — that would destroy the\n' >&2
            printf 'vector index and the embedding model. Rollback must not lose data.\n' >&2
            exit 2 ;;
        *) printf 'unknown argument: %s\n' "$a" >&2; exit 2 ;;
    esac
done

G=$'\033[32m'; R=$'\033[31m'; Y=$'\033[33m'; N=$'\033[0m'
say()  { printf '%s\n' "$*"; }
ok()   { printf "  ${G}ok${N}   %s\n" "$*"; }
warn() { printf "  ${Y}warn${N} %s\n" "$*"; }
die()  { printf "  ${R}FAIL${N} %s\n" "$*" >&2; exit 1; }
act()  { if [ "$DRY" = 1 ]; then printf "  [dry-run] %s\n" "$*"; else eval "$@"; fi; }

# Root is needed to ACT, not to look.
if [ "$DRY" = 0 ] && [ "$(id -u)" -ne 0 ]; then
    die "run this with sudo — restoring Apache's port needs root:
      sudo $0
  (or preview without root:  $0 --dry-run)"
fi
docker info >/dev/null 2>&1 || die "cannot reach the docker daemon."
dkc() { docker compose --env-file "$ENV_FILE" "$@"; }

say ""
say "=== 1. STOP THE COMPOSE STACK (volumes preserved) ==="
act "dkc down"
[ "$DRY" = 0 ] && ok "stopped; volumes trakop_lens_pgvector_data / trakop_lens_ollama_models kept"

say ""
say "=== 2. RESTORE THE HOST WEB LAYER (re-enable, restore config, start) ==="
# Re-enable FIRST, before touching config: an operator who interrupts this script
# half-way should be left with units that at least come back on reboot.
for u in apache2 php7.4-fpm; do
    if [ -z "$(systemctl list-unit-files --no-legend "$u.service" 2>/dev/null)" ]; then
        warn "$u not installed — skipping"
        continue
    fi
    [ "$(systemctl is-enabled "$u" 2>/dev/null)" = "enabled" ] || act "systemctl enable '$u' >/dev/null 2>&1"
    ok "$u enabled for boot"
done
# php7.4-fpm serves Apache over a UNIX socket, so it must be up BEFORE Apache
# handles a request or every .php returns 503 from an otherwise healthy Apache.
if [ -n "$(systemctl list-unit-files --no-legend php7.4-fpm.service 2>/dev/null)" ] \
   && [ "$(systemctl is-active php7.4-fpm 2>/dev/null)" != "active" ]; then
    act "systemctl start php7.4-fpm"
    ok "php7.4-fpm started (before Apache, so no 503 window)"
fi

restored=0
for f in "$PORTS_CONF" "$VHOST_CONF"; do
    if [ -f "${f}${BAK_SUFFIX}" ]; then
        act "cp -a '${f}${BAK_SUFFIX}' '$f'"
        ok "restored $(basename "$f")"
        restored=1
    else
        warn "no backup for $(basename "$f") — start-docker.sh may not have moved it"
    fi
done
if [ "$restored" = "1" ]; then
    act "apache2ctl configtest"
    act "systemctl restart apache2"
elif [ "$(systemctl is-active apache2 2>/dev/null)" != "active" ]; then
    act "systemctl start apache2"
fi

say ""
say "=== 3. RESTART HOST REDIS ==="
if [ "$(systemctl is-active redis-server 2>/dev/null)" != "active" ]; then
    act "systemctl start redis-server"
    ok "redis-server started"
else
    ok "redis-server already active"
fi

say ""
say "=== 4. SET THE ENV FILE BACK TO SIDE-BY-SIDE PORTS ==="
# So a later plain `up -d` binds ports that are actually free while host Apache
# holds :80 again. Without this, starting Docker later fails on a port conflict.
if [ "$DRY" = 1 ]; then
    say "  [dry-run] set APACHE_PORT=8081 and REDIS_PORT=6380 in .env.docker"
else
    sed -ri 's/^APACHE_PORT=.*/APACHE_PORT=8081/' "$ENV_FILE"
    sed -ri 's/^REDIS_PORT=.*/REDIS_PORT=6380/' "$ENV_FILE"
    ok "APACHE_PORT=8081  REDIS_PORT=6380"
fi

say ""
say "=== 5. VERIFY HOST MODE ==="
if [ "$DRY" = 1 ]; then
    say "  [dry-run] skipped"
else
    sleep 2
    code="$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "http://127.0.0.1/trakop-web/code/" 2>/dev/null)"
    case "$code" in
        2??|3??) ok "host application on :80 -> HTTP $code" ;;
        *)       die "host :80 returned '$code' — check: systemctl status apache2 ; apache2ctl configtest" ;;
    esac
    # The header must be GONE — if it is still there, Docker still holds :80.
    curl -sI --max-time 8 "http://127.0.0.1/trakop-web/code/" 2>/dev/null | grep -qi 'X-Trakop-Runtime' \
        && warn "X-Trakop-Runtime still present — the container may still hold :80" \
        || ok "no container header on :80 — host Apache is serving"
    for p in adminer.php phpmyadmin/; do
        printf "      :80/%-14s HTTP %s\n" "$p" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 6 "http://127.0.0.1/$p")"
    done
fi

say ""
say "HOST MODE active. http://localhost is host Apache + php7.4-fpm."
say ""
say "The RAG datastores are stopped too. TrakopLens does NOT lose its knowledge base for"
say "that any more: retrieval falls back to an index in the application's own MySQL, chosen"
say "automatically. That index has to exist in each tenant database — build it once:"
say "  cd code/webroot && php ../bin/cake.php rag_reindex --corpus=all --backend=mysql-lexical"
say "  code/tools/trakoplens/verify-host-mode.sh          # proves it end to end"
say ""
say "For the container's embedding quality without the containers, install Ollama on the"
say "host and use --backend=mysql-vector; details in ops/trakoplens-host-mode.md."
say ""
say "Or keep just the datastores up while the app runs on the host:"
say "  docker compose --env-file .env.docker up -d pgvector ollama redis"
say ""
say "Back to Docker:  sudo docker/scripts/start-docker.sh"
