#!/usr/bin/env bash
set -euo pipefail

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

echo "[cp-edge-wire] NOTE: auxiliary smoke only - verifies Control Plane-Edge hello and disconnect via real processes."

if command -v shellcheck >/dev/null 2>&1; then
    echo "[cp-edge-wire] running shellcheck..."
    shellcheck "$0"
else
    echo "[cp-edge-wire] shellcheck not found, skipping"
fi

# -- Timeout configuration ---------------------------------------------------
CP_READY_TIMEOUT="${IOP_CP_READY_TIMEOUT:-20}"
HELLO_TIMEOUT="${IOP_HELLO_TIMEOUT:-30}"
DISCONNECT_TIMEOUT="${IOP_DISCONNECT_TIMEOUT:-20}"

# -- Temp workspace ----------------------------------------------------------
# Keep executable smoke binaries on the repository filesystem. Some CI and
# sandbox environments mount the system temporary directory with `noexec`.
SMOKE_TMP_ROOT="$REPO_ROOT/.tmp"
mkdir -p "$SMOKE_TMP_ROOT"
TMP_DIR=$(mktemp -d "$SMOKE_TMP_ROOT/e2e-control-plane-edge-wire.XXXXXX")
CP_CONFIG="$TMP_DIR/control-plane.yaml"
EDGE_CONFIG="$TMP_DIR/edge.yaml"
CP_BIN="$TMP_DIR/control-plane"
EDGE_BIN="$TMP_DIR/edge"
CP_OUT="$TMP_DIR/cp_out"
EDGE_OUT="$TMP_DIR/edge_out"
EDGE_LOG="$TMP_DIR/edge.log"

CP_PID=""
EDGE_PID=""

dump_logs() {
    if [ -f "$CP_OUT" ]; then
        echo "=== CONTROL PLANE OUTPUT ==="
        cat "$CP_OUT"
    fi
    if [ -f "$EDGE_OUT" ]; then
        echo "=== EDGE PROCESS OUTPUT ==="
        cat "$EDGE_OUT"
    fi
    if [ -f "$EDGE_LOG" ]; then
        echo "=== EDGE LOG ==="
        cat "$EDGE_LOG"
    fi
}

cleanup() {
    local rc=$?
    if [ -n "$EDGE_PID" ] && kill -0 "$EDGE_PID" 2>/dev/null; then
        kill "$EDGE_PID" 2>/dev/null || true
    fi
    if [ -n "$CP_PID" ] && kill -0 "$CP_PID" 2>/dev/null; then
        kill "$CP_PID" 2>/dev/null || true
    fi
    # Give processes a moment to flush
    sleep 0.3 2>/dev/null || true
    if [ -n "$EDGE_PID" ]; then wait "$EDGE_PID" 2>/dev/null || true; fi
    if [ -n "$CP_PID" ]; then wait "$CP_PID" 2>/dev/null || true; fi
    if [ "$rc" -ne 0 ]; then
        echo "[cp-edge-wire] FAIL - dumping logs"
        dump_logs
    fi
    rm -rf "$TMP_DIR" 2>/dev/null || true
}
trap cleanup EXIT

# -- Random free port selection ----------------------------------------------
# Pick ports in ranges that do not overlap with the tracked local env ports:
#   13000-13099 (dev preview), 18080, 19080, 19081, 19090, 19092, 19190.
# Use ephemeral-style ranges that are unlikely to conflict.
USED_PORTS=""

pick_free_port() {
    local base="$1"
    local port
    for _ in $(seq 1 50); do
        port=$((base + RANDOM % 1000))
        if [[ " $USED_PORTS " == *" $port "* ]]; then
            continue
        fi
        if ! (echo "" > /dev/tcp/127.0.0.1/"$port") 2>/dev/null; then
            USED_PORTS="${USED_PORTS} ${port}"
            echo "$port"
            return 0
        fi
    done
    # Fallback: ask the OS
    python3 -c "import socket; s=socket.socket(); s.bind(('',0)); print(s.getsockname()[1]); s.close()" 2>/dev/null \
        || echo "$((base + RANDOM % 1000))"
}

