#!/usr/bin/env bash

# Debug
if [[ -n "${BBX_DEBUG}" ]]; then
  set -x
fi

# -----------------------------
# Global Variables / Defaults
# -----------------------------
OS_TYPE=""
TOR_INSTALLED=false
SUDO=""
TORRC=""
TORDIR=""
TOR_USER=""
TOR_GROUP=""
TOR_SERVICE="tor@default"  # Linux instance-based setups
torsslcerts="${HOME}/tor-sslcerts"
COOKIE_AUTH_FILE=""

# Timeouts (seconds)
TOR_CTRL_TIMEOUT="${TOR_CTRL_TIMEOUT:-5}"   # control-port connect/read
TOR_HS_TIMEOUT="${TOR_HS_TIMEOUT:-120}"     # wait for hostname files

# Debug flag: set BBX_TORBB_DEBUG=true to see Tor control interactions
TORBB_DEBUG="${BBX_TORBB_DEBUG:-false}"

log_dbg() { [[ "$TORBB_DEBUG" == "true" ]] && printf '[torbb:debug] %s\n' "$*" >&2; }
log_inf() { printf '[torbb] %s\n' "$*" >&2; }
log_err() { printf '[torbb:error] %s\n' "$*" >&2; }

if command -v sudo &>/dev/null; then
  SUDO="sudo -n"
fi

# Make sure our log dir/file exist so later 'tail' doesn't fail
mkdir -p "${HOME}/.config/dosyago/bbpro"
: > "${HOME}/.config/dosyago/bbpro/torbb_errors.txt" || true


