#!/bin/bash
set -e
VERSION="1.3.0-live"
CONFIG_DIR="$HOME/.bhim"
CONFIG_FILE="$CONFIG_DIR/config.json"
PID_FILE="$CONFIG_DIR/tunnel.pid"
LOG_FILE="$CONFIG_DIR/tunnel.log"
CLIENT_DIR="$CONFIG_DIR/client"
STATIC_API_KEY="bhim_live_sk_tunnel_2024_static_key"
BASE_DOMAIN="tunnel.bhim.si"
SERVER_HOST="${BHIM_SERVER:-tunnel.bhim.si}"
WS_PORT="${BHIM_WS_PORT:-443}"
WS_PATH="${BHIM_WS_PATH:-/tunnel}"
WS_PROTOCOL="${BHIM_WS_PROTO:-wss}"
SERVER_IP="88.222.241.153"
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; CYAN='\033[0;36m'; NC='\033[0m'

ensure_config_dir(){ mkdir -p "$CONFIG_DIR" "$CLIENT_DIR"; }
get_config_value(){ python3 -c "import json,sys; d=json.load(open('$CONFIG_FILE')); print(d.get('$1',''))" 2>/dev/null || node -e "try{console.log(require('$CONFIG_FILE').$1||'')}catch{}" 2>/dev/null || echo ""; }
save_config(){
  local key=$1 sub=$2 port=$3 custom=$4
  python3 <<PY 2>/dev/null || true
import json, os
p=os.path.expanduser("~/.bhim/config.json")
d={}
try:
 import json as js; d=js.load(open(p))
except: pass
d['apiKey']= """$key"""
d['subdomain']= """$sub"""
d['port']= """$port"""
if """$custom""": d['customDomain']= """$custom"""
d['server']= """$SERVER_HOST"""
open(p,'w').write(json.dumps(d, indent=2))
PY
}
check_running(){ [ -f "$PID_FILE" ] && ps -p $(cat "$PID_FILE") >/dev/null 2>&1; }

print_help(){
echo -e "${CYAN}🚇 Bhim Tunnel v$VERSION${NC}
Cloudflare-style tunneling for $BASE_DOMAIN
${NC}
Usage:
  bhim tunnel start [--port 3000] [--subdomain myapp] [--api-key KEY] [--custom-domain dom.com] [--foreground]
  bhim tunnel stop | status | logs | restart
  bhim config set --api-key KEY --subdomain myapp
  bhim domain add <custom.com> --subdomain myapp
  bhim version / help

Examples:
  bhim tunnel start --port 3000 --subdomain a
  bhim tunnel start --port 8000 --subdomain hello --foreground
  curl https://$BASE_DOMAIN/install.sh | bash

Endpoints:
  https://<subdomain>.$BASE_DOMAIN  → localhost
  https://$BASE_DOMAIN/t/<subdomain>/ → always works even if *.tunnel DNS NXDOMAIN

Static Key (MVP): $STATIC_API_KEY
"
}

