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

HOST="89.117.79.202"
USER="foster_bridge"
KEY="${MICHEL_SSH_KEY:-$HOME/.ssh/michel_windows_ed25519}"
EXPECTED_FP="SHA256:fRtAPoPhusxctqlacXUlrMLO7H+K66/nimb8ZPamShw"
REQUEST_PORT="18644"
CALLBACK_REMOTE_PORT="18645"
FOSTER_WEBHOOK_PORT="8765"
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$HOME/.config/foster-ask-michel"
CALLBACK_SECRET="$CONFIG_DIR/callback-secret"
UNIT="$HOME/.config/systemd/user/foster-michel-tunnel.service"
KNOWN_HOSTS="$HOME/.ssh/known_hosts"

[[ -f "$KEY" ]] || { echo "Missing SSH key: $KEY" >&2; exit 1; }
chmod 600 "$KEY"
mkdir -p "$CONFIG_DIR" "$(dirname "$UNIT")"
chmod 700 "$CONFIG_DIR"

# Pin and re-verify the Windows host key before retrieving the new callback secret.
scan="$(mktemp)"
trap 'rm -f "$scan"' EXIT
ssh-keyscan -T 8 -t ed25519 "$HOST" > "$scan" 2>/dev/null
actual_fp="$(ssh-keygen -lf "$scan" -E sha256 | awk 'NR==1 {print $2}')"
[[ "$actual_fp" == "$EXPECTED_FP" ]] || {
  echo "HOST KEY MISMATCH: expected $EXPECTED_FP, got $actual_fp" >&2; exit 1;
}

batch="$(mktemp)"
printf 'get michel-callback-route-secret.txt %s\n' "$CALLBACK_SECRET" > "$batch"
sftp -q -b "$batch" -i "$KEY" -o IdentitiesOnly=yes -o BatchMode=yes \
  -o StrictHostKeyChecking=yes "$USER@$HOST"
rm -f "$batch"
[[ -s "$CALLBACK_SECRET" ]] || { echo "Callback secret retrieval failed" >&2; exit 1; }
chmod 600 "$CALLBACK_SECRET"

# Resolve the active Foster Hermes home from the running gateway when possible.
if [[ -z "${FOSTER_HERMES_HOME:-}" ]]; then
  gateway_pid="$(pgrep -f 'hermes.*gateway|gateway.run' | head -n1 || true)"
  if [[ -n "$gateway_pid" && -r "/proc/$gateway_pid/environ" ]]; then
    FOSTER_HERMES_HOME="$(tr '\0' '\n' < "/proc/$gateway_pid/environ" | sed -n 's/^HERMES_HOME=//p' | head -n1)"
  fi
fi
FOSTER_HERMES_HOME="${FOSTER_HERMES_HOME:-$HOME/.hermes}"
[[ -d "$FOSTER_HERMES_HOME" ]] || {
  echo "Foster Hermes home not found: $FOSTER_HERMES_HOME" >&2; exit 1;
}

# Resolve the live Hermes Agent source tree without assuming an installation prefix.
if [[ -z "${FOSTER_AGENT_DIR:-}" ]]; then
  gateway_pid="${gateway_pid:-$(pgrep -f 'hermes.*gateway|gateway.run' | head -n1 || true)}"
  if [[ -n "$gateway_pid" && -e "/proc/$gateway_pid/cwd" ]]; then
    candidate="$(readlink -f "/proc/$gateway_pid/cwd" || true)"
    [[ -f "$candidate/toolsets.py" && -d "$candidate/tools" ]] && FOSTER_AGENT_DIR="$candidate"
  fi
fi
if [[ -z "${FOSTER_AGENT_DIR:-}" ]]; then
  for candidate in "$HOME/hermes-agent" "$HOME/.hermes/hermes-agent" /opt/hermes-agent; do
    [[ -f "$candidate/toolsets.py" && -d "$candidate/tools" ]] && { FOSTER_AGENT_DIR="$candidate"; break; }
  done
fi
[[ -n "${FOSTER_AGENT_DIR:-}" && -f "$FOSTER_AGENT_DIR/toolsets.py" ]] || {
  echo "Cannot locate Hermes Agent source. Re-run with FOSTER_AGENT_DIR=/absolute/path" >&2; exit 1;
}

install -m 600 "$HERE/ask_michel_tool.py" "$FOSTER_AGENT_DIR/tools/ask_michel_tool.py"

python - "$FOSTER_AGENT_DIR" "$FOSTER_HERMES_HOME" "$CALLBACK_SECRET" <<'PY'
import json, pathlib, shutil, sys, time
agent=pathlib.Path(sys.argv[1]); home=pathlib.Path(sys.argv[2]); secret_path=pathlib.Path(sys.argv[3])
secret=secret_path.read_text(encoding='ascii').strip()
if len(secret) < 32: raise SystemExit('Callback secret is unexpectedly short')

# Make the native tool visible in all normal Foster messaging toolsets.
toolsets=agent/'toolsets.py'
text=toolsets.read_text(encoding='utf-8')
if '"ask_michel_verify"' not in text:
    needle='    "read_terminal",\n'
    if text.count(needle) != 1: raise SystemExit('Cannot patch toolsets.py safely')
    text=text.replace(needle, needle+'    "ask_michel_verify",\n')
    toolsets.write_text(text, encoding='utf-8')

