#!/data/data/com.termux/files/usr/bin/bash
# =============================================================================
# gcp-phone-setup.sh — one-shot setup to expose a phone's SSH over the GCP relay
#
# Run this in a freshly installed Termux (Play Store build) on a NEW phone.
# It tunnels Termux's own sshd out through your GCP VM so you can reach this
# phone from anywhere at  ssh -i pc-access-key root@<VM_IP> -p <PORT>.
#
# You must first copy TWO small files onto this phone (any folder):
#   1) the VM access key  (the private key that logs in to the VM as the relay
#      user — reuse the SAME google_compute_engine key from your first phone)
#   2) the PC public key  (pc-access-key.pub — authorizes YOUR laptop/PC to ssh
#      into this phone)
#
# Usage:
#   bash gcp-phone-setup.sh --port 2223 \
#        --vm-key ./google_compute_engine \
#        --pc-pubkey ./pc-access-key.pub
#
# Options (with defaults):
#   --port N            REQUIRED. Unique VM port for this phone (2222-2240).
#   --vm-key PATH       REQUIRED. Private key to auth phone -> VM.
#   --pc-pubkey PATH    REQUIRED. Public key that may ssh INTO this phone.
#   --vm-ip IP          GCP VM external IP           (default 136.67.4.216)
#   --vm-user USER      SSH user on the VM           (default karthik)
#   --local-ssh-port N  Termux sshd port            (default 8022)
#   --low-battery N     Watchdog engages at N%      (default 20)
#   --no-boot           Do not install the Termux:Boot autostart script
#   --no-watchdog       Do not install the low-battery watchdog
#   -h | --help
# =============================================================================
set -uo pipefail

VM_IP="136.67.4.216"; VM_USER="karthik"; LOCAL_SSH_PORT="8022"
PORT=""; VM_KEY=""; PC_PUBKEY=""; LOW_BAT="20"
ENABLE_BOOT=1; ENABLE_WATCHDOG=1
BIN="/data/data/com.termux/files/usr/bin"
PREFIX="/data/data/com.termux/files/usr"

die() { echo "ERROR: $*" >&2; exit 1; }
usage() { sed -n '2,40p' "$0"; }

while [ $# -gt 0 ]; do
    case "$1" in
        --port)           PORT="${2:-}"; shift 2;;
        --vm-key)         VM_KEY="${2:-}"; shift 2;;
        --pc-pubkey)      PC_PUBKEY="${2:-}"; shift 2;;
        --vm-ip)          VM_IP="${2:-}"; shift 2;;
        --vm-user)        VM_USER="${2:-}"; shift 2;;
        --local-ssh-port) LOCAL_SSH_PORT="${2:-}"; shift 2;;
        --low-battery)    LOW_BAT="${2:-}"; shift 2;;
        --no-boot)        ENABLE_BOOT=0; shift;;
        --no-watchdog)    ENABLE_WATCHDOG=0; shift;;
        -h|--help)        usage; exit 0;;
        *) die "unknown argument: $1  (use --help)";;
    esac
done

[ -n "$PORT" ]      || die "--port is required"
[ -n "$VM_KEY" ]    || die "--vm-key is required"
[ -n "$PC_PUBKEY" ] || die "--pc-pubkey is required"
[ -f "$VM_KEY" ]    || die "vm key not found: $VM_KEY"
[ -f "$PC_PUBKEY" ] || die "pc pubkey not found: $PC_PUBKEY"
case "$PORT" in ''|*[!0-9]*) die "--port must be a number";; esac
if [ "$PORT" -lt 2222 ] || [ "$PORT" -gt 2240 ]; then
    echo "WARNING: port $PORT is outside the VM firewall range 2222-2240."
    echo "         Open it on the VM (allow-relay-range) or this will never connect."
fi

echo "==> [1/8] installing packages (openssh, termux-api, util-linux)"
yes | pkg update  >/dev/null 2>&1 || true
pkg install -y openssh termux-api util-linux >/dev/null 2>&1 \
    || die "pkg install failed — check network and rerun"
command -v "$BIN/flock" >/dev/null   || die "flock missing after install"
command -v "$BIN/sshd"  >/dev/null   || die "sshd missing after install"

echo "==> [2/8] generating Termux sshd host keys (if needed)"
ssh-keygen -A >/dev/null 2>&1 || true