# -----------------------------
# OS Detection & Paths
# -----------------------------
detect_os() {
  if [[ "$OSTYPE" == "darwin"* ]]; then
    OS_TYPE="macos"
    TOR_USER="$USER"
    TOR_GROUP="staff"   # Homebrew uses your login user; group 'staff' is safe default

    # Use the main Homebrew prefix for etc/ and var/
    local bprefix
    bprefix="$(brew --prefix 2>/dev/null || echo "/opt/homebrew")"

    TORRC="${bprefix}/etc/tor/torrc"
    TORDIR="${bprefix}/var/lib/tor"

    # Ensure directories exist
    mkdir -p "${bprefix}/etc/tor" "${TORDIR}"

    # If torrc is missing, try to copy sample; else create a minimal one
    if [[ ! -f "$TORRC" ]]; then
      if [[ -f "${bprefix}/etc/tor/torrc.sample" ]]; then
        cp "${bprefix}/etc/tor/torrc.sample" "$TORRC"
      else
        cat >"$TORRC" <<'MINITORRC'
# Minimal torrc generated by setup
DataDirectory __TORDIR__
ControlPort 9051
CookieAuthentication 1
# Avoid pidfile permission surprises under brew services
AvoidDiskWrites 1
MINITORRC
        # Fill in TORDIR
        sed -i '' -e "s#__TORDIR__#${TORDIR}#g" "$TORRC" 2>/dev/null || \
        sed -i -e "s#__TORDIR__#${TORDIR}#g" "$TORRC"
      fi
    fi

    COOKIE_AUTH_FILE="${TORDIR}/control_auth_cookie"
  elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
    if [ -f /etc/debian_version ]; then
      OS_TYPE="debian"; TOR_USER="debian-tor"; TOR_GROUP="debian-tor"
    elif [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
      OS_TYPE="centos"; TOR_USER="toranon"; TOR_GROUP="toranon"
    elif [ -f /etc/arch-release ]; then
      OS_TYPE="arch"; TOR_USER="tor"; TOR_GROUP="tor"
    elif [ -f /etc/amazon-linux-release ]; then
      OS_TYPE="centos"; TOR_USER="toranon"; TOR_GROUP="toranon"
    else
      log_err "Unsupported Linux distribution"; exit 1
    fi
    TORRC="/etc/tor/torrc"; TORDIR="/var/lib/tor"
  elif [[ "$OSTYPE" == "MINGW"* || "$OSTYPE" == "MSYS"* || "$OSTYPE" == "cygwin"* ]]; then
    OS_TYPE="win"; TOR_USER="$USER"; TOR_GROUP=""
    TORRC="$HOME/tor/torrc"; TORDIR="$HOME/tor/data"
  else
    log_err "Unsupported OS"; exit 1
  fi
  COOKIE_AUTH_FILE="$TORDIR/control_auth_cookie"
}

find_torrc_path() {
  if [[ "$OS_TYPE" == "macos" ]]; then
    local bprefix
    bprefix="$(brew --prefix 2>/dev/null || echo "/opt/homebrew")"
    TORRC="${bprefix}/etc/tor/torrc"
    TORDIR="${bprefix}/var/lib/tor"
    mkdir -p "${bprefix}/etc/tor" "${TORDIR}"

    if [[ ! -f "$TORRC" ]]; then
      if [[ -f "${bprefix}/etc/tor/torrc.sample" ]]; then
        cp "${bprefix}/etc/tor/torrc.sample" "$TORRC"
      else
        cat >"$TORRC" <<'MINITORRC'
DataDirectory __TORDIR__
ControlPort 9051
CookieAuthentication 1
AvoidDiskWrites 1
MINITORRC
        sed -i '' -e "s#__TORDIR__#${TORDIR}#g" "$TORRC" 2>/dev/null || \
        sed -i -e "s#__TORDIR__#${TORDIR}#g" "$TORRC"
      fi
    fi
  elif [[ "$OS_TYPE" == "win" ]]; then
    TORRC="${HOME}/tor/torrc"; TORDIR="${HOME}/tor/data"
    mkdir -p "$TORDIR"; [[ -f "$TORRC" ]] || touch "$TORRC"
  else
    TORRC="/etc/tor/torrc"; TORDIR="/var/lib/tor"
  fi
  COOKIE_AUTH_FILE="${TORDIR}/control_auth_cookie"
  echo "$TORRC"
}

# -----------------------------
# Group check (Linux only)
# -----------------------------
check_tor_group() {
  if [[ "$OS_TYPE" == "macos" || "$OS_TYPE" == "win" ]]; then
    log_dbg "No group check needed for $OS_TYPE"
  elif id -nG "$USER" | grep -qw "$TOR_GROUP"; then
    log_dbg "User $USER is in the correct Tor group ($TOR_GROUP)."
  else
    log_err "User $USER is not in the $TOR_GROUP group."
    echo "Please run 'sudo setup_tor $USER' to configure Tor for this user." >&2
    exit 1
  fi
}

# -----------------------------
# Package Manager
# -----------------------------
initialize_package_manager() {
  local package_manager
  if [[ "$OS_TYPE" == "macos" ]]; then
    package_manager=$(command -v brew)
  elif [[ "$OS_TYPE" == "win" ]]; then
    package_manager=$(command -v choco || command -v scoop)
  elif command -v apt &>/dev/null; then
    package_manager=$(command -v apt)
    if command -v apt-get &>/dev/null; then
      source non-interactive.sh >&2 || true
    fi
  elif command -v dnf >/dev/null 2>&1; then
    package_manager="$(command -v dnf) --best --allowerasing --skip-broken"
  elif command -v pacman >/dev/null 2>&1; then
    package_manager=$(command -v pacman)
  else
    log_err "No supported package manager found. Exiting."
    return 1
  fi
  log_inf "Using package manager: $package_manager"
  export APT=$package_manager
}

# -----------------------------
# Utilities
# -----------------------------
ensure_shutdown() { pm2 delete all >/dev/null 2>&1 || true; }
os_type() {
  case "$(uname -s)" in
    Darwin*) echo "macOS";;
    Linux*)  echo "Linux";;
    MING*|MSYS*|CYGWIN*) echo "win";;
    *)       echo "unknown";;
  esac
}

