#!/bin/sh
# n9wrt — OpenWRT installer.
# Detects the router CPU, installs the n9d daemon + the LuCI app (Services -> n9wrt),
# and enables the service. Re-running it upgrades the binary/app without touching your config.
#
#   wget -qO- https://n9witch.com/downloads/openwrt/n9-install.sh | sh
#
set -e
BASE="https://n9witch.com/downloads/openwrt"

say() { echo "n9-install: $*"; }
have() { command -v "$1" >/dev/null 2>&1; }

# wget/uclient-fetch fallback (BusyBox wget can't always do https; uclient-fetch (libustream) can).
fetch() { # url dest
	if have uclient-fetch; then uclient-fetch -q -O "$2" "$1"; else wget -q -O "$2" "$1"; fi
}

# Map the router arch to one of our prebuilt binaries.
arch_suffix() {
	a=" $(opkg print-architecture 2>/dev/null | awk '{print $2}' | tr '\n' ' ') "
	case "$a" in
		*mipsel*) echo mipsle; return;;
		*mips_*)  echo mips;   return;;
		*aarch64*|*arm64*) echo arm64; return;;
		*arm_*)   echo armv7;  return;;
		*x86_64*) echo x86_64; return;;
	esac
	case "$(uname -m)" in
		aarch64|arm64) echo arm64;;
		armv7l|armv6l|arm) echo armv7;;
		x86_64|amd64) echo x86_64;;
		mips) echo mips;;
		*) echo "";;
	esac
}

SFX="$(arch_suffix)"
[ -n "$SFX" ] || { say "unsupported / undetected CPU arch (opkg print-architecture / uname -m)"; exit 1; }
say "CPU -> n9d-$SFX"

# TUN driver (required for the tunnel device). Often already built-in.
if have opkg && ! opkg list-installed 2>/dev/null | grep -q '^kmod-tun '; then
	say "installing kmod-tun…"
	opkg update >/dev/null 2>&1 || true
	opkg install kmod-tun >/dev/null 2>&1 || say "WARN: kmod-tun not installed (may be built into the kernel)"
fi

say "fetching LuCI app + init files…"
fetch "$BASE/n9-openwrt-files.tar.gz" /tmp/n9-files.tar.gz
tar -xzf /tmp/n9-files.tar.gz -C / && rm -f /tmp/n9-files.tar.gz
chmod 0755 /etc/init.d/n9
# Normalize perms/owner on everything the tarball delivered: root tar-extract preserves the tar's
# UID (a build-machine user) and uhttpd 403s any static file missing the world-read bit, so force
# root:root + 0644 regardless of what the archive (or a previous bad install) left behind.
chmod 0644 /www/luci-static/resources/view/n9/*.js /usr/share/luci/menu.d/luci-app-n9.json /usr/share/rpcd/acl.d/luci-app-n9.json 2>/dev/null || true
chown -R 0:0 /www/luci-static/resources/view/n9 2>/dev/null || true
chown 0:0 /etc/init.d/n9 /usr/share/luci/menu.d/luci-app-n9.json /usr/share/rpcd/acl.d/luci-app-n9.json 2>/dev/null || true
# Drop stale views the tarball no longer ships (tar extract adds/overwrites but never deletes) so an
# upgrade from an older layout doesn't keep the removed kill-switch page hanging around.
rm -f /www/luci-static/resources/view/n9/settings.js
rm -rf /tmp/luci-modulecache 2>/dev/null || true

# Default config — never clobber an existing one.
if [ ! -f /etc/config/n9 ]; then
	cat > /etc/config/n9 <<'CFG'
config n9 'main'
	option enabled '0'
	option link ''
	option transport 'udp'
	option node ''
	option route '0.0.0.0/0'
	option lan_masq '1'
	option killswitch '0'
	option ru_direct '1'
CFG
	say "wrote default /etc/config/n9"
fi

say "fetching daemon…"
# Fetch to a temp on the SAME filesystem as /usr/sbin, then atomically rename over the live binary.
# Writing /usr/sbin/n9d directly fails with ETXTBSY while the old daemon is running (a running
# executable can't be truncated — but it CAN be replaced via rename), which left upgrades stuck on
# the old binary. Rename swaps the inode; the running process keeps the old one until the restart below.
fetch "$BASE/n9d-$SFX" /usr/sbin/n9d.new
chmod 0755 /usr/sbin/n9d.new
mv -f /usr/sbin/n9d.new /usr/sbin/n9d

# Record the installed release so `/etc/init.d/n9 update` can tell the binary AND the web UI are both
# current (its "already latest" check compares this marker to the manifest version).
fetch "$BASE/n9d-latest.json" /tmp/n9-mf.json 2>/dev/null || true
MVER=$(sed -n 's/.*"version"[^"]*"\([^"]*\)".*/\1/p' /tmp/n9-mf.json 2>/dev/null)
rm -f /tmp/n9-mf.json
mkdir -p /etc/n9d; [ -n "$MVER" ] && echo "$MVER" > /etc/n9d/version

/etc/init.d/n9 enable 2>/dev/null || true
# Apply the freshly-installed binary + init script if the service is configured (no-op on a fresh
# install with no link yet) — otherwise an upgrade keeps running the previous binary until reboot.
/etc/init.d/n9 restart 2>/dev/null || true
# Refresh LuCI menu/ACL so «Services -> n9wrt» appears without a reboot.
rm -f /tmp/luci-indexcache 2>/dev/null || true
/etc/init.d/rpcd reload 2>/dev/null || true

say "installed. Open LuCI -> Services -> n9wrt, paste your link (HOST:8603/ACCESS_KEY), tick «Включить», Save & Apply."
say "CLI alt: uci set n9.main.link='HOST:8603/ACCESS_KEY'; uci set n9.main.enabled='1'; uci commit n9; /etc/init.d/n9 restart"
say "Check access without a tunnel:  /etc/init.d/n9 status"