# Preserve reply-to anchors for deliver_only webhook routes.
webhook=agent/'gateway/platforms/webhook.py'
text=webhook.read_text(encoding='utf-8')
old='        return await adapter.send(chat_id, content, metadata=metadata)\n'
new=('        reply_to = extra.get("reply_to") or None\n'
     '        return await adapter.send(\n'
     '            chat_id, content, reply_to=reply_to, metadata=metadata\n'
     '        )\n')
if 'reply_to = extra.get("reply_to") or None' not in text:
    if text.count(old) != 1: raise SystemExit('Cannot patch webhook reply anchor safely')
    backup=webhook.with_suffix(f'.py.phase3-{int(time.time())}.bak')
    shutil.copy2(webhook, backup)
    webhook.write_text(text.replace(old,new),encoding='utf-8')

# Add an HMAC-authenticated, LLM-free result route that returns to the origin.
subs=home/'webhook_subscriptions.json'
data=json.loads(subs.read_text(encoding='utf-8')) if subs.exists() else {}
data['michel-result']={
    'secret': secret,
    'prompt': '🔎 Michel verification — request {request_id}\n\n{result}',
    'event_types': ['michel_verification_result'],
    'deliver': 'telegram',
    'deliver_only': True,
    'deliver_extra': {
        'chat_id': '{origin.chat_id}',
        'message_thread_id': '{origin.thread_id}',
        'reply_to': '{origin.message_id}',
    },
}
subs.parent.mkdir(parents=True,exist_ok=True)
subs.write_text(json.dumps(data,indent=2,ensure_ascii=False)+'\n',encoding='utf-8')

skill=home/'skills/ask-michel/SKILL.md'
skill.parent.mkdir(parents=True,exist_ok=True)
skill.write_text('''---
name: ask-michel
description: Delegate an MCSJ answer to Michel and route the verified result back to the originating Foster user.
---

# Ask Michel verification

When a user asks Foster to verify, confirm, check, or arbitrate an MCSJ answer with Michel:

1. Call `ask_michel_verify` once with the original question, Foster's proposed answer, relevant context, and screenshot flag.
2. Tell the user the verification was accepted and give the request ID.
3. Do not ask Saitz to relay the result. Michel's completed result returns asynchronously to this same chat/topic/message through Foster.
4. Do not use the standalone `ask-michel` CLI from a user chat; the native tool is required because it captures concurrency-safe origin metadata.
''',encoding='utf-8')
PY

# Enable Foster's loopback-only generic webhook listener.
HERMES_HOME="$FOSTER_HERMES_HOME" hermes config set platforms.webhook.enabled true >/dev/null
HERMES_HOME="$FOSTER_HERMES_HOME" hermes config set platforms.webhook.host 127.0.0.1 >/dev/null
HERMES_HOME="$FOSTER_HERMES_HOME" hermes config set platforms.webhook.port "$FOSTER_WEBHOOK_PORT" >/dev/null

# Replace the Phase 2 unit atomically: request tunnel Linux→Windows and result tunnel Windows→Linux.
tmp_unit="$(mktemp)"
cat > "$tmp_unit" <<EOF
[Unit]
Description=Foster and Michel signed bidirectional webhook tunnel
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/ssh -NT -i $KEY -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -L 127.0.0.1:$REQUEST_PORT:127.0.0.1:8644 -R 127.0.0.1:$CALLBACK_REMOTE_PORT:127.0.0.1:$FOSTER_WEBHOOK_PORT $USER@$HOST
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
EOF
install -m 600 "$tmp_unit" "$UNIT"
rm -f "$tmp_unit"
systemctl --user daemon-reload
systemctl --user restart foster-michel-tunnel.service

# Restart Foster Hermes so it discovers the native tool, subscription, and listener.
HERMES_HOME="$FOSTER_HERMES_HOME" hermes gateway restart >/dev/null

for _ in $(seq 1 30); do
  request_ok=0; callback_ok=0
  curl -fsS --max-time 2 "http://127.0.0.1:$REQUEST_PORT/health" >/dev/null && request_ok=1 || true
  curl -fsS --max-time 2 "http://127.0.0.1:$FOSTER_WEBHOOK_PORT/health" >/dev/null && callback_ok=1 || true
  [[ "$request_ok" == 1 && "$callback_ok" == 1 ]] && break
  sleep 1
done
curl -fsS --max-time 5 "http://127.0.0.1:$REQUEST_PORT/health" >/dev/null
curl -fsS --max-time 5 "http://127.0.0.1:$FOSTER_WEBHOOK_PORT/health" >/dev/null
systemctl --user is-active --quiet foster-michel-tunnel.service

python -m py_compile "$FOSTER_AGENT_DIR/tools/ask_michel_tool.py" "$FOSTER_AGENT_DIR/gateway/platforms/webhook.py"
printf 'FOSTER_HERMES_HOME=%s\n' "$FOSTER_HERMES_HOME"
printf 'FOSTER_AGENT_DIR=%s\n' "$FOSTER_AGENT_DIR"
printf 'SAL_PHASE3_STATUS=SUCCESS\n'
