#!/bin/bash
# ==============================================================================================
# ========================= Upgrade Webhook Setup =============================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Registers the Varaverk upgrade webhook in Sonarr, Radarr, and Lidarr via
# their notification APIs. Idempotent — skips any arr that already has it.
#
# Run once after first install, or any time you add a new arr or host.
# The listener (start_webhook_listener.sh) must be running before arrs will
# actually deliver events, but this script can register the connection first.
#
# ==============================================================================================
# OPERATIONAL MODEL
# ==============================================================================================
#
#   1. Generate WEBHOOK_SECRET in master.conf if empty
#   2. Register webhook in each local arr (Sonarr / Radarr / Lidarr)
#   3. SSH to remote host and run itself there (unless --local-only)
#
# ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# Idempotent Registration
#   Skips any arr that already has the webhook registered. Safe to re-run after
#   adding a new arr or after a conf change without creating duplicate entries.
#
# Self-Propagating
#   SSHes to the remote and runs itself with --local-only — one execution
#   configures both servers without a separate remote step.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
#   Idempotent      — skips arrs that already have the webhook registered
#   Secret auto-gen — WEBHOOK_SECRET generated if empty; never left blank
#   --local-only    — used internally for SSH; prevents infinite recursion
#   --dry-run mode  — shows what would be registered without making API calls
#   acquire_lock    — prevents concurrent registration runs
#
# ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
# master.conf
#
#   WEBHOOK_PORT
#       Port the listener binds and the registered webhook URL points at. 0 disables the
#       listener entirely (start_webhook_listener.sh exits early), so registering against
#       a port of 0 would produce URLs nothing is serving.
#
#   WEBHOOK_SECRET
#       Shared secret embedded in the registered URL as ?key=. Generated here on first run
#       and written back into master.conf — the write-back is verified, because the arrs
#       are registered with this value and a failed persist would leave them holding a
#       secret this host does not have.
#
# host*.conf (aliased by detect_hosts())
#
#   SONARR_URL / SONARR_API_KEY
#   RADARR_URL / RADARR_API_KEY
#   LIDARR_URL / LIDARR_API_KEY
#       Each arr the webhook is registered in. An arr with no URL or key configured on
#       this host is skipped rather than failing the run.
#
#   SSH_KEY
#       Used when propagating the same secret to the partner via OVERRIDE_SECRET.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# webhook_setup.sh
#     Configure local arrs, then SSH to remote and configure remote arrs.
#
# webhook_setup.sh --local-only
#     Local arrs only (used internally when called via SSH on the remote).
#
# webhook_setup.sh --dry-run
#     Show what would be registered without making any changes.
#
# webhook_setup.sh --log
#     Verbose output.
#
# ==============================================================================================

set -uo pipefail

LOCAL_ONLY=false

for arg in "$@"; do
    case "$arg" in
        --local-only) LOCAL_ONLY=true ;;
    esac
done

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ECOSYSTEM_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
MASTER_CONF="$ECOSYSTEM_ROOT/Configurations/master.conf"

source "$ECOSYSTEM_ROOT/load_config.sh"
parse_args "$@"

# Writes the generated secret into master.conf via sed -i and SSHes to the partner.
if [[ "$EUID" -ne 0 ]]; then
    error "Must be run as root"
    exit 1
fi

acquire_lock
detect_hosts

WEBHOOK_NAME="Varaverk Upgrade"

# ── Resolve or generate the secret ──────────────────────────────────────────
# OVERRIDE_SECRET env var is set when called recursively via SSH from the
# primary host, so both ends use the same secret.
#
# Every write-back below is verified by re-reading master.conf. The secret gets baked into
# the webhook URL registered in each arr — if the sed silently fails to match, the arrs end
# up holding a secret this host does not have, and the listener rejects every delivery.
_persist_secret() {
    local secret="$1"
    sed -i "s/WEBHOOK_SECRET=\"\"/WEBHOOK_SECRET=\"$secret\"/" "$MASTER_CONF"
    if ! grep -q "WEBHOOK_SECRET=\"$secret\"" "$MASTER_CONF" 2>/dev/null; then
        error "Could not persist WEBHOOK_SECRET to $MASTER_CONF"
        error "Registering the arrs now would leave them with a secret this host does not have"
        notify "Webhook setup aborted on $(hostname) — could not persist WEBHOOK_SECRET" \
            "Webhook Setup" "warning"
        exit 1
    fi
}

if [[ -n "${OVERRIDE_SECRET:-}" ]]; then
    if [[ -z "${WEBHOOK_SECRET:-}" ]]; then
        _persist_secret "$OVERRIDE_SECRET"
    fi
    WEBHOOK_SECRET="$OVERRIDE_SECRET"
fi