cmd_install_deps(){
  mkdir -p "$CLIENT_DIR"
  (cd "$CLIENT_DIR" && npm init -y >/dev/null 2>&1; npm install ws >/dev/null 2>&1 && echo "ws installed")
}
cmd_config_show(){ cat "$CONFIG_FILE" 2>/dev/null || echo "No config at $CONFIG_FILE"; }
cmd_config_set(){
  local api_key="" subdomain="" port="" custom_domain=""
  while [[ $# -gt 0 ]]; do case $1 in --api-key) api_key="$2"; shift 2;; --subdomain) subdomain="$2"; shift 2;; --port) port="$2"; shift 2;; --custom-domain) custom_domain="$2"; shift 2;; --server) SERVER_HOST="$2"; shift 2;; *) shift;; esac; done
  port=${port:-3000}; api_key=${api_key:-$STATIC_API_KEY}; subdomain=${subdomain:-myapp}
  ensure_config_dir; save_config "$api_key" "$subdomain" "$port" "$custom_domain"
  echo -e "${GREEN}Saved $CONFIG_FILE${NC}"; cat "$CONFIG_FILE"
}
cmd_tunnel_start(){
  local port="" subdomain="" api_key="" custom_domain="" host="127.0.0.1" foreground=false
  while [[ $# -gt 0 ]]; do case $1 in --port|-p) port="$2"; shift 2;; --subdomain|-s) subdomain="$2"; shift 2;; --api-key) api_key="$2"; shift 2;; --custom-domain|--domain) custom_domain="$2"; shift 2;; --host) host="$2"; shift 2;; --foreground|-f) foreground=true; shift;; --server) SERVER_HOST="$2"; shift 2;; --ws-port) WS_PORT="$2"; shift 2;; --ws-path) WS_PATH="$2"; shift 2;; --protocol) WS_PROTOCOL="$2"; shift 2;; *) if [[ "$1" =~ ^[0-9]+$ ]]; then port="$1"; shift; else shift; fi;; esac; done
  api_key=${api_key:-$(get_config_value apiKey)}; subdomain=${subdomain:-$(get_config_value subdomain)}; port=${port:-$(get_config_value port)}; custom_domain=${custom_domain:-$(get_config_value customDomain)}
  api_key=${api_key:-$STATIC_API_KEY}; subdomain=${subdomain:-myapp}; port=${port:-3000}
  ensure_config_dir
  local client_js="$CLIENT_DIR/tunnel-client.js"; [ -f "$(dirname "$0")/tunnel-client.js" ] && client_js="$(dirname "$0")/tunnel-client.js"; [ -f "./client/tunnel-client.js" ] && client_js="./client/tunnel-client.js"
  if [ ! -f "$client_js" ]; then echo "Client not found, downloading..."; mkdir -p "$CLIENT_DIR"; curl -fsSL "https://$BASE_DOMAIN/tunnel-client.js" -o "$CLIENT_DIR/tunnel-client.js" 2>/dev/null || curl -fsSL "http://$SERVER_HOST:3000/tunnel-client.js" -o "$CLIENT_DIR/tunnel-client.js" 2>/dev/null || curl -fsSL "http://$SERVER_IP:3000/tunnel-client.js" -o "$CLIENT_DIR/tunnel-client.js" 2>/dev/null || { echo "download failed"; exit 1; }; client_js="$CLIENT_DIR/tunnel-client.js"; fi
  if check_running; then echo -e "${YELLOW}Already running PID $(cat $PID_FILE). Use bhim tunnel stop${NC}"; return 0; fi
  if ! command -v node >/dev/null 2>&1; then echo -e "${RED}Node.js required${NC}"; exit 1; fi
  echo -e "${CYAN}Starting tunnel v$VERSION${NC}"; echo "  Subdomain: $subdomain"; echo "  Local: http://$host:$port"; echo "  Public1: https://$subdomain.$BASE_DOMAIN (needs wildcard A *.tunnel → $SERVER_IP)"; echo "  Public2: https://$BASE_DOMAIN/t/$subdomain/ (always works)"; [ -n "$custom_domain" ] && echo "  Custom: https://$custom_domain"; echo "  Server: $SERVER_HOST:$WS_PORT$WS_PATH ($WS_PROTOCOL)"; echo ""
  local node_args=("--subdomain" "$subdomain" "--port" "$port" "--api-key" "$api_key" "--server" "$SERVER_HOST" "--ws-port" "$WS_PORT" "--ws-path" "$WS_PATH" "--protocol" "$WS_PROTOCOL" "--host" "$host"); [ -n "$custom_domain" ] && node_args+=("--custom-domain" "$custom_domain")
  if [ "$foreground" = true ]; then NODE_PATH="$CLIENT_DIR/node_modules" node "$client_js" "${node_args[@]}"; else NODE_PATH="$CLIENT_DIR/node_modules" nohup node "$client_js" "${node_args[@]}" > "$LOG_FILE" 2>&1 & local pid=$!; echo $pid > "$PID_FILE"; sleep 2; if ps -p $pid >/dev/null 2>&1; then echo -e "${GREEN}✓ Tunnel started PID $pid${NC}"; echo "  URL: https://$subdomain.$BASE_DOMAIN → http://$host:$port"; echo "  URL2: https://$BASE_DOMAIN/t/$subdomain/ → http://$host:$port"; echo "  Logs: tail -f $LOG_FILE"; echo "  Stop: bhim tunnel stop"; tail -n 20 "$LOG_FILE" 2>/dev/null || true; else echo -e "${RED}Failed check $LOG_FILE${NC}"; cat "$LOG_FILE" 2>/dev/null; rm -f "$PID_FILE"; exit 1; fi; fi
  save_config "$api_key" "$subdomain" "$port" "$custom_domain" >/dev/null 2>&1 || true
}
cmd_tunnel_stop(){ if [ -f "$PID_FILE" ]; then local pid=$(cat "$PID_FILE"); if ps -p "$pid" >/dev/null 2>&1; then kill "$pid" && echo -e "${GREEN}✓ Stopped $pid${NC}" || echo -e "${RED}Kill fail${NC}"; else echo "No process $pid"; fi; rm -f "$PID_FILE"; else pkill -f "tunnel-client.js" && echo -e "${GREEN}✓ Stopped${NC}" || echo "No tunnel running"; fi; }
cmd_tunnel_status(){
  echo -e "${CYAN}Bhim Tunnel Status v$VERSION${NC}"; echo "-------------------"
  if check_running; then echo -e "Status: ${GREEN}Running PID $(cat $PID_FILE)${NC}"; cat "$CONFIG_FILE" 2>/dev/null; echo ""; tail -n 20 "$LOG_FILE" 2>/dev/null; else echo -e "Status: ${RED}Stopped${NC}"; cat "$CONFIG_FILE" 2>/dev/null || echo "No config"; fi; echo ""; echo "Server: https://$BASE_DOMAIN/api/status"; curl -sk "https://$BASE_DOMAIN/api/status" 2>&1 | head -c 500 || curl -s "http://$BASE_DOMAIN/api/status" 2>&1 | head -c 500 || curl -s "http://$SERVER_IP:3000/api/status" 2>/dev/null | head -c 500 || echo "(offline)"; echo "";
}
cmd_tunnel_logs(){ tail -f "$LOG_FILE" 2>/dev/null || echo "No log $LOG_FILE"; }
cmd_domain_add(){
  local custom_domain="" subdomain="" api_key=""
  while [[ $# -gt 0 ]]; do case $1 in --domain|--custom-domain) custom_domain="$2"; shift 2;; --subdomain) subdomain="$2"; shift 2;; --api-key) api_key="$2"; shift 2;; *) if [ -z "$custom_domain" ]; then custom_domain="$1"; fi; shift;; esac; done
  api_key=${api_key:-$(get_config_value apiKey)}; subdomain=${subdomain:-$(get_config_value subdomain)}; api_key=${api_key:-$STATIC_API_KEY}
  if [ -z "$custom_domain" ]; then echo "Usage: bhim domain add <yourdomain.com> --subdomain myapp"; exit 1; fi
  echo "Adding $custom_domain -> $subdomain.$BASE_DOMAIN via API..."; curl -sk -X POST "https://$BASE_DOMAIN/api/domain/add" -H "Content-Type: application/json" -d "{\"apiKey\":\"$api_key\",\"subdomain\":\"$subdomain\",\"customDomain\":\"$custom_domain\"}" 2>&1 | head -c 800 || curl -s -X POST "http://$SERVER_IP:3000/api/domain/add" -H "Content-Type: application/json" -d "{\"apiKey\":\"$api_key\",\"subdomain\":\"$subdomain\",\"customDomain\":\"$custom_domain\"}"; echo ""; echo -e "${YELLOW}DNS: CNAME $custom_domain -> $subdomain.$BASE_DOMAIN OR A -> $SERVER_IP${NC}"
}
case "${1:-help}" in
  tunnel) case "${2:-}" in start) shift 2; cmd_tunnel_start "$@";; stop) cmd_tunnel_stop;; status) cmd_tunnel_status;; logs) cmd_tunnel_logs;; restart) cmd_tunnel_stop; sleep 1; cmd_tunnel_start "$@";; *) print_help;; esac;;
  config) case "${2:-}" in set) shift 2; cmd_config_set "$@";; show|list|get) cmd_config_show;; *) cmd_config_show;; esac;;
  domain) case "${2:-}" in add) shift 2; cmd_domain_add "$@";; list) curl -sk https://$BASE_DOMAIN/api/status 2>/dev/null | python3 -m json.tool 2>/dev/null || curl -s http://$SERVER_IP:3000/api/status;; *) echo "Usage: bhim domain add <domain>";; esac;;
  install) cmd_install_deps;; version|--version|-v) echo "bhim v$VERSION";;
  help|--help|-h|"") print_help;;
  *) if [ "$1" = "start" ]; then shift; cmd_tunnel_start "$@"; elif [ "$1" = "stop" ]; then cmd_tunnel_stop; elif [ "$1" = "status" ]; then cmd_tunnel_status; else print_help; fi;;
esac