CP_HTTP_PORT=$(pick_free_port 29080)
CP_CLIENT_WS_PORT=$(pick_free_port 30180)
CP_EDGE_WIRE_PORT=$(pick_free_port 31181)
EDGE_NODE_PORT=$(pick_free_port 32090)
EDGE_BOOTSTRAP_PORT=$(pick_free_port 33082)
EDGE_METRICS_PORT=$(pick_free_port 34092)

echo "[cp-edge-wire] ports: cp_http=$CP_HTTP_PORT cp_ws=$CP_CLIENT_WS_PORT cp_edge_wire=$CP_EDGE_WIRE_PORT edge_node=$EDGE_NODE_PORT edge_bootstrap=$EDGE_BOOTSTRAP_PORT edge_metrics=$EDGE_METRICS_PORT"

# -- Build temp binaries ------------------------------------------------------
echo "[cp-edge-wire] building temp binaries..."
go build -o "$CP_BIN" "$REPO_ROOT/apps/control-plane/cmd/control-plane"
go build -o "$EDGE_BIN" "$REPO_ROOT/apps/edge/cmd/edge"

# -- Write temp configs -------------------------------------------------------
cat > "$CP_CONFIG" <<EOF
server:
  listen: "127.0.0.1:${CP_HTTP_PORT}"
  wire_listen: "127.0.0.1:${CP_CLIENT_WS_PORT}"
  edge_wire_listen: "127.0.0.1:${CP_EDGE_WIRE_PORT}"
logging:
  level: "info"
  pretty: false
EOF

cat > "$EDGE_CONFIG" <<EOF
edge:
  id: "smoke-edge-wire"
  name: "Smoke Edge Wire"
server:
  listen: "127.0.0.1:${EDGE_NODE_PORT}"
bootstrap:
  listen: "127.0.0.1:${EDGE_BOOTSTRAP_PORT}"
  artifact_dir: "${TMP_DIR}/artifacts"
metrics:
  port: ${EDGE_METRICS_PORT}
logging:
  level: "info"
  pretty: false
  path: "${EDGE_LOG}"
control_plane:
  enabled: true
  wire_addr: "127.0.0.1:${CP_EDGE_WIRE_PORT}"
  reconnect_interval_sec: 2
EOF

# -- Start Control Plane ------------------------------------------------------
echo "[cp-edge-wire] starting Control Plane..."
"$CP_BIN" serve --config "$CP_CONFIG" \
    > "$CP_OUT" 2>&1 &
CP_PID=$!

# Wait for CP edge wire TCP port to be ready
echo "[cp-edge-wire] waiting for Control Plane edge wire port ${CP_EDGE_WIRE_PORT} (timeout: ${CP_READY_TIMEOUT}s)..."
deadline=$((SECONDS + CP_READY_TIMEOUT))
while ! (echo "" > /dev/tcp/127.0.0.1/"${CP_EDGE_WIRE_PORT}") 2>/dev/null; do
    if ! kill -0 "$CP_PID" 2>/dev/null; then
        echo "[cp-edge-wire] FAIL: Control Plane exited before port was ready"
        exit 1
    fi
    if (( SECONDS >= deadline )); then
        echo "[cp-edge-wire] FAIL: Control Plane edge wire port ${CP_EDGE_WIRE_PORT} not ready after ${CP_READY_TIMEOUT}s"
        exit 1
    fi
    sleep 0.5
done
echo "[cp-edge-wire] Control Plane edge wire port ready"

# -- Start Edge ---------------------------------------------------------------
echo "[cp-edge-wire] starting Edge..."
"$EDGE_BIN" serve --config "$EDGE_CONFIG" \
    > "$EDGE_OUT" 2>&1 &