echo "==> [3/8] authorizing your PC key + enforcing key-only login"
mkdir -p "$HOME/.ssh"; chmod 700 "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
cat "$PC_PUBKEY" >> "$HOME/.ssh/authorized_keys"
sort -u "$HOME/.ssh/authorized_keys" -o "$HOME/.ssh/authorized_keys"
chmod 600 "$HOME/.ssh/authorized_keys"
SSHD="$PREFIX/etc/ssh/sshd_config"
if grep -q "^Port " "$SSHD" 2>/dev/null; then
    sed -i "s/^Port .*/Port $LOCAL_SSH_PORT/" "$SSHD"
else
    echo "Port $LOCAL_SSH_PORT" >> "$SSHD"
fi
grep -q "^PasswordAuthentication no" "$SSHD" 2>/dev/null || echo "PasswordAuthentication no" >> "$SSHD"

echo "==> [4/8] installing VM access key"
install -m 600 "$VM_KEY" "$HOME/.ssh/gcp_vm_key"

echo "==> [5/8] writing relay config"
cat > "$HOME/.gcp-relay.conf" <<CONF
VM_IP="$VM_IP"
VM_USER="$VM_USER"
LOCAL_SSH_PORT="$LOCAL_SSH_PORT"
CONF
echo "$PORT" > "$HOME/.relay-port"

# pre-check: is this port already taken on the VM by another phone?
echo "==> checking VM port $PORT is free ..."
inuse=$(ssh -i "$HOME/.ssh/gcp_vm_key" -o StrictHostKeyChecking=accept-new \
        -o ConnectTimeout=15 "$VM_USER@$VM_IP" \
        "sudo ss -tlnH 2>/dev/null | grep -c ':$PORT '" 2>/dev/null || echo "?")
if [ "$inuse" = "1" ]; then
    die "port $PORT is already in use on the VM by another phone — pick a different --port"
elif [ "$inuse" = "?" ]; then
    echo "    (could not reach VM to pre-check; continuing — relay will retry if busy)"
else
    echo "    port $PORT is free"
fi

echo "==> [6/8] writing gcp_relay.sh"
cat > "$HOME/gcp_relay.sh" <<'RELAY'
#!/data/data/com.termux/files/usr/bin/bash
# Single reverse SSH tunnel to the GCP relay VM (Termux sshd -> VM:PORT).
# Singleton per port via flock (safe to launch repeatedly).
CONF="$HOME/.gcp-relay.conf"; [ -f "$CONF" ] && . "$CONF"
VM_IP="${VM_IP:-136.67.4.216}"; VM_USER="${VM_USER:-karthik}"
LOCAL_SSH_PORT="${LOCAL_SSH_PORT:-8022}"
REMOTE_PORT="${1:-$(cat "$HOME/.relay-port" 2>/dev/null || echo 2222)}"
VM_KEY="$HOME/.ssh/gcp_vm_key"
LOCK="$HOME/.gcp_relay.${REMOTE_PORT}.lock"
PIDFILE="$HOME/.gcp_relay.${REMOTE_PORT}.pid"

exec 9>"$LOCK"
if ! flock -n 9; then
    echo "[$(date '+%F %T')] relay for port $REMOTE_PORT already running — exiting"
    exit 0
fi
echo $$ > "$PIDFILE"
trap 'rm -f "$PIDFILE"' EXIT

while true; do
    echo "[$(date '+%F %T')] tunnel $VM_IP:$REMOTE_PORT -> localhost:$LOCAL_SSH_PORT ..."
    ssh -i "$VM_KEY" -o StrictHostKeyChecking=accept-new \
        -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
        -o ExitOnForwardFailure=yes -N \
        -R "0.0.0.0:${REMOTE_PORT}:localhost:${LOCAL_SSH_PORT}" "$VM_USER@$VM_IP" 9<&-
    echo "[$(date '+%F %T')] tunnel dropped (exit $?), retry in 5s"
    sleep 5
done
RELAY
chmod +x "$HOME/gcp_relay.sh"

if [ "$ENABLE_WATCHDOG" = 1 ]; then
echo "==> writing battery-watchdog.sh (engages at ${LOW_BAT}%)"
cat > "$HOME/battery-watchdog.sh" <<WD
#!/data/data/com.termux/files/usr/bin/bash
# On low battery + unplugged: release wakelock + sync so Android can shut down
# gracefully instead of dying mid-write (prevents /data corruption).
LOW=$LOW_BAT; RESUME=35; INTERVAL=60; LOG=\$HOME/battery-watchdog.log
BIN=/data/data/com.termux/files/usr/bin
command -v "\$BIN/termux-battery-status" >/dev/null 2>&1 || {
    echo "[\$(date '+%F %T')] termux-battery-status missing; watchdog NOT running" >> "\$LOG"; exit 1; }
