#!/bin/bash
# Hourly intraday monitor -- stop/target hits + missing-stop checks on open
# positions (check_positions.py), plus mechanical trigger_price_cad crossings
# on watchlist entries (check_watchlist_triggers.py, added 2026-08-12). Both
# are pure arithmetic against live_prices.json -- no web searches, no Claude
# invocation, no candidate scanning. Fires ONE push notification (via
# ntfy.sh) per run, batching every new trigger from both scripts together,
# only when something new fires. ntfy.sh needs no account/API key -- it's a
# plain HTTP POST to a topic name. Install the ntfy app and subscribe to the
# topic below.
#
# Topic lives in ntfy_alert.py (single source, shared with the Python-side
# alert callers) -- read from there instead of a second hardcoded copy here.
#
# Added 2026-08-28: a newly-crossed watchlist trigger no longer just sits as
# a passive alert waiting for tomorrow's scan -- KXS ran from its $157.47
# trigger to $178.76 (+13.5%) in one session with nothing but that passive
# alert firing, even though Questrade's own get_quotes/get_historical_data
# had the real numbers the whole time. For each newly-triggered ticker this
# run, a narrow headless claude -p call runs
# watchlist_trigger_reconfirm_prompt.md -- Questrade-only re-scoring (no web
# search), and auto-execution via the same Step 6 flow as run_daily_scan.sh
# if it genuinely still qualifies. This does not replace tomorrow's full
# Step 1c re-evaluation.

REPO=/media/raid/rshare/SwingTrader
cd "$REPO" || exit 1
NTFY_TOPIC=$(/usr/bin/python3 -c "from ntfy_alert import NTFY_TOPIC; print(NTFY_TOPIC)")

if ! /usr/bin/python3 "$REPO/is_trading_day.py"; then
    echo "$(date) TSX closed today -- skipping position check"
    exit 0
fi

POSITION_ALERTS=$(/usr/bin/python3 "$REPO/check_positions.py")
WATCHLIST_ALERTS=$(/usr/bin/python3 "$REPO/check_watchlist_triggers.py")
ALERTS=$(printf '%s\n%s\n' "$POSITION_ALERTS" "$WATCHLIST_ALERTS" | grep -v '^$')

# Fire the narrow reconfirm flow for each newly-crossed watchlist trigger,
# in the background so a slow/hung Questrade call can't delay this hour's
# stop/target alert above. One invocation per ticker (extracted as the first
# token of each "TICKER WATCHLIST TRIGGER: ..." line).
if [ -n "$WATCHLIST_ALERTS" ]; then
    echo "$WATCHLIST_ALERTS" | grep 'WATCHLIST TRIGGER' | awk '{print $1}' | sort -u | \
    while read -r TICKER; do
        [ -z "$TICKER" ] && continue
        /home/neilm/.local/bin/claude -p \
          --dangerously-skip-permissions \
          --allowedTools "Bash,Read,Write,mcp__Questrade__list_accounts,mcp__Questrade__get_balances,mcp__Questrade__get_positions,mcp__Questrade__search_symbols,mcp__Questrade__get_quotes,mcp__Questrade__get_historical_data,mcp__Questrade__preview_order_instruction,mcp__Questrade__create_order_instruction,mcp__Questrade__get_order_history" \
          >>"$REPO/daily_run.log" 2>&1 << REPROMPT &
Read /media/raid/rshare/SwingTrader/watchlist_trigger_reconfirm_prompt.md and execute it for
ticker $TICKER, whose watchlist trigger just crossed this hour.
REPROMPT
    done
fi

if [ -n "$ALERTS" ]; then
    echo "$(date) ALERT: $ALERTS"
    N=$(echo "$ALERTS" | grep -c .)
    MSG=$(echo "$ALERTS" | tr '\n' ' | ')
    # ntfy's practical limit is well above this, but cap generously and say so
    # instead of silently dropping alerts past the old 180-char cutoff.
    if [ "${#MSG}" -gt 1000 ]; then
        MSG="$(echo "$MSG" | cut -c1-970) ... (+more, see daily_run.log)"
    fi
    # Escalate to urgent priority if any stop-hit or missing-stop alert fired.
    PRIORITY="high"
    if echo "$ALERTS" | grep -qE "STOP HIT|NO STOP set"; then
        PRIORITY="urgent"
    fi
    curl -s \
      -H "Title: SwingTrader Alert ($N)" \
      -H "Priority: $PRIORITY" \
      -H "Tags: chart_with_upwards_trend" \
      -d "$MSG" \
      "https://ntfy.sh/$NTFY_TOPIC" > /dev/null
else
    echo "$(date) no new triggers"
fi