EDGE_PID=$!

# -- Wait for hello accepted on CP side ---------------------------------------
echo "[cp-edge-wire] waiting for hello accepted (timeout: ${HELLO_TIMEOUT}s)..."
deadline=$((SECONDS + HELLO_TIMEOUT))
while true; do
    if grep -q "edge hello accepted" "$CP_OUT" 2>/dev/null; then
        echo "[cp-edge-wire] CP: hello accepted"
        break
    fi
    if ! kill -0 "$CP_PID" 2>/dev/null; then
        echo "[cp-edge-wire] FAIL: Control Plane exited while waiting for hello accepted"
        exit 1
    fi
    if ! kill -0 "$EDGE_PID" 2>/dev/null; then
        echo "[cp-edge-wire] FAIL: Edge exited while waiting for hello accepted"
        exit 1
    fi
    if (( SECONDS >= deadline )); then
        echo "[cp-edge-wire] FAIL: hello accepted not seen after ${HELLO_TIMEOUT}s"
        exit 1
    fi
    sleep 0.5
done

# -- Wait for connected marker on Edge side -----------------------------------
deadline=$((SECONDS + HELLO_TIMEOUT))
while true; do
    if grep -q "connected to control plane" "$EDGE_LOG" 2>/dev/null; then
        echo "[cp-edge-wire] Edge: connected to control plane"
        break
    fi
    if ! kill -0 "$EDGE_PID" 2>/dev/null; then
        echo "[cp-edge-wire] FAIL: Edge exited while waiting for connected marker"
        exit 1
    fi
    if (( SECONDS >= deadline )); then
        echo "[cp-edge-wire] FAIL: 'connected to control plane' not seen on Edge after ${HELLO_TIMEOUT}s"
        exit 1
    fi
    sleep 0.5
done

# -- Stop Edge and wait for disconnect on CP side -----------------------------
echo "[cp-edge-wire] stopping Edge process to trigger disconnect..."
kill "$EDGE_PID" 2>/dev/null || true
wait "$EDGE_PID" 2>/dev/null || true
EDGE_PID=""

echo "[cp-edge-wire] waiting for disconnect marker on CP (timeout: ${DISCONNECT_TIMEOUT}s)..."
deadline=$((SECONDS + DISCONNECT_TIMEOUT))
while true; do
    if grep -q "edge disconnected" "$CP_OUT" 2>/dev/null; then
        echo "[cp-edge-wire] CP: edge disconnected"
        break
    fi
    if ! kill -0 "$CP_PID" 2>/dev/null; then
        echo "[cp-edge-wire] FAIL: Control Plane exited while waiting for disconnect marker"
        exit 1
    fi
    if (( SECONDS >= deadline )); then
        echo "[cp-edge-wire] FAIL: 'edge disconnected' not seen on CP after ${DISCONNECT_TIMEOUT}s"
        exit 1
    fi
    sleep 0.5
done

# -- Final checks -------------------------------------------------------------
dump_logs
echo "==========================="

FAIL=0

if ! grep -q "edge hello accepted" "$CP_OUT" 2>/dev/null; then
    echo "[cp-edge-wire] FAIL: 'edge hello accepted' not found in CP log"
    FAIL=1
fi
if ! grep -q "connected to control plane" "$EDGE_LOG" 2>/dev/null; then
    echo "[cp-edge-wire] FAIL: 'connected to control plane' not found in Edge log"
    FAIL=1
fi
if ! grep -q "edge disconnected" "$CP_OUT" 2>/dev/null; then
    echo "[cp-edge-wire] FAIL: 'edge disconnected' not found in CP log"
    FAIL=1
fi

if [ "$FAIL" -eq 1 ]; then
    echo "[cp-edge-wire] Control Plane-Edge wire smoke FAILED."
    exit 1
fi

echo "[cp-edge-wire] Control Plane-Edge wire smoke PASSED."
exit 0