echo "[\$(date '+%F %T')] watchdog started (LOW=\$LOW)" >> "\$LOG"; protected=0
while true; do
    js=\$("\$BIN/termux-battery-status" 2>/dev/null)
    pct=\$(printf '%s' "\$js" | grep -oE '"percentage": *[0-9]+' | grep -oE '[0-9]+')
    plug=\$(printf '%s' "\$js" | grep -oE '"plugged": *"[^"]*"' | sed -E 's/.*"([^"]*)"\$/\1/')
    [ -z "\$pct" ] && { sleep "\$INTERVAL"; continue; }
    if [ "\$protected" = 0 ] && [ "\$pct" -le "\$LOW" ] && [ "\$plug" = "UNPLUGGED" ]; then
        echo "[\$(date '+%F %T')] LOW \$pct% unplugged -> sync + wake-unlock" >> "\$LOG"
        sync; "\$BIN/termux-wake-unlock"; protected=1
    elif [ "\$protected" = 1 ] && [ "\$pct" -ge "\$RESUME" ] && [ "\$plug" != "UNPLUGGED" ]; then
        echo "[\$(date '+%F %T')] recovered \$pct% charging -> wake-lock" >> "\$LOG"
        "\$BIN/termux-wake-lock"; protected=0
    fi
    sleep "\$INTERVAL"
done
WD
chmod +x "$HOME/battery-watchdog.sh"
fi

echo "==> [7/8] wiring Termux ~/.bashrc autostart (idempotent)"
MARK="# >>> gcp-relay autostart >>>"
if ! grep -qF "$MARK" "$HOME/.bashrc" 2>/dev/null; then
cat >> "$HOME/.bashrc" <<'BRC'

# >>> gcp-relay autostart >>>
termux-wake-lock 2>/dev/null
sshd 2>/dev/null
setsid bash "$HOME/gcp_relay.sh" >> "$HOME/relay.log" 2>&1 </dev/null &
# <<< gcp-relay autostart <<<
BRC
fi

if [ "$ENABLE_BOOT" = 1 ]; then
echo "==> [8/8] installing Termux:Boot autostart script"
mkdir -p "$HOME/.termux/boot"
cat > "$HOME/.termux/boot/00-start-relay.sh" <<'BOOT'
#!/data/data/com.termux/files/usr/bin/bash
BIN=/data/data/com.termux/files/usr/bin
export PATH="$BIN:$PATH"
LOG="$HOME/boot.log"
echo "[$(date '+%F %T')] boot start" >> "$LOG"
[ -f "$HOME/battery-watchdog.sh" ] && $BIN/setsid $BIN/bash "$HOME/battery-watchdog.sh" >/dev/null 2>&1 </dev/null &
$BIN/termux-wake-lock
$BIN/sshd 2>/dev/null
$BIN/setsid $BIN/bash "$HOME/gcp_relay.sh" >> "$HOME/relay.log" 2>&1 </dev/null &
echo "[$(date '+%F %T')] boot launched sshd + relay" >> "$LOG"
BOOT
chmod +x "$HOME/.termux/boot/00-start-relay.sh"
else
echo "==> [8/8] skipping Termux:Boot script (--no-boot)"
fi

echo "==> starting sshd + relay now, and verifying ..."
sshd 2>/dev/null
termux-wake-lock 2>/dev/null
setsid bash "$HOME/gcp_relay.sh" >> "$HOME/relay.log" 2>&1 </dev/null &
sleep 12
if ssh -i "$HOME/.ssh/gcp_vm_key" -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15 \
      "$VM_USER@$VM_IP" "timeout 5 bash -c 'exec 3<>/dev/tcp/127.0.0.1/$PORT; head -1 <&3'" 2>/dev/null \
      | grep -q "SSH-2.0"; then
    RESULT="VERIFIED — tunnel is live"
else
    RESULT="not confirmed yet (may still be connecting; check ~/relay.log)"
fi

cat <<DONE

============================================================
 SETUP COMPLETE — $RESULT
============================================================
 Connect to THIS phone from your PC:
     ssh -i pc-access-key -p $PORT <your-user>@$VM_IP
   (the phone's Termux user is: $(whoami))

 Logs on this phone:   ~/relay.log   ~/boot.log   ~/battery-watchdog.log
 Stop / free the port: bash gcp-phone-teardown.sh

 To finish boot-autostart:
   1) install/open the Termux:Boot capability once
   2) realme/ColorOS: allow Termux auto-launch + set battery Unrestricted
   3) TEST the watchdog before trusting unattended boot:
        setsid bash ~/battery-watchdog.sh & ; sleep 2; cat ~/battery-watchdog.log
============================================================
DONE
