#!/bin/bash
# devdesk-notify-matrix SESSION SINCE
# devdesk-notify-matrix --usage PCT RESETS_AT
#
# Started (detached) by devdesk-state-hook when a session starts waiting on you.
# After DEVDESK_MATRIX_DELAY seconds, if that same wait is still on, no DevDesk
# tab is in view, and this session hasn't posted in DEVDESK_MATRIX_QUIET seconds,
# post what Claude is asking to the hookshot webhook in DEVDESK_MATRIX_WEBHOOK_FILE
# (devdesk#28, #50).
set -euo pipefail

# shellcheck source=libexec/devdesk-lib.sh
. "${DEVDESK_LIBEXEC:-/usr/lib/devdesk}/devdesk-lib.sh"

# Post BODY (JSON with a .text) to the hookshot webhook. The URL is a secret
# (anyone holding it can post to the room): it goes to curl on stdin, never on
# the command line.
post() {
    local webhook
    # shellcheck disable=SC1003 # tr deletes whitespace, quotes and backslashes from the URL
    webhook=$(tr -d '[:space:]"\\' <"$DEVDESK_MATRIX_WEBHOOK_FILE")
    printf 'url = "%s"\n' "$webhook" |
        curl -fsS --max-time 10 --retry 2 -K - -H 'Content-Type: application/json' --data-binary "$1" >/dev/null
}

# devdesk-notify-matrix --usage PCT RESETS_AT (devdesk#45): started by the status
# line when the 5-hour plan window passes DEVDESK_USAGE_WARN percent. Once per
# window, and only when no client is attached to any session (you're away; a
# browser tab shows its own warning).
if [ "${1:-}" = --usage ]; then
    pct=${2:-} resets=${3:-}
    [[ $pct =~ ^[0-9]+$ && $resets =~ ^[0-9]+$ ]] || exit 0
    marker="$DEVDESK_STATE_DIR/usage-warned"
    exec 9>>"$marker.lock"
    flock -n 9 || exit 0
    [ "$(cat "$marker" 2>/dev/null)" != "$resets" ] || exit 0
    printf '%s\n' "$resets" >"$marker"
    [ -r "$DEVDESK_MATRIX_WEBHOOK_FILE" ] || exit 0
    [ -z "$(dd_tmux list-clients -F x 2>/dev/null)" ] || exit 0
    at=$(date -d "@$resets" '+%H:%M %Z')
    post "$(jq -cMn --arg p "$pct" --arg at "$at" --arg h "$(hostname)" \
        '{kind: "usage", host: $h, text: "Claude plan usage is at \($p)% of the 5-hour window; it resets at \($at)."}')"
    exit 0
fi

session=${1:-}
since=${2:-}
dd_valid_name "$session" || exit 0
[[ $since =~ ^[0-9]+$ ]] || exit 0
[ -r "$DEVDESK_MATRIX_WEBHOOK_FILE" ] || exit 0

sleep "$DEVDESK_MATRIX_DELAY"

state_file="$DEVDESK_STATUS_DIR/$session.json"
# Still the same wait? (Answering it moves the state on; a new wait has its own notifier.)
[ "$(jq -rM '"\(.state) \(.since)"' "$state_file" 2>/dev/null)" = "waiting $since" ] || exit 0
# You're at DevDesk if any tab has shown a session in the last ~2 minutes
# (presence markers, devdesk#26): the browser tells you itself (devdesk#50).
[ -z "$(find "$DEVDESK_PRESENCE_DIR" -type f 2>/dev/null | head -n 1)" ] || exit 0
# The idle reminder isn't a request (the state hook drops it; old states may have it).
message=$(jq -rM '.message // ""' "$state_file" 2>/dev/null)
request=$(jq -cM '.request // null' "$state_file" 2>/dev/null) || request=null
if [ "$request" = null ] && { [ -z "$message" ] || [[ $message == *"waiting for your input"* ]]; }; then exit 0; fi
# At most one message per session per DEVDESK_MATRIX_QUIET seconds.
sent="$DEVDESK_STATE_DIR/matrix-sent/$session"
mkdir -p "${sent%/*}"
if [ -n "$(find "$sent" -newermt "-$DEVDESK_MATRIX_QUIET seconds" 2>/dev/null)" ]; then exit 0; fi
touch "$sent"

url=""
# existing=1: if the session was ended by the time you tap, say so instead of
# starting a new Claude there (devdesk#38).
[ -z "$DEVDESK_PUBLIC_URL" ] || url="${DEVDESK_PUBLIC_URL%/}/?arg=$session&existing=1"
# What exactly it wants: "alpha: Claude wants to run Bash (Remove x)" and the command.
body=$(jq -cMn --arg s "$session" --arg m "$message" --argjson r "$request" --arg u "$url" --arg h "$(hostname)" '
    (if $r then "\($s): Claude wants to run \($r.tool)\(if $r.description then " (\($r.description))" else "" end)"
     else "\($s): \($m)" end) as $head
    | ($r.detail // null | if . then .[0:300] else null end) as $d
    | {session: $s, message: $m, url: (if $u == "" then null else $u end), host: $h,
       text: ($head + (if $d then "\n" + $d else "" end) + (if $u == "" then "" else "\nAnswer: " + $u end))}')

post "$body"
