#!/usr/bin/env bash
# Pre-Survey Map v1.0.6 first install for x86_64 Docker 18.09 hosts.
# This script is intentionally isolated: it only creates/starts presurvey-* containers
# and presurvey-net. It never stops/removes unrelated containers and never touches
# host/none networks.
set -euo pipefail

VERSION=v1.0.6
IMAGE_TAR=${IMAGE_TAR:-presurvey-images-v1.0.6-x86.tar}
NET=${NET:-presurvey-net}
DB_CTN=${DB_CTN:-presurvey-db}
API_CTN=${API_CTN:-presurvey-api}
WEB_CTN=${WEB_CTN:-presurvey-web}
DB_VOLUME=${DB_VOLUME:-presurvey-pgdata}
DB_USER=${DB_USER:-presurvey}
DB_PASSWORD=${DB_PASSWORD:-uiPHtLVpYpuxNiBtj9ZQWVQkHW7YtrVf}
DB_NAME=${DB_NAME:-presurvey}
WEBPORT=${WEBPORT:-18080}

POSTGIS_IMAGE=postgis/postgis:16-3.4
API_IMAGE=pre-survey-map-api:v1.0.6
WEB_IMAGE=pre-survey-map-web:v1.0.6

SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
IMAGE_TAR_PATH="$SCRIPT_DIR/$IMAGE_TAR"
INIT_SQL="$SCRIPT_DIR/init.sql"
GEO_DIR="$SCRIPT_DIR/geo_data"

log() { printf '%s\n' "$*"; }
die() {
    log "!! $*"
    log "   debug: NET=$NET DB_CTN=$DB_CTN API_CTN=$API_CTN WEB_CTN=$WEB_CTN WEBPORT=$WEBPORT"
    exit 1
}

exists_container() {
    docker inspect "$1" >/dev/null 2>&1
}

is_running() {
    [ "$(docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null || echo false)" = "true" ]
}

start_if_stopped() {
    if exists_container "$1" && ! is_running "$1"; then
        log "   starting existing $1"
        docker start "$1" >/dev/null
    fi
}

port_busy() {
    if command -v ss >/dev/null 2>&1; then
        ss -ltn | awk '{print $4}' | grep -Eq "(^|:)${WEBPORT}$"
    elif command -v netstat >/dev/null 2>&1; then
        netstat -ltn | awk '{print $4}' | grep -Eq "(^|:)${WEBPORT}$"
    else
        python - "$WEBPORT" <<'PY'
import socket, sys
port = int(sys.argv[1])
s = socket.socket()
try:
    s.bind(("0.0.0.0", port))
except OSError:
    sys.exit(0)
finally:
    s.close()
sys.exit(1)
PY
    fi
}

wait_db() {
    log "== wait db pg_isready =="
    for i in $(seq 1 60); do
        if docker exec "$DB_CTN" pg_isready -U "$DB_USER" -d "$DB_NAME" >/dev/null 2>&1; then
            log "   db ready"
            return 0
        fi
        sleep 2
    done
    docker logs "$DB_CTN" 2>/dev/null | tail -80 || true
    die "db did not become ready"
}

wait_api() {
    log "== wait api health through docker network alias api =="
    for i in $(seq 1 60); do
        if docker run --rm --network "$NET" "$API_IMAGE" python - <<'PY' >/tmp/presurvey-api-health.out 2>/tmp/presurvey-api-health.err
import urllib.request
r = urllib.request.urlopen("http://api:8000/health", timeout=5)
body = r.read().decode()
print(body)
raise SystemExit(0 if r.status == 200 and '"db":true' in body else 1)
PY
        then
            log "   api health OK: $(cat /tmp/presurvey-api-health.out)"
            return 0
        fi
        sleep 2
    done
    docker logs "$API_CTN" 2>/dev/null | tail -100 || true
    cat /tmp/presurvey-api-health.err 2>/dev/null || true
    die "api health failed"
}

fetch_web_sites() {
    url="http://localhost:${WEBPORT}/api/sites"
    if command -v curl >/dev/null 2>&1; then
        curl -fsS "$url"
    elif command -v wget >/dev/null 2>&1; then
        wget -qO- "$url"
    else
        python - "$url" <<'PY'
import sys, urllib.request
print(urllib.request.urlopen(sys.argv[1], timeout=10).read().decode())
PY
    fi
}

