#!/usr/bin/env bash
# post-bot-alert.sh — post a one-line message to a Discord alert channel.
#
# Routing: #bot-alerts (default; Syncro + general, whole team) vs #dev-alerts
# (private; RMM/Dev alerts, Howard + Mike only). Auto-routes by message prefix:
# [RMM] [DEPLOY] [DEV] [BUILD] [GURURMM] [SMARTBADGE-WATCH] -> #dev-alerts;
# everything else (incl. [SYNCRO]) -> #bot-alerts. Override with a 2nd arg.
#
# Usage:
#   bash post-bot-alert.sh "message text"            # auto-route by prefix
#   bash post-bot-alert.sh "message text" dev         # force #dev-alerts
#   bash post-bot-alert.sh "message text" bot         # force #bot-alerts
#   echo "message text" | bash post-bot-alert.sh
#
# Identity: This script sources get-identity.sh, making $USER_SHORT, $USER_NAME,
# $MACHINE, $USER_EMAIL available. Callers can use these in messages for correct
# attribution (e.g., "[RMM] $USER_SHORT deployed..."). The script itself doesn't
# auto-inject identity - callers must explicitly use the vars when needed.
#
# Token resolution (first hit wins):
#   1. SOPS vault: projects/discord-bot/bot-token.sops.yaml  field credentials.bot_token
#   2. projects/discord-bot/.env                              key  DISCORD_TOKEN
# Reading from the vault means this works from any machine, not just BEAST.
#
# Soft-fail by design: if the message is empty, the token is missing, or Discord is
# unreachable, it prints a [WARNING] and exits 0 so it NEVER breaks the caller
# (e.g. the /syncro billing workflow). The alert is best-effort, not load-bearing.

set -u

BOT_CHANNEL_ID="624710699771232265"    # #bot-alerts  — default (Syncro + general; whole team)
DEV_CHANNEL_ID="1509998508198068484"   # #dev-alerts  — private RMM/Dev alerts (Howard + Mike only)
ROOT="${CLAUDETOOLS_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"

# Load identity for attribution (soft-fail if missing)
source "$ROOT/.claude/scripts/get-identity.sh" 2>/dev/null || true

# --- message (arg or stdin) ---
MSG="${1:-}"
if [ -z "$MSG" ] && [ ! -t 0 ]; then MSG="$(cat)"; fi
if [ -z "$MSG" ]; then
  echo "[WARNING] post-bot-alert: empty message — nothing sent" >&2
  exit 0
fi

# Discord caps message content at 2000 chars (code 50035 on overflow). Alerts
# are one-liners by contract — truncate rather than chunk.
if [ "${#MSG}" -gt 1900 ]; then
  MSG="${MSG:0:1900} ...[truncated]"
  echo "[WARNING] post-bot-alert: message over 1900 chars — truncated" >&2
fi

# --- channel routing ---
# Optional 2nd arg: "dev"/"bot" keyword, a raw channel id, or omit for auto.
# Auto: RMM/Dev-category prefixes -> #dev-alerts (private); everything else
# (Syncro, general) -> #bot-alerts. Keeps existing call sites correct unchanged.
TARGET="${2:-auto}"
case "$TARGET" in
  dev|dev-alerts) CHANNEL_ID="$DEV_CHANNEL_ID"; CHANNEL_NAME="#dev-alerts" ;;
  bot|bot-alerts) CHANNEL_ID="$BOT_CHANNEL_ID"; CHANNEL_NAME="#bot-alerts" ;;
  auto|"")
    if printf '%s' "$MSG" | grep -qiE '^\[(RMM|DEPLOY|DEV|BUILD|GURURMM|SMARTBADGE-WATCH)\b'; then
      CHANNEL_ID="$DEV_CHANNEL_ID"; CHANNEL_NAME="#dev-alerts"
    else
      CHANNEL_ID="$BOT_CHANNEL_ID"; CHANNEL_NAME="#bot-alerts"
    fi ;;
  *) CHANNEL_ID="$TARGET"; CHANNEL_NAME="channel ${TARGET}" ;;
esac

# --- token: vault first, then .env ---
TOKEN="$(bash "$ROOT/.claude/scripts/vault.sh" get-field \
  projects/discord-bot/bot-token.sops.yaml credentials.bot_token 2>/dev/null)"
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
  ENV_FILE="$ROOT/projects/discord-bot/.env"
  if [ -f "$ENV_FILE" ]; then
    TOKEN="$(grep -iE '^[[:space:]]*DISCORD_TOKEN[[:space:]]*=' "$ENV_FILE" | head -1 \
      | sed -E 's/^[^=]*=[[:space:]]*//; s/^["'"'"']//; s/["'"'"'][[:space:]]*$//')"
  fi
fi
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
  echo "[WARNING] post-bot-alert: no bot token (vault + .env both empty) — alert skipped" >&2
  exit 0
fi

# --- post (jq builds the JSON; piped to curl via STDIN, never argv — a payload
# passed as a command-line arg on Windows goes through the argv encoding layer,
# which mangles non-ASCII chars into invalid JSON -> Discord 50109) ---
RESP="$(jq -nc --arg c "$MSG" '{content: $c}' | curl -s -m 15 -w $'\n%{http_code}' \
  -X POST "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages" \
  -H "Authorization: Bot ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "User-Agent: ClaudeToolsBot (claudetools, 1.0)" \
  --data-binary @- 2>/dev/null)"

HTTP="$(printf '%s' "$RESP" | tail -n1)"
BODY="$(printf '%s' "$RESP" | sed '$d')"

if [ "$HTTP" = "200" ]; then
  MID="$(printf '%s' "$BODY" | jq -r '.id // empty' 2>/dev/null)"
  echo "[OK] post-bot-alert: posted to ${CHANNEL_NAME} (message_id=${MID})"
  exit 0
fi

echo "[WARNING] post-bot-alert: Discord returned ${HTTP:-no-response} — ${BODY}" >&2
# Log the Discord POST failure (non-200 / unreachable) once. Do NOT route this
# through post-bot-alert itself — that would recurse; log-skill-error.sh only
# writes to errorlog.md. Soft-fail preserved: this never changes the exit 0.
bash "$ROOT/.claude/scripts/log-skill-error.sh" "post-bot-alert" "Discord POST failed (non-200/unreachable)" --context "channel=${CHANNEL_NAME} http=${HTTP:-none} resp=${BODY:0:80}" >/dev/null 2>&1 || true
exit 0