if [[ -z "${WEBHOOK_SECRET:-}" ]]; then
    if [[ "$DRY_RUN" == true ]]; then
        WEBHOOK_SECRET="<would-generate>"
    else
        if ! command -v openssl >/dev/null 2>&1; then
            error "openssl not found — cannot generate WEBHOOK_SECRET"
            exit 1
        fi
        GENERATED=$(openssl rand -hex 32)
        _persist_secret "$GENERATED"
        WEBHOOK_SECRET="$GENERATED"
        echo "Generated WEBHOOK_SECRET — saved to master.conf"
    fi
fi

LOCAL_IP=$(hostname -I | awk '{print $1}')
WEBHOOK_URL="http://${LOCAL_IP}:${WEBHOOK_PORT}/webhook?key=${WEBHOOK_SECRET}"

# ── Helper: register webhook in one arr ─────────────────────────────────────
_register() {
    local label="$1" base_url="$2" api_key="$3" api_ver="$4"
    local import_field="$5"   # onDownload (Sonarr/Radarr) or onReleaseImport (Lidarr)

    if [[ "$DRY_RUN" == true ]]; then
        echo "  [$label] Would register → $WEBHOOK_URL"
        return 0
    fi

    # Check if already registered by name
    local existing
    existing=$(curl -sf --max-time 5 \
        -H "X-Api-Key: $api_key" \
        "$base_url/api/$api_ver/notification" 2>/dev/null) || {
        echo "  [$label] Cannot reach arr — skipping"
        return 1
    }

    if echo "$existing" | grep -q "\"name\":[[:space:]]*\"${WEBHOOK_NAME}\""; then
        echo "  [$label] Already registered — skipping"
        return 0
    fi

    local payload
    payload=$(printf '{
  "name": "%s",
  "implementation": "Webhook",
  "configContract": "WebhookSettings",
  "onGrab": false,
  "%s": true,
  "onUpgrade": true,
  "onRename": false,
  "onHealthIssue": false,
  "includeHealthWarnings": false,
  "onApplicationUpdate": false,
  "tags": [],
  "fields": [
    {"name": "url",      "value": "%s"},
    {"name": "method",   "value": 1},
    {"name": "username", "value": ""},
    {"name": "password", "value": ""}
  ]
}' "$WEBHOOK_NAME" "$import_field" "$WEBHOOK_URL")

    local http_code
    http_code=$(curl -sf --max-time 5 -o /dev/null -w '%{http_code}' \
        -X POST \
        -H "X-Api-Key: $api_key" \
        -H 'Content-Type: application/json' \
        -d "$payload" \
        "$base_url/api/$api_ver/notification" 2>/dev/null)

    if [[ "$http_code" == "201" || "$http_code" == "200" ]]; then
        echo "  [$label] Registered ✅  →  $WEBHOOK_URL"
    else
        echo "  [$label] Failed (HTTP ${http_code:-timeout})"
        return 1
    fi
}

# ── Local arrs ───────────────────────────────────────────────────────────────
echo ""
echo "━━━ Upgrade Webhook Setup — $MY_ID ($LOCAL_SERVER_NAME) ━━━"
echo "  LAN IP : $LOCAL_IP"
echo "  Port   : $WEBHOOK_PORT"
echo "  URL    : $WEBHOOK_URL"
echo ""

[[ -n "${SONARR_URL:-}" && -n "${SONARR_API_KEY:-}" ]] && \
    _register "Sonarr" "$SONARR_URL" "$SONARR_API_KEY" "v3" "onDownload"

[[ -n "${RADARR_URL:-}" && -n "${RADARR_API_KEY:-}" ]] && \
    _register "Radarr" "$RADARR_URL" "$RADARR_API_KEY" "v3" "onDownload"

[[ -n "${LIDARR_URL:-}" && -n "${LIDARR_API_KEY:-}" ]] && \
    _register "Lidarr" "$LIDARR_URL" "$LIDARR_API_KEY" "v1" "onReleaseImport"

# ── Remote host ───────────────────────────────────────────────────────────────
if [[ "$LOCAL_ONLY" == false && -n "${REMOTE_ID:-}" ]]; then
    echo ""
    echo "━━━ Configuring remote: $REMOTE_SERVER_NAME ━━━"

    remote_ip=$(resolve_tailscale_ip "$REMOTE_SERVER_NAME") || {
        echo "  Cannot resolve Tailscale IP for $REMOTE_SERVER_NAME — skipping"
        echo "  Run manually on that host: Tools/webhook_setup.sh --local-only"
        echo ""
        exit 0
    }

    remote_flags="--local-only"
    [[ "$DRY_RUN" == true ]] && remote_flags="$remote_flags --dry-run"

    ssh -i "$SSH_KEY" -o ConnectTimeout=10 -o StrictHostKeyChecking=no \
        root@"$remote_ip" \
        "OVERRIDE_SECRET='$WEBHOOK_SECRET' bash /boot/config/plugins/varaverk/Tools/webhook_setup.sh $remote_flags" \
        || echo "  Remote setup failed — check SSH and that Varaverk is installed on $REMOTE_SERVER_NAME"
fi

echo ""
echo "Done."