find_mkcert_root_ca() {
  local mkcert_dir=""
  mkcert_dir="$(mkcert -CAROOT 2>/dev/null || true)"
  if [[ -n "$mkcert_dir" ]]; then echo "$mkcert_dir"; return 0; fi
  case "$(uname)" in
    "Linux") mkcert_dir="${HOME}/.local/share/mkcert";;
    "Darwin") mkcert_dir="${HOME}/Library/Application Support/mkcert";;
    "MINGW"*|"MSYS"*|"CYGWIN"*) mkcert_dir="${HOME}/AppData/Local/mkcert";;
    *) log_err "Unsupported OS for mkcert root ca location finding"; return 1;;
  esac
  if [ -d "$mkcert_dir" ]; then echo "$mkcert_dir"; else echo "warning: mkcert directory not found." >&2; return 1; fi
}

get_normalized_arch() {
  local arch
  arch="$(dpkg --print-architecture 2>/dev/null || uname -m)"
  if [ "$arch" = "x86_64" ] || [ "$arch" = "amd64" ]; then echo "amd64"; else echo "$arch"; fi
}

setup_mkcert() {
  log_inf "Setting up mkcert..."
  if ! command -v mkcert &>/dev/null; then
    if [ "$OS_TYPE" == "macos" ]; then
      brew install nss mkcert
    elif [ "$OS_TYPE" == "win" ]; then
      choco install mkcert || { scoop bucket add extras && scoop install mkcert; }
    else
      local amd64; amd64="$(get_normalized_arch)"
      if [[ "$OS_TYPE" == "centos" ]]; then
        $SUDO $APT install -y nss-tools
      elif [[ "$OS_TYPE" == "debian" || "$OS_TYPE" == "arch" ]]; then
        $SUDO $APT install -y libnss3-tools
      fi
      curl -fsSL -o mkcert "https://dl.filippo.io/mkcert/latest?for=linux/${amd64}"
      chmod +x mkcert
      $SUDO mv mkcert /usr/local/bin/mkcert
    fi
    mkcert -install
  fi
}

# -----------------------------
# Tor Installation
# -----------------------------
install_tor() {
  if command -v tor &>/dev/null; then
    TOR_INSTALLED=true; log_inf "Tor is installed"; return
  fi
  case $OS_TYPE in
    debian)
      log_inf "Adding Tor repository for Debian..."
      $SUDO apt-get update
      $SUDO apt-get install -y apt-transport-https gpg wget
      wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --import
      gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | $SUDO apt-key add -
      echo "deb https://deb.torproject.org/torproject.org $(lsb_release -sc) main" | $SUDO tee /etc/apt/sources.list.d/tor.list
      $SUDO apt-get update
      $SUDO apt-get install -y tor deb.torproject.org-keyring
      TOR_INSTALLED=true
      ;;
    centos)
      $SUDO yum install -y epel-release || $SUDO dnf install -y epel-release
      $SUDO yum install -y tor || $SUDO dnf install -y tor
      TOR_INSTALLED=true
      ;;
    arch)
      $SUDO pacman -Sy --noconfirm tor
      TOR_INSTALLED=true
      ;;
    macos)
      brew install tor
      TOR_INSTALLED=true
      ;;
    win)
      log_err "Please install Tor manually on Windows: https://www.torproject.org/download/"
      exit 1
      ;;
  esac
}

# -----------------------------
# OS-pinned timeout + nc
# -----------------------------
TIMEOUT_CMD=""
require_timeout() {
  if [[ "$OS_TYPE" == "macos" ]]; then
    command -v gtimeout >/dev/null 2>&1 || { brew list coreutils >/dev/null 2>&1 || brew install coreutils; }
    command -v gtimeout >/dev/null 2>&1 || { log_err "gtimeout missing (brew install coreutils)"; return 1; }
    TIMEOUT_CMD="gtimeout"
  else
    command -v timeout >/dev/null 2>&1 || { log_err "timeout missing (install coreutils)"; return 1; }
    TIMEOUT_CMD="timeout"
  fi
}

