#!/bin/sh
# Стабильный URL для Joplin на телефоне при Android-хотспоте: http://<подсеть>.100:8080
# Alias *.100 на en0 (DHCP primary не трогаем). LaunchAgent поднимает alias после reconnect.
#
#   ./joplin-hotspot-alias.sh status
#   ./joplin-hotspot-alias.sh ensure
#
# Passwordless: ./joplin-hotspot-alias-install-sudo.sh

set -e

CONFIG="${JOPLIN_WEBDAV_CONFIG:-$HOME/.config/joplin-webdav/env}"
WIFI_DEV="${WIFI_DEVICE:-en0}"
PORT="${JOPLIN_WEBDAV_PORT:-8080}"
LOG="$HOME/Library/Logs/joplin-webdav/alias.log"

ipv4_subnet() {
  printf '%s\n' "$1" | awk -F. '{print $1"."$2"."$3}'
}

ipv4_last_octet() {
  printf '%s\n' "$1" | awk -F. '{print $4}'
}

default_gateway() {
  route -n get default 2>/dev/null | awk '/gateway:/{print $2; exit}'
}

load_config() {
  if [ -f "$CONFIG" ]; then
    # shellcheck disable=SC1090
    . "$CONFIG"
  fi
  PORT="${JOPLIN_WEBDAV_PORT:-$PORT}"
}

joplin_phone_ip() {
  load_config
  gw="$(default_gateway 2>/dev/null || true)"
  [ -n "$gw" ] || return 1
  subnet="$(ipv4_subnet "$gw")"
  if [ -n "${JOPLIN_STATIC_IP:-}" ]; then
    last="$(ipv4_last_octet "$JOPLIN_STATIC_IP")"
  else
    last=100
  fi
  printf '%s\n' "${subnet}.${last}"
}

phone_url() {
  ip="$(joplin_phone_ip 2>/dev/null || true)"
  [ -n "$ip" ] || return 1
  printf 'http://%s:%s\n' "$ip" "$PORT"
}

has_ip_on_dev() {
  ip="$1"
  dev="$2"
  ifconfig "$dev" 2>/dev/null | grep -q "inet ${ip} "
}

log_msg() {
  mkdir -p "$(dirname "$LOG")"
  printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG"
}

run_priv() {
  if [ "$(id -u)" -eq 0 ]; then
    "$@"
  else
    sudo "$@"
  fi
}

write_phone_url_env() {
  url="$(phone_url 2>/dev/null || true)"
  [ -n "$url" ] && [ -f "$CONFIG" ] || return 0
  if grep -q '^JOPLIN_PHONE_URL=' "$CONFIG" 2>/dev/null; then
    sed -i '' "s|^JOPLIN_PHONE_URL=.*|JOPLIN_PHONE_URL=$url|" "$CONFIG" 2>/dev/null \
      || sed -i "s|^JOPLIN_PHONE_URL=.*|JOPLIN_PHONE_URL=$url|" "$CONFIG"
  else
    printf 'JOPLIN_PHONE_URL=%s\n' "$url" >>"$CONFIG"
  fi
}

cmd_status() {
  load_config
  target="$(joplin_phone_ip 2>/dev/null || true)"
  primary="$(ipconfig getifaddr "$WIFI_DEV" 2>/dev/null || true)"
  gw="$(default_gateway 2>/dev/null || true)"
  url="$(phone_url 2>/dev/null || true)"

  echo "mode:       Android-хотспот (alias *.100)"
  echo "device:     $WIFI_DEV"
  echo "primary:    ${primary:-(none)}"
  echo "gateway:    ${gw:-(none)}"
  echo "joplin IP:  ${target:-(no gateway)}"

  if [ -n "$target" ] && has_ip_on_dev "$target" "$WIFI_DEV"; then
    echo "alias:      OK"
  elif [ -n "$target" ] && [ "$primary" = "$target" ]; then
    echo "alias:      OK (primary)"
  elif [ -n "$target" ]; then
    echo "alias:      MISSING — телефон не достучится"
    echo "  fix: $0 ensure"
  fi

  if [ -n "$url" ]; then
    echo ""
    echo "URL на телефоне (работает с Android-хотспота):"
    echo "  $url"
    echo ""
    echo "⚠ http://*.local:8080 с телефона НЕ работает (Android не резолвит mDNS клиентов хотспота)"
  fi
}

cmd_ensure() {
  target="$(joplin_phone_ip 2>/dev/null || true)"
  if [ -z "$target" ]; then
    log_msg "skip: no gateway"
    exit 0
  fi
  primary="$(ipconfig getifaddr "$WIFI_DEV" 2>/dev/null || true)"
  if [ -z "$primary" ]; then
    log_msg "skip: no primary IP"
    exit 0
  fi
  if [ "$primary" = "$target" ] || has_ip_on_dev "$target" "$WIFI_DEV"; then
    write_phone_url_env
    exit 0
  fi
  log_msg "add alias $target on $WIFI_DEV (primary $primary)"
  run_priv ifconfig "$WIFI_DEV" inet "$target" netmask 255.255.255.0 alias
  write_phone_url_env
  echo "alias OK: $target"
  echo "URL на телефоне: $(phone_url)"
}

usage() {
  echo "Usage: $(basename "$0") status|ensure" >&2
  exit 1
}

case "${1:-ensure}" in
  status) cmd_status ;;
  ensure) cmd_ensure ;;
  -h|--help) usage ;;
  *) usage ;;
esac
