#!/bin/sh
# Стабильный URL для Joplin: http://<подсеть>.100:8080
# Primary IP *.100 через networksetup (Android видит primary, alias — часто нет).
#
#   ./joplin-hotspot-alias.sh status
#   ./joplin-hotspot-alias.sh ensure|repair
#   ./joplin-hotspot-alias.sh dhcp          # вернуть DHCP (перед домашним Wi‑Fi)
#
# Passwordless: ./joplin-hotspot-alias-install-sudo.sh

set -e

CONFIG="${JOPLIN_WEBDAV_CONFIG:-$HOME/.config/joplin-webdav/env}"
WIFI_DEV="${WIFI_DEVICE:-en0}"
WIFI_SERVICE="${WIFI_SERVICE:-Wi-Fi}"
PORT="${JOPLIN_WEBDAV_PORT:-8080}"
LOG="$HOME/Library/Logs/joplin-webdav/alias.log"
NS="/usr/sbin/networksetup"

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} "
}

# Убрать *.100 alias с других подсетей (после смены хотспота / Wi‑Fi)
prune_stale_aliases() {
  target="$1"
  dev="$2"
  ifconfig "$dev" 2>/dev/null | awk '/inet / {print $2}' | while read -r ip; do
    case "$ip" in
      *.*.*.100)
        [ "$ip" = "$target" ] && continue
        ifconfig "$dev" -alias "$ip" 2>/dev/null || true
        log_msg "removed stale alias $ip"
        ;;
    esac
  done
}

is_android_hotspot_gw() {
  gw="$1"
  case "$gw" in
    10.*|172.20.10.*|192.168.43.*|192.168.44.*|192.168.49.*) return 0 ;;
    *) return 1 ;;
  esac
}

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

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:       static primary *.100 ($WIFI_SERVICE)"
  echo "device:     $WIFI_DEV"
  echo "primary:    ${primary:-(none)}"
  echo "gateway:    ${gw:-(none)}"
  echo "joplin IP:  ${target:-(no gateway)}"

  if [ -n "$gw" ] && ! is_android_hotspot_gw "$gw"; then
    echo "network:    домашний/роутер Wi‑Fi (не Android-хотспот)"
    echo "  → телефон должен быть в той же Wi‑Fi сети, что Mac"
  else
    echo "network:    похоже на Android-хотспот"
  fi

  if [ -n "$target" ]; then
    ifconfig "$WIFI_DEV" 2>/dev/null | awk -v t="$target" '/inet / { if ($2 ~ /\.100$/ && $2 != t) print "stale ifconfig: " $2 " (repair)" }'
  fi

  if [ -n "$target" ] && [ "$primary" = "$target" ]; then
    echo "static IP:  OK (primary = $target)"
  elif [ -n "$target" ]; then
    echo "static IP:  MISSING (primary $primary, нужен $target)"
    echo "  fix: $0 repair"
  fi

  if [ -n "$url" ]; then
    echo ""
    echo "URL на телефоне:"
    echo "  $url"
    echo ""
    echo "Проверка: браузер НА ТЕЛЕФОНЕ → URL → запрос логина за 2–3 сек"
    echo "Если браузер висит — телефон не видит Mac (не Joplin)"
    echo ""
    echo "⚠ http://*.local:8080 с телефона НЕ работает (Android не резолвит mDNS клиентов хотспота)"
  fi
}

cmd_ensure() {
  force=0
  [ "${1:-}" = --force ] && force=1
  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" ] && [ "$force" -eq 0 ]; then
    [ "$(id -u)" -ne 0 ] && write_phone_url_env
    exit 0
  fi
  if [ "$(id -u)" -ne 0 ]; then
    log_msg "setmanual $target (was $primary)"
    sudo_arg=ensure
    [ "$force" -eq 1 ] && sudo_arg="ensure --force"
    # shellcheck disable=SC2086
    if ! sudo -n "$0" $sudo_arg; then
      echo "static IP FAILED: нужен sudo." >&2
      echo "  один раз: ./docs/apps/joplin/scripts/joplin-hotspot-alias-install-sudo.sh" >&2
      echo "  затем:    $0 repair" >&2
      exit 1
    fi
    write_phone_url_env
    echo "static IP OK: $target"
    echo "URL на телефоне: $(phone_url)"
    exit 0
  fi
  gw="$(default_gateway 2>/dev/null || true)"
  [ -n "$gw" ] || { log_msg "skip: no gateway"; exit 1; }
  prune_stale_aliases "$target" "$WIFI_DEV"
  log_msg "networksetup -setmanual $target gw $gw [root]"
  "$NS" -setmanual "$WIFI_SERVICE" "$target" "255.255.255.255.0" "$gw"
}

cmd_dhcp() {
  if [ "$(id -u)" -ne 0 ]; then
    if ! sudo -n "$0" dhcp; then
      echo "Нужен sudo: sudo $NS -setdhcp \"$WIFI_SERVICE\"" >&2
      exit 1
    fi
    echo "Wi‑Fi → DHCP"
    exit 0
  fi
  "$NS" -setdhcp "$WIFI_SERVICE"
  log_msg "setdhcp $WIFI_SERVICE"
}

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

case "${1:-ensure}" in
  status) cmd_status ;;
  ensure) cmd_ensure "${2:-}" ;;
  repair) "$0" ensure --force ;;
  dhcp) cmd_dhcp ;;
  -h|--help) usage ;;
  *) usage ;;
esac