build_nc_cmd() {
  local secs="${1:-5}"
  if [[ "$OS_TYPE" == "macos" ]]; then
    NC_CMD=( /usr/bin/nc -w "$secs" )      # macOS nc: -w works; avoid -N/-q
  else
    NC_CMD=( nc -q 0 -w "$secs" )          # GNU nc: -q 0 + -w works on Linux (fall back below if needed)
  fi
}

# Probe control port quickly
nc_probe() {
  local host="$1" port="$2" secs="${3:-5}"
  require_timeout || return 1
  build_nc_cmd "$secs"
  log_dbg "probe: ${TIMEOUT_CMD} ${secs} ${NC_CMD[*]} $host $port  (payload=PROTOCOLINFO/QUIT)"
  printf 'PROTOCOLINFO\r\nQUIT\r\n' | "$TIMEOUT_CMD" "$secs" "${NC_CMD[@]}" "$host" "$port" >/dev/null 2>&1 && return 0

  # Linux fallback: if -q 0 caused an error, retry without -q
  if [[ "$OS_TYPE" != "macos" ]]; then
    NC_CMD=( nc -w "$secs" )
    log_dbg "probe-fallback: ${TIMEOUT_CMD} ${secs} ${NC_CMD[*]} $host $port"
    printf 'PROTOCOLINFO\r\nQUIT\r\n' | "$TIMEOUT_CMD" "$secs" "${NC_CMD[@]}" "$host" "$port" >/dev/null 2>&1 && return 0
  fi
  return 1
}

# Send payload to control port (reads stdin). Returns nc exit status.
nc_send() {
  local host="$1" port="$2" secs="${3:-5}"
  require_timeout || return 1
  build_nc_cmd "$secs"
  log_dbg "send: ${TIMEOUT_CMD} ${secs} ${NC_CMD[*]} $host $port"
  "$TIMEOUT_CMD" "$secs" "${NC_CMD[@]}" "$host" "$port" 2>>"${HOME}/.config/dosyago/bbpro/torbb_errors.txt" || {
    local status=$?
    if [[ "$OS_TYPE" != "macos" ]]; then
      NC_CMD=( nc -w "$secs" )
      log_dbg "send-fallback: ${TIMEOUT_CMD} ${secs} ${NC_CMD[*]} $host $port"
      "$TIMEOUT_CMD" "$secs" "${NC_CMD[@]}" "$host" "$port" 2>>"${HOME}/.config/dosyago/bbpro/torbb_errors.txt"
      status=$?
    fi
    return $status
  }
}

# Control command with AUTH; outputs Tor's response to stdout
torctl_auth_send() {
  local port="$1"; local cookie_file="$2"; shift 2
  local cmd="$*"
  local cookie_hex
  cookie_hex="$(xxd -p "$cookie_file" 2>/dev/null | tr -d '\n')" || true
  [[ -z "$cookie_hex" ]] && { log_err "empty cookie"; return 1; }

  log_dbg "control-cmd(port=$port): $cmd"
  {
    printf 'AUTHENTICATE %s\r\n' "$cookie_hex"
    printf '%s\r\n' "$cmd"
    printf 'QUIT\r\n'
  } | nc_send 127.0.0.1 "$port" "$TOR_CTRL_TIMEOUT"
}

