#!/usr/bin/env bash
# =============================================================================
# Timmy node — status / diagnostics
# Run this any time to get a full health snapshot.
# Also machine-readable via: bash status.sh --json
# =============================================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SECRETS_FILE="$SCRIPT_DIR/.node-secrets"
LND_DIR="$HOME/.lnd"
LOG_DIR="$HOME/Library/Logs/timmy-node"
LNCLI="/opt/homebrew/bin/lncli"
BCLI="/opt/homebrew/bin/bitcoin-cli"
JSON_MODE=false
[[ "${1:-}" == "--json" ]] && JSON_MODE=true

[[ -f "$SECRETS_FILE" ]] && source "$SECRETS_FILE"

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
section() { $JSON_MODE || echo -e "\n${BOLD}${CYAN}── $* ──${NC}"; }
pass()    { $JSON_MODE || echo -e "  ${GREEN}✓${NC}  $*"; }
fail()    { $JSON_MODE || echo -e "  ${RED}✗${NC}  $*"; }
warn()    { $JSON_MODE || echo -e "  ${YELLOW}!${NC}  $*"; }

declare -A STATUS

# ─── Bitcoin Core ────────────────────────────────────────────────────────────
section "Bitcoin Core"

BTC_ARGS=()
[[ -n "${RPC_USER:-}" ]] && BTC_ARGS+=(-rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS")

if ! pgrep -x bitcoind &>/dev/null; then
  fail "bitcoind process not running"
  STATUS[bitcoind]="down"
else
  pass "bitcoind is running (PID: $(pgrep -x bitcoind))"
  STATUS[bitcoind]="running"

  if BTC_INFO=$("$BCLI" "${BTC_ARGS[@]}" getblockchaininfo 2>/dev/null); then
    CHAIN=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['chain'])")
    BLOCKS=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['blocks'])")
    HEADERS=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['headers'])")
    PROGRESS=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(f\"{d['verificationprogress']*100:.2f}%\")")
    PRUNED=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('pruned', False))")
    PRUNEHEIGHT=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('pruneheight', 'n/a'))")
    SIZE_ON_DISK=$(echo "$BTC_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(f\"{d.get('size_on_disk',0)/1e9:.1f} GB\")")

    pass "Chain: $CHAIN | Blocks: $BLOCKS / $HEADERS | Sync: $PROGRESS"
    pass "Pruned: $PRUNED (prune height: $PRUNEHEIGHT) | Disk: $SIZE_ON_DISK"
    STATUS[bitcoin_sync]="$PROGRESS"
    STATUS[bitcoin_blocks]="$BLOCKS"

    if MEMPOOL=$("$BCLI" "${BTC_ARGS[@]}" getmempoolinfo 2>/dev/null); then
      TXCOUNT=$(echo "$MEMPOOL" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['size'])")
      pass "Mempool: $TXCOUNT txs"
    fi

    NETINFO=$("$BCLI" "${BTC_ARGS[@]}" getnetworkinfo 2>/dev/null || echo "{}")
    PEERS=$(echo "$NETINFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('connections', '?'))")
    pass "Peers: $PEERS"
    STATUS[bitcoin_peers]="$PEERS"
  else
    warn "bitcoind is running but RPC not ready yet (starting up?)"
    STATUS[bitcoin_rpc]="not ready"
  fi
fi

# ─── LND ─────────────────────────────────────────────────────────────────────
section "LND"

if ! pgrep -x lnd &>/dev/null; then
  fail "lnd process not running"
  STATUS[lnd]="down"
else
  pass "lnd is running (PID: $(pgrep -x lnd))"
  STATUS[lnd]="running"

  if LND_INFO=$("$LNCLI" --lnddir="$LND_DIR" getinfo 2>/dev/null); then
    LND_VERSION=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['version'])" 2>/dev/null || echo "?")
    LND_ALIAS=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['alias'])" 2>/dev/null || echo "?")
    LND_SYNCED=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['synced_to_chain'])" 2>/dev/null || echo "?")
    LND_PEERS=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['num_peers'])" 2>/dev/null || echo "?")
    LND_CHANS=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['num_active_channels'])" 2>/dev/null || echo "?")
    LND_BLOCK=$(echo "$LND_INFO" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['block_height'])" 2>/dev/null || echo "?")

    pass "Version: $LND_VERSION | Alias: $LND_ALIAS"
    pass "Synced to chain: $LND_SYNCED | Block: $LND_BLOCK"
    pass "Peers: $LND_PEERS | Active channels: $LND_CHANS"
    STATUS[lnd_synced]="$LND_SYNCED"
    STATUS[lnd_channels]="$LND_CHANS"

    if BAL=$("$LNCLI" --lnddir="$LND_DIR" walletbalance 2>/dev/null); then
      CONFIRMED=$(echo "$BAL" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['confirmed_balance'])" 2>/dev/null || echo "?")
      UNCONFIRMED=$(echo "$BAL" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['unconfirmed_balance'])" 2>/dev/null || echo "?")
      pass "On-chain balance: ${CONFIRMED} sats confirmed, ${UNCONFIRMED} unconfirmed"
      STATUS[wallet_confirmed]="$CONFIRMED"
    fi

    if CHANBAL=$("$LNCLI" --lnddir="$LND_DIR" channelbalance 2>/dev/null); then
      LOCAL=$(echo "$CHANBAL" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['local_balance']['sat'])" 2>/dev/null || echo "?")
      REMOTE=$(echo "$CHANBAL" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['remote_balance']['sat'])" 2>/dev/null || echo "?")
      pass "Channel balance: ${LOCAL} sats local, ${REMOTE} sats remote"
      STATUS[channel_local]="$LOCAL"
    fi
  elif "$LNCLI" --lnddir="$LND_DIR" state 2>/dev/null | grep -q "WAITING_TO_START\|LOCKED"; then
    warn "LND wallet is LOCKED — run: lncli --lnddir=$LND_DIR unlock"
    STATUS[lnd_state]="locked"
  else
    warn "LND running but wallet not ready (still starting or needs creation)"
    STATUS[lnd_state]="not ready"
  fi