log "== 0. preflight =="
command -v docker >/dev/null 2>&1 || die "docker not found"
[ -f "$IMAGE_TAR_PATH" ] || die "image tar not found: $IMAGE_TAR_PATH"
[ -f "$INIT_SQL" ] || die "init.sql not found: $INIT_SQL"
[ -d "$GEO_DIR" ] || die "geo_data dir not found: $GEO_DIR"
log "   package dir: $SCRIPT_DIR"
log "   DB_PASSWORD is set in this script; edit DB_PASSWORD=... before running if needed."

log "== 1. docker load images =="
docker load -i "$IMAGE_TAR_PATH"
docker image inspect "$POSTGIS_IMAGE" "$API_IMAGE" "$WEB_IMAGE" >/dev/null \
    || die "required images missing after docker load"

log "== 2. create/reuse isolated network $NET =="
if docker network inspect "$NET" >/dev/null 2>&1; then
    log "   network exists: $NET"
else
    docker network create "$NET" >/dev/null
    log "   network created: $NET"
fi

log "== 3. create/start db =="
if exists_container "$DB_CTN"; then
    log "   existing $DB_CTN found; reuse it"
    start_if_stopped "$DB_CTN"
else
    docker run -d \
        --name "$DB_CTN" \
        --network "$NET" \
        -e POSTGRES_USER="$DB_USER" \
        -e POSTGRES_PASSWORD="$DB_PASSWORD" \
        -e POSTGRES_DB="$DB_NAME" \
        -v "$DB_VOLUME":/var/lib/postgresql/data \
        -v "$INIT_SQL":/docker-entrypoint-initdb.d/init.sql:ro \
        "$POSTGIS_IMAGE" >/dev/null
    log "   db created with volume $DB_VOLUME"
fi
wait_db

DBIP=$(docker inspect -f "{{(index .NetworkSettings.Networks \"$NET\").IPAddress}}" "$DB_CTN" 2>/dev/null || true)
[ -n "$DBIP" ] || die "cannot detect db IP on $NET"
log "   DBIP=$DBIP"

log "== 4. create/start api =="
if exists_container "$API_CTN"; then
    log "   existing $API_CTN found; reuse it"
    start_if_stopped "$API_CTN"
else
    docker run -d \
        --name "$API_CTN" \
        --network "$NET" \
        --network-alias api \
        -e DB_HOST="$DBIP" \
        -e DB_PORT=5432 \
        -e DB_USER="$DB_USER" \
        -e DB_PASSWORD="$DB_PASSWORD" \
        -e DB_NAME="$DB_NAME" \
        -v "$GEO_DIR":/app/geo_data:ro \
        "$API_IMAGE" \
        uvicorn main:app --host 0.0.0.0 --port 8000 --loop asyncio >/dev/null
    log "   api created: DB_HOST=$DBIP alias=api loop=asyncio"
fi
wait_api

log "== 5. create/start web =="
if exists_container "$WEB_CTN"; then
    log "   existing $WEB_CTN found; reuse it"
    start_if_stopped "$WEB_CTN"
else
    if port_busy; then
        die "WEBPORT=$WEBPORT is already in use; rerun with WEBPORT=<free_port> bash $0"
    fi
    docker run -d \
        --name "$WEB_CTN" \
        --network "$NET" \
        -p "${WEBPORT}:80" \
        "$WEB_IMAGE" >/dev/null
    log "   web created: http://localhost:$WEBPORT"
fi

log "== 6. verify web reverse proxy /api/sites =="
for i in $(seq 1 30); do
    if fetch_web_sites >/tmp/presurvey-sites.out 2>/tmp/presurvey-sites.err \
        && grep -q '"FeatureCollection"' /tmp/presurvey-sites.out; then
        bytes=$(wc -c </tmp/presurvey-sites.out | tr -d ' ')
        log "   /api/sites OK, bytes=$bytes"
        log "== install complete =="
        log "   URL: http://localhost:$WEBPORT"
        log "   containers:"
        docker ps --filter "name=presurvey-" --format '   {{.Names}}  {{.Status}}  {{.Ports}}'
        exit 0
    fi
    sleep 2
done
cat /tmp/presurvey-sites.err 2>/dev/null || true
die "web reverse proxy /api/sites failed"