# -----------------------------
# Control-port hidden service (Linux path)
# -----------------------------
add_hidden_service_via_control_port() {
  local service_port="$1"
  local tor_control_port=9051
  local tor_cookie_file="$COOKIE_AUTH_FILE"
  if ! $SUDO test -f "$tor_cookie_file" && [[ -f "${HOME}/.tor/control_auth_cookie" ]]; then
    tor_cookie_file="${HOME}/.tor/control_auth_cookie"
  fi
  local tor_cookie_hex=""
  if [[ "$OS_TYPE" == "macos" || "$OS_TYPE" == "win" ]]; then
    tor_cookie_hex=$(xxd -u -p "$tor_cookie_file" 2>/dev/null | tr -d '\n')
  else
    tor_cookie_hex=$($SUDO xxd -u -p "$tor_cookie_file" 2>/dev/null | tr -d '\n')
  fi
  if [[ -z "$tor_cookie_hex" ]]; then
    log_err "Failed to read Tor control cookie from $tor_cookie_file"; exit 1
  fi
  local payload; payload=$(printf 'AUTHENTICATE %s\r\nADD_ONION NEW:ED25519-V3 Flags=Detach Port=443,127.0.0.1:%s\r\nQUIT\r\n' "$tor_cookie_hex" "$service_port")
  log_dbg "ADD_ONION via control on port $tor_control_port for 127.0.0.1:${service_port}"
  local response; response=$(printf '%s' "$payload" | nc_send 127.0.0.1 "$tor_control_port" "$TOR_CTRL_TIMEOUT" || true)
  log_dbg "ADD_ONION response: $(echo "$response" | tr '\n' ';' | sed 's/;*$//')"
  local onion_address; onion_address=$(echo "$response" | grep '^250-ServiceID=' | cut -d'=' -f2 | tr -d '[:space:]')
  if [[ -z "$onion_address" ]]; then
    log_err "Failed to obtain Onion address for port $service_port."
    exit 1
  fi
  echo "${onion_address}.onion"
}

# -----------------------------
# Wait helpers
# -----------------------------
wait_for_control_port() {
  local port="${1:-9051}"
  local deadline=$((SECONDS + TOR_CTRL_TIMEOUT + 10)) # a bit extra after restart/spawn
  while (( SECONDS < deadline )); do
    if nc_probe 127.0.0.1 "$port" "$TOR_CTRL_TIMEOUT"; then
      log_dbg "control port $port reachable"
      return 0
    fi
    sleep 1
  done
  log_err "Timeout waiting for Tor control port ${port} to listen."
  return 1
}

wait_for_hostnames() {
  local base_port=$((APP_PORT - 2))
  local deadline=$((SECONDS + TOR_HS_TIMEOUT))
  while (( SECONDS < deadline )); do
    local pending=0
    for i in {0..4}; do
      local service_port=$((base_port + i))
      local hidden_service_dir="${TORDIR}/hidden_service_${service_port}"
      if [[ ! -f "${hidden_service_dir}/hostname" ]]; then
        pending=1
      fi
    done
    if (( pending == 0 )); then
      log_dbg "All onion hostname files present."
      return 0
    fi
    sleep 1
  done
  log_err "Timeout waiting for onion hostname files (waited ${TOR_HS_TIMEOUT}s)."
  return 1
}

# -----------------------------
# macOS: choose control port + cookie
# -----------------------------
macos_pick_control_port_and_cookie() {
  local ports=()
  local conf_port
  conf_port="$(awk 'BEGIN{IGNORECASE=1} /^ControlPort[[:space:]]+/ {print $2; exit}' "$TORRC" 2>/dev/null || true)"
  [[ -n "$conf_port" ]] && ports+=("$conf_port")
  ports+=("9051" "9151")

  for p in "${ports[@]}"; do
    log_dbg "probing control port $p"
    if nc_probe 127.0.0.1 "$p" "$TOR_CTRL_TIMEOUT"; then
      local cookie="$TORDIR/control_auth_cookie"
      if [[ ! -f "$cookie" ]]; then
        local tb_cookie="${HOME}/Library/Application Support/TorBrowser-Data/Tor/control_auth_cookie"
        [[ -f "$tb_cookie" ]] && cookie="$tb_cookie"
      fi
      if [[ -f "$cookie" ]]; then
        echo "$p|$cookie"; return 0
      fi
    fi
  done
  return 1
}