fi

# ─── LNbits ──────────────────────────────────────────────────────────────────
section "LNbits"
LNBITS_URL_LOCAL="http://127.0.0.1:5000"

if ! pgrep -f "lnbits" &>/dev/null; then
  fail "lnbits process not running"
  STATUS[lnbits]="down"
else
  pass "lnbits process is running"
  STATUS[lnbits]="running"

  if curl -sf "$LNBITS_URL_LOCAL/api/v1/health" &>/dev/null 2>&1; then
    pass "LNbits HTTP reachable at $LNBITS_URL_LOCAL"
    STATUS[lnbits_http]="ok"
  else
    warn "LNbits process is up but HTTP not responding yet (starting?)"
    STATUS[lnbits_http]="starting"
  fi
fi

# ─── Bore tunnel (if running) ─────────────────────────────────────────────────
section "Bore tunnel (external access)"
if BORE_PID=$(pgrep -f "bore local.*5000" 2>/dev/null); then
  BORE_CMD=$(ps -p "$BORE_PID" -o args= 2>/dev/null || echo "?")
  pass "bore tunnel active (PID $BORE_PID): $BORE_CMD"
  STATUS[bore]="active"
else
  warn "No bore tunnel running. Timmy (Replit) cannot reach LNbits."
  echo "      Start with: bash $SCRIPT_DIR/expose.sh"
  STATUS[bore]="down"
fi

# ─── Recent errors ────────────────────────────────────────────────────────────
section "Recent log errors (last 20 lines)"
for svc in bitcoind lnd lnbits; do
  ERR_FILE="$LOG_DIR/$svc.err"
  if [[ -f "$ERR_FILE" ]] && [[ -s "$ERR_FILE" ]]; then
    ERRS=$(tail -5 "$ERR_FILE" | grep -iE "error|fatal|panic|crit" || true)
    if [[ -n "$ERRS" ]]; then
      fail "$svc recent errors:"
      echo "$ERRS" | sed 's/^/      /'
      STATUS["${svc}_errors"]="yes"
    else
      pass "$svc error log: clean"
    fi
  fi
done

# ─── JSON output ─────────────────────────────────────────────────────────────
if $JSON_MODE; then
  echo "{"
  i=0; count=${#STATUS[@]}
  for k in "${!STATUS[@]}"; do
    i=$((i+1))
    comma=$([[ $i -lt $count ]] && echo "," || echo "")
    echo "  \"$k\": \"${STATUS[$k]}\"$comma"
  done
  echo "}"
  exit 0
fi

# ─── Summary ─────────────────────────────────────────────────────────────────
section "Summary"
ALL_OK=true
[[ "${STATUS[bitcoind]:-down}" != "running" ]] && { fail "bitcoind is down"; ALL_OK=false; }
[[ "${STATUS[lnd]:-down}" != "running" ]]     && { fail "lnd is down";      ALL_OK=false; }
[[ "${STATUS[lnbits]:-down}" != "running" ]]  && { fail "lnbits is down";   ALL_OK=false; }
[[ "${STATUS[bore]:-down}" != "active" ]]     && { warn "bore tunnel is down — Timmy can't reach LNbits"; }

$ALL_OK && echo -e "\n  ${GREEN}${BOLD}All core services are running.${NC}\n" || \
           echo -e "\n  ${RED}${BOLD}Some services need attention — see above.${NC}\n"
echo "  Run 'bash $SCRIPT_DIR/start.sh' to start stopped services."
echo "  Run 'bash $SCRIPT_DIR/expose.sh' to open the bore tunnel for Replit."
echo ""
