#!/bin/sh
# Shared helpers for client2server hotplug scripts.
# Source this file from 01-wifi / 02-dhcp / etc.
#
# Behavior:
#   - Loads UCI config (SERVER_URL / TOKEN / ROUTER_ID).
#   - Provides send_event() that:
#       1. Appends the JSON event to a shared on-disk buffer.
#       2. Wakes the Lua agent via SIGHUP so it flushes ASAP.
#       3. Falls back to a direct curl POST if the buffer is not writable
#          (e.g. /var/run not yet mounted in early boot).
#
# Shared buffer location: /var/run/client2server/buffer
#   - Same format as client2server-unified.lua's buffer file
#     (one JSON event per line, NDJSON).
#   - The Lua agent's buffer.init() reads it on startup, and
#     buffer.flush() drains it on every reconnect / SIGHUP.

CLIENT2SERVER_DIR="${CLIENT2SERVER_DIR:-/var/run/client2server}"
BUFFER_FILE="${BUFFER_FILE:-${CLIENT2SERVER_DIR}/buffer}"
PID_FILE="${PID_FILE:-${CLIENT2SERVER_DIR}/pid}"
ENV_FILE="${ENV_FILE:-${CLIENT2SERVER_DIR}/env}"

# Ensure runtime dir exists
mkdir -p "$CLIENT2SERVER_DIR" 2>/dev/null

# Load config: prefer env file (set by init.d), fall back to UCI
if [ -f "$ENV_FILE" ]; then
    # shellcheck disable=SC1090
    . "$ENV_FILE"
fi

: "${SERVER_URL:=$(uci get client2server.server.url 2>/dev/null)}"
: "${ROUTER_ID:=$(uci get client2server.router.id 2>/dev/null)}"
: "${TOKEN:=$(uci get client2server.server.token 2>/dev/null)}"

# Final fallbacks
: "${SERVER_URL:=http://127.0.0.1:3843}"
: "${ROUTER_ID:=$(cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown)}"

log_msg() {
    logger -t client2server-hotplug -p user.info "$1"
}

log_err() {
    logger -t client2server-hotplug -p user.err "$1"
}

# Build a JSON event in the same shape the Lua agent uses.
# Args: event_type, data_json
build_event_json() {
    local event_type="$1"
    local data="$2"
    printf '{"router_id":"%s","event":"%s","data":%s}' \
        "$ROUTER_ID" "$event_type" "$data"
}

# Append to disk buffer (atomic-ish via mv from a temp file).
# Returns 0 on success, 1 on failure.
spool_event() {
    local json="$1"
    local tmp
    tmp=$(mktemp "${BUFFER_FILE}.XXXXXX") || return 1
    if ! printf '%s\n' "$json" >> "$tmp"; then
        rm -f "$tmp" 2>/dev/null
        return 1
    fi
    if ! cat "$tmp" >> "$BUFFER_FILE" 2>/dev/null; then
        rm -f "$tmp" 2>/dev/null
        return 1
    fi
    rm -f "$tmp" 2>/dev/null
    return 0
}

# Wake the Lua agent (best-effort).
# We touch `<state_dir>/wake`; the agent's main loop polls for it
# and triggers an immediate buffer flush. This is more portable than
# SIGHUP across Lua 5.1/5.2/LuaJIT builds.
wake_agent() {
    touch "$CLIENT2SERVER_DIR/wake" 2>/dev/null || true
    # Also try SIGHUP as a fast path (harmless if PID is stale or
    # the agent doesn't install a handler).
    if [ -f "$PID_FILE" ]; then
        local pid
        pid=$(cat "$PID_FILE" 2>/dev/null)
        if [ -n "$pid" ] && [ "$pid" -gt 0 ] 2>/dev/null; then
            kill -HUP "$pid" 2>/dev/null || true
        fi
    fi
}

# Direct HTTP POST fallback. Args: json_event
direct_post() {
    local json="$1"
    if [ -n "$TOKEN" ]; then
        curl -s -m 3 -X POST "$SERVER_URL/api/events" \
            -H "Content-Type: application/json" \
            -H "Authorization: Bearer $TOKEN" \
            -d "$json" >/dev/null 2>&1
    else
        curl -s -m 3 -X POST "$SERVER_URL/api/events" \
            -H "Content-Type: application/json" \
            -d "$json" >/dev/null 2>&1
    fi
}

# Main entry point. Args: event_type, data_json
# Behavior:
#   1. Try to spool to disk + wake agent (preferred: survives outages).
#   2. If spooling fails, do a one-shot direct POST (best effort, may drop).
send_event() {
    local event_type="$1"
    local data="$2"
    local json
    json=$(build_event_json "$event_type" "$data")

    if spool_event "$json"; then
        log_msg "Spooled: $event_type"
        wake_agent
        return 0
    fi

    # Fallback: try direct POST (may be lost if offline)
    log_err "Spool failed, falling back to direct POST: $event_type"
    direct_post "$json"
    log_msg "Sent (fallback): $event_type"
}