# -----------------------------
# Configure Tor (macOS live-reload)
# -----------------------------
configure_and_export_tor() {
  local base_port=$((APP_PORT - 2))
  log_inf "Setting up tor hidden services..."

  # Ensure HS blocks exist and directories are secure
  for i in {0..4}; do
    local service_port=$((base_port + i))
    local hidden_service_dir="${TORDIR}/hidden_service_${service_port}"
    local dirLine="HiddenServiceDir ${hidden_service_dir}"
    if ! grep -qF -- "$dirLine" "$TORRC"; then
      echo "$dirLine" | $SUDO tee -a "$TORRC" >/dev/null
      echo "HiddenServicePort 443 127.0.0.1:${service_port}" | $SUDO tee -a "$TORRC" >/dev/null
    fi
    $SUDO mkdir -p "$hidden_service_dir"
    if [[ "$OS_TYPE" == "macos" ]]; then
      $SUDO chown "$USER:staff" "$hidden_service_dir" 2>/dev/null || true
      $SUDO chmod 700 "$hidden_service_dir"
    else
      $SUDO chown "${TOR_USER}:${TOR_GROUP}" "$hidden_service_dir"
      $SUDO chmod 770 "$hidden_service_dir"
    fi
  done

  if [[ "$OS_TYPE" == "macos" ]]; then
    # Try to attach and live-reload first
    local pick; pick="$(macos_pick_control_port_and_cookie || true)"
    if [[ -n "$pick" ]]; then
      local ctrl_port="${pick%%|*}"
      local cookie_file="${pick##*|}"
      log_inf "macOS: Found control port ${ctrl_port}; attempting SIGNAL RELOAD..."
      local resp
      resp="$(torctl_auth_send "$ctrl_port" "$cookie_file" "SIGNAL RELOAD" || true)"
      log_dbg "SIGNAL RELOAD response: $(echo "$resp" | tr '\n' ';' | sed 's/;*$//')"
      if grep -q '^250' <<<"$resp"; then
        log_inf "Tor config reloaded without restart."
      else
        log_inf "Reload failed; trying SIGNAL HUP via control..."
        resp="$(torctl_auth_send "$ctrl_port" "$cookie_file" "SIGNAL HUP" || true)"
        log_dbg "SIGNAL HUP response: $(echo "$resp" | tr '\n' ';' | sed 's/;*$//')"
        if ! grep -q '^250' <<<"$resp"; then
          log_inf "Signals failed; restarting Homebrew tor service..."
          brew services restart tor >/dev/null 2>&1 || true
          sleep 2
          if ! wait_for_control_port "$ctrl_port"; then
            log_inf "Control port not up; killing stray tor and starting ad-hoc..."
            pkill -x tor 2>/dev/null || true
            nohup tor -f "$TORRC" >/dev/null 2>&1 &
            wait_for_control_port "$ctrl_port" || { log_err "Tor not listening after ad-hoc start."; return 1; }
          fi
        fi
      fi
    else
      log_inf "macOS: No healthy control port; (re)starting Homebrew tor..."
      brew services restart tor >/dev/null 2>&1 || brew services start tor >/dev/null 2>&1 || true
      sleep 2
      if ! (nc_probe 127.0.0.1 9051 "$TOR_CTRL_TIMEOUT" || nc_probe 127.0.0.1 9151 "$TOR_CTRL_TIMEOUT"); then
        log_inf "Homebrew service didn't expose control port; killing and starting ad-hoc..."
        pkill -x tor 2>/dev/null || true
        nohup tor -f "$TORRC" >/dev/null 2>&1 &
        # try 9051 first, fallback 9151
        wait_for_control_port 9051 || wait_for_control_port 9151 || { log_err "Tor not listening after ad-hoc start."; return 1; }
      fi
    fi
  else
    log_inf "Restarting tor..."
    $SUDO systemctl restart "$TOR_SERVICE" &>/dev/null || true
    if [[ -f /.dockerenv ]] || ! systemctl is-active "$TOR_SERVICE" >/devnull 2>&1; then
      log_inf "Detected Docker or systemd failure, starting Tor manually..."
      $SUDO pkill -x tor 2>/dev/null || true
      if [[ "$OS_TYPE" == "centos" ]]; then
        $SUDO -u "$TOR_GROUP" nohup tor -f "$TORRC" >/dev/null 2>&1 &
      elif [[ "$OS_TYPE" == "debian" || "$OS_TYPE" == "arch" ]]; then
        $SUDO nohup tor -f "$TORRC" >/dev/null 2>&1 &
      fi
      sleep 2
      if ! pgrep -f tor >/dev/null; then
        log_err "Failed to start Tor manually"; exit 1
      fi
    fi
  fi

  log_inf "Waiting for onion services to connect..."
  wait_for_hostnames || { log_err "Hidden services didn't come up in time."; return 1; }

  log_inf "Creating HTTPS TLS certs for onion domains..."
  setup_mkcert
  for i in {0..4}; do
    local service_port=$((base_port + i))
    local hidden_service_dir="$TORDIR/hidden_service_${service_port}"
    local onion_address
    if [[ "$OS_TYPE" == "macos" || "$OS_TYPE" == "win" ]]; then
      onion_address="$(cat "${hidden_service_dir}/hostname")"
    else
      onion_address="$($SUDO cat "${hidden_service_dir}/hostname")"
    fi
    export "ADDR_${service_port}=${onion_address}"
    log_inf "$service_port $onion_address"
    local cert_dir="${torsslcerts}/${onion_address}"
    mkdir -p "$cert_dir"
    if ! mkcert -cert-file "${cert_dir}/fullchain.pem" -key-file "${cert_dir}/privkey.pem" "$onion_address" >/dev/null 2>&1; then
      log_err "mkcert failed for $onion_address"; exit 1
    fi
  done
}

# -----------------------------
# Firewall helper
# -----------------------------
get_ssh_port() {
  local ssh_port; ssh_port=$(grep -i '^Port ' /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}')
  [[ -z "$ssh_port" ]] && ssh_port=22
  echo "$ssh_port"
}

manage_firewall() {
  log_inf "Closing firewall (except ssh)..."
  case $OS_TYPE in
    debian|centos|arch)
      $SUDO ufw allow "$(get_ssh_port)" &>/dev/null || true
      $SUDO ufw --force enable &>/dev/null || true
      ;;
    macos)
      log_inf "Warning: Please ensure your firewall is enabled in macOS Settings."
      ;;
    win)
      log_inf "Warning: Configure Windows Firewall manually to allow SSH and Tor."
      ;;
  esac
}

# -----------------------------
# Main
# -----------------------------
{
  if command -v bbpro >/dev/null 2>&1; then
    log_inf "bbpro installed. proceeding..."
  else
    log_err "bbpro not installed. please run"
    echo "./deploy-scripts/global_install.sh localhost" >&2
    echo "before proceeding." >&2
    exit 1
  fi

  detect_os
  check_tor_group
  initialize_package_manager
  if command -v tor &>/dev/null; then TOR_INSTALLED=true; else install_tor; fi

  if [[ "$OS_TYPE" == "macos" ]]; then
    # Ensure DataDirectory is correct
    if ! grep -qiE "^DataDirectory[[:space:]]+${TORDIR}$" "$TORRC"; then
      # Replace existing DataDirectory or append if missing
      if grep -qiE "^DataDirectory[[:space:]]+" "$TORRC"; then
        # macOS sed needs backup suffix or empty string
        sed -i '' -e "s#^DataDirectory[[:space:]].*#DataDirectory ${TORDIR}#I" "$TORRC" 2>/dev/null || \
        sed -i -e "s#^DataDirectory[[:space:]].*#DataDirectory ${TORDIR}#I" "$TORRC"
      else
        printf '\nDataDirectory %s\n' "$TORDIR" >> "$TORRC"
      fi
    fi
  fi

  # bb env
  # shellcheck disable=SC1090
  source ~/.config/dosyago/bbpro/test.env || { log_err "bb environment not found. please run setup_bbpro first."; exit 1; }
  [ -z "${CONFIG_DIR:-}" ] && { log_err "CONFIG_DIR not set. Run setup_bbpro again."; exit 1; }
  [[ ${APP_PORT:-} =~ ^[0-9]+$ ]] || { log_err "Invalid APP_PORT"; exit 1; }

  # Optional repo config
  CONFIG_FILE="${CONFIG_DIR}/config"
  if [[ -f "$CONFIG_FILE" ]]; then
    log_inf "Sourcing $CONFIG_FILE..."
    # shellcheck disable=SC1090
    source "$CONFIG_FILE"
  else
    log_inf "No config file found at ${CONFIG_FILE}. Proceeding without it."
  fi

  # LICENSE_KEY prompt (unchanged)
  if [[ -z "${LICENSE_KEY:-}" ]]; then
    log_inf "LICENSE_KEY is required to proceed."
    while [[ -z "${LICENSE_KEY:-}" ]]; do
      read -p "Please enter your LICENSE_KEY: " LICENSE_KEY
      if [[ -z "$LICENSE_KEY" ]]; then log_err "LICENSE_KEY cannot be empty. Please try again."; fi
    done
    log_inf "LICENSE_KEY set."
  else
    log_inf "LICENSE_KEY is already set."
  fi

  log_inf "Ensuring any other bbpro $USER was running is shutdown..."
  ensure_shutdown

  find_torrc_path

  if [[ "$OS_TYPE" == "macos" || "$OS_TYPE" == "win" ]]; then
    [[ $TOR_INSTALLED == true ]] && configure_and_export_tor
    manage_firewall
  else
    manage_firewall
    base_port=$((APP_PORT - 2))
    log_inf "Setting up tor hidden services via Control Port..."
    for i in {0..4}; do
      service_port=$((base_port + i))
      onion_address="$(add_hidden_service_via_control_port "$service_port")"
      export "ADDR_${service_port}=${onion_address}"
      log_inf "Onion address for port ${service_port}: ${onion_address}"
      cert_dir="${torsslcerts}/${onion_address}"
      setup_mkcert
      mkdir -p "$cert_dir"
      if ! mkcert -cert-file "${cert_dir}/fullchain.pem" -key-file "${cert_dir}/privkey.pem" "$onion_address" >/dev/null 2>&1; then
        log_err "mkcert failed for $onion_address"; exit 1
      fi
    done
  fi

  cert_root=$(find_mkcert_root_ca || true)

  cat > "${CONFIG_DIR}/torbb.env" <<EOF
source "${CONFIG_DIR}/test.env"
export TORBB=true
export TORCA_CERT_ROOT="${cert_root}"
export SSLCERTS_DIR="${torsslcerts}"
EOF
  base_port=$((APP_PORT - 2))
  for i in {0..4}; do
    service_port=$((base_port + i))
    ref="ADDR_${service_port}"
    echo "export ${ref}=${!ref}" >> "${CONFIG_DIR}/torbb.env"
  done

  export TORBB=true
  echo -n "Starting bbpro..." >&2
  if ! bbpro &>/dev/null; then
    log_err "bbpro failed to start..."; exit 1
  fi
  echo "Started!" >&2
} >&2

# Final output
ref="ADDR_${APP_PORT}"
cert_file="${torsslcerts}/${!ref}/fullchain.pem"
DOMAIN="${!ref}"
LOGIN_LINK="https://${DOMAIN}/login?token=${LOGIN_TOKEN}"
echo "$LOGIN_LINK" > "${CONFIG_DIR}/login.link"
echo "Login link for Tor hidden service BB instance:" >&2
echo "$LOGIN_LINK"

