#!/bin/bash
# ─────────────────────────────────────────────────────────────────────────────
# ADS-B Feeder Installer
#
# Install:   curl -sSL https://phatfly.net/adsb-feeder/install.sh | sudo bash
# Uninstall: curl -sSL https://phatfly.net/adsb-feeder/install.sh | sudo bash -s -- --uninstall
#
# Or download and run:
#   wget https://phatfly.net/adsb-feeder/install.sh
#   sudo bash install.sh
# ─────────────────────────────────────────────────────────────────────────────

set -euo pipefail

VERSION="1.0.0"
DOWNLOAD_URL="https://phatfly.net/adsb-feeder/adsb-feeder-arm64.gz"

INSTALL_DIR="/opt/adsb-feeder"
CONFIG_DIR="/etc/adsb-feeder"
ENV_FILE="${CONFIG_DIR}/feeder.env"
SYSTEMD_DIR="/etc/systemd/system"

# ── Colors ──────────────────────────────────────────────────────────────────────

if [[ -t 1 ]]; then
    RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
    BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
else
    RED=''; GREEN=''; YELLOW=''; BLUE=''; CYAN=''; BOLD=''; DIM=''; NC=''
fi

info()  { echo -e "${BLUE}::${NC} $*"; }
ok()    { echo -e "${GREEN}✓${NC} $*"; }
warn()  { echo -e "${YELLOW}!${NC} $*"; }
err()   { echo -e "${RED}✗${NC} $*" >&2; }
step()  { echo -e "\n${CYAN}${BOLD}[$1/5]${NC} ${BOLD}$2${NC}"; }

# ── Defaults ────────────────────────────────────────────────────────────────────

FEEDER_LAT=""
FEEDER_LON=""
FEEDER_ID=""
NATS_MODE="tcp"
NATS_HOST="feeder.phatfly.net"
NATS_PORT="4444"
NATS_PATH="/nats"
FEEDER_ALT=""
BEAST_HOST="127.0.0.1"
BEAST_PORT="30005"
HTTP_PORT="8080"
BINARY_PATH=""
HTTP_PORT_SET=""
SKIP_READSB=false
UNINSTALL=false
NON_INTERACTIVE=false
ENV_PRESET=""

# ── Parse Args ──────────────────────────────────────────────────────────────────

while [[ $# -gt 0 ]]; do
    case "$1" in
        --lat)           FEEDER_LAT="$2"; shift 2 ;;
        --lon)           FEEDER_LON="$2"; shift 2 ;;
        --alt)           FEEDER_ALT="$2"; shift 2 ;;
        --feeder-id)     FEEDER_ID="$2"; shift 2 ;;
        --nats-mode)     NATS_MODE="$2"; shift 2 ;;
        --nats-host)     NATS_HOST="$2"; shift 2 ;;
        --nats-port)     NATS_PORT="$2"; shift 2 ;;
        --nats-path)     NATS_PATH="$2"; shift 2 ;;
        --beast-host)    BEAST_HOST="$2"; shift 2 ;;
        --beast-port)    BEAST_PORT="$2"; shift 2 ;;
        --http-port)     HTTP_PORT="$2"; HTTP_PORT_SET=1; shift 2 ;;
        --binary)        BINARY_PATH="$2"; shift 2 ;;
        --env)           ENV_PRESET="$2"; shift 2 ;;
        --skip-readsb)   SKIP_READSB=true; shift ;;
        --non-interactive) NON_INTERACTIVE=true; shift ;;
        --uninstall)     UNINSTALL=true; shift ;;
        -h|--help)
            echo "Usage: curl -sSL https://phatfly.net/adsb-feeder/install.sh | sudo bash"
            echo ""
            echo "Options:"
            echo "  --lat <float>         Feeder latitude (will prompt if not set)"
            echo "  --lon <float>         Feeder longitude (will prompt if not set)"
            echo "  --alt <float>         Antenna altitude in meters above sea level"
            echo "  --feeder-id <name>    Feeder name (default: hostname-based)"
            echo "  --env <sandbox|prod>  Environment preset (sets NATS host/port)"
            echo "  --skip-readsb         Don't install readsb"
            echo "  --non-interactive     Fail instead of prompting (for automation)"
            echo "  --binary <path>       Use local binary instead of downloading"
            echo "  --uninstall           Remove everything"
            echo "  -h, --help            Show this help"
            exit 0
            ;;
        *)  shift ;;
    esac
done

# ── Preflight ───────────────────────────────────────────────────────────────────

banner() {
    local WHITE='\033[1;37m'
    local GRAY='\033[0;90m'
    echo ""
    echo -e "${WHITE}${BOLD}        _           _    __ _                    _   ${NC}"
    echo -e "${WHITE}${BOLD}  _ __ | |__   __ _| |_ / _| |_   _   _ __   ___| |_ ${NC}"
    echo -e "${WHITE}${BOLD} | '_ \\| '_ \\ / _\` | __| |_| | | | | | '_ \\ / _ \\ __|${NC}"
    echo -e "${WHITE}${BOLD} | |_) | | | | (_| | |_|  _| | |_| |_| | | |  __/ |_ ${NC}"
    echo -e "${WHITE}${BOLD} | .__/|_| |_|\\__,_|\\__|_| |_|\\__, (_)_| |_|\\___|\\__|${NC}"
    echo -e "${WHITE}${BOLD} |_|                          |___/                  ${NC}"
    echo ""
    echo -e "  ${CYAN}ADS-B Feeder Installer${NC}  ${GRAY}v${VERSION}${NC}"
    echo ""
}

require_root() {
    if [[ $EUID -ne 0 ]]; then
        err "Please run as root:  sudo bash install.sh"
        exit 1
    fi
}

check_platform() {
    local arch
    arch=$(uname -m)
    if [[ "$arch" != "aarch64" ]]; then
        err "Requires a 64-bit Raspberry Pi (aarch64). Detected: $arch"
        exit 1
    fi
    if [[ ! -f /etc/os-release ]]; then
        err "Unsupported OS (missing /etc/os-release)"
        exit 1
    fi
    source /etc/os-release
    info "Platform: ${PRETTY_NAME} (${arch})"
}

can_prompt() {
    # Can we interact with the user? Works even when script is piped (curl | bash)
    # because /dev/tty is the controlling terminal regardless of stdin redirection
    ! $NON_INTERACTIVE && [[ -e /dev/tty ]]
}

prompt_value() {
    local var_name="$1" label="$2" default="${3:-}"
    local current="${!var_name}"

    [[ -n "$current" ]] && return

    # Non-interactive: use default or fail
    if ! can_prompt; then
        if [[ -n "$default" ]]; then
            eval "$var_name='$default'"
            return
        fi
        err "Missing required: $label (pass --$(echo "$var_name" | tr '[:upper:]' '[:lower:]' | tr '_' '-'))"
        exit 1
    fi

    # Read from /dev/tty so prompts work even when piped (curl | bash)
    local input
    if [[ -n "$default" ]]; then
        read -rp "  $label [$default]: " input < /dev/tty
        eval "$var_name='${input:-$default}'"
    else
        while true; do
            read -rp "  $label: " input < /dev/tty
            if [[ -n "$input" ]]; then
                eval "$var_name='$input'"
                return
            fi
            echo -e "  ${RED}Required${NC}"
        done
    fi
}

is_float() { [[ "$1" =~ ^-?[0-9]+\.?[0-9]*$ ]]; }

# ── Uninstall ───────────────────────────────────────────────────────────────────

do_uninstall() {
    banner
    require_root
    info "Uninstalling ADS-B Feeder..."

    systemctl stop adsb-feeder 2>/dev/null || true
    systemctl disable adsb-feeder 2>/dev/null || true

    # Only remove readsb if we installed it
    if [[ -f "${CONFIG_DIR}/.installed-readsb" ]]; then
        info "Removing readsb (installed by this script)..."
        systemctl stop readsb 2>/dev/null || true
        systemctl disable readsb 2>/dev/null || true
        rm -f "${SYSTEMD_DIR}/readsb.service" /usr/local/bin/readsb
        rm -f /etc/udev/rules.d/rtl-sdr.rules /etc/modprobe.d/rtl-sdr-blacklist.conf
    fi

    rm -f "${SYSTEMD_DIR}/adsb-feeder.service"
    rm -rf "${INSTALL_DIR}" "${CONFIG_DIR}"
    systemctl daemon-reload

    ok "ADS-B Feeder has been removed."
    echo ""
    echo -e "  To reinstall: ${BOLD}curl -sSL https://phatfly.net/adsb-feeder/install.sh | sudo bash${NC}"
    exit 0
}

# ── 1. Detect Beast Source ──────────────────────────────────────────────────────

BEAST_SOURCE=""

detect_beast() {
    step 1 "Checking for ADS-B receiver"

    if ss -tlnp 2>/dev/null | grep -q ":${BEAST_PORT} "; then
        for svc in readsb dump1090-fa dump1090; do
            if systemctl is-active --quiet "$svc" 2>/dev/null; then
                BEAST_SOURCE="$svc"
                break
            fi
        done
        BEAST_SOURCE="${BEAST_SOURCE:-unknown}"
        ok "Found ${BEAST_SOURCE} on port ${BEAST_PORT}"
        return 0
    fi

    # Installed but not running?
    for svc in readsb dump1090-fa dump1090; do
        if systemctl list-unit-files "${svc}.service" 2>/dev/null | grep -q "$svc"; then
            warn "${svc} is installed but not running"
            if can_prompt; then
                read -rp "  Start ${svc}? [Y/n] " answer < /dev/tty
                if [[ "${answer,,}" != "n" ]]; then
                    systemctl start "$svc"; sleep 2
                    if ss -tlnp 2>/dev/null | grep -q ":${BEAST_PORT} "; then
                        BEAST_SOURCE="$svc"
                        ok "Started ${svc}"
                        return 0
                    fi
                fi
            fi
        fi
    done

    warn "No ADS-B receiver found on port ${BEAST_PORT}"
    return 1
}

install_readsb() {
    info "Installing readsb (ADS-B receiver)..."
    apt-get update -qq
    apt-get install -y -qq build-essential pkg-config libncurses-dev librtlsdr-dev git

    rm -rf /tmp/readsb-build
    git clone --depth 1 https://github.com/wiedehopf/readsb.git /tmp/readsb-build
    cd /tmp/readsb-build && make -j"$(nproc)" RTLSDR=yes
    cp readsb /usr/local/bin/readsb
    cd / && rm -rf /tmp/readsb-build

    useradd --system --no-create-home --groups plugdev readsb 2>/dev/null || true

    # Udev + blacklist
    cat > /etc/udev/rules.d/rtl-sdr.rules <<'EOF'
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", GROUP="plugdev", MODE="0660", TAG+="uaccess"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", GROUP="plugdev", MODE="0660", TAG+="uaccess"
EOF
    cat > /etc/modprobe.d/rtl-sdr-blacklist.conf <<'EOF'
blacklist dvb_usb_rtl28xxu
blacklist rtl2832
blacklist rtl2830
EOF
    udevadm control --reload-rules 2>/dev/null || true

    local lat="${FEEDER_LAT:-0.0}" lon="${FEEDER_LON:-0.0}"
    cat > "${SYSTEMD_DIR}/readsb.service" <<UNIT
[Unit]
Description=readsb ADS-B receiver
After=network.target

[Service]
Type=simple
User=readsb
ExecStart=/usr/local/bin/readsb \\
    --device-type rtlsdr \\
    --gain -10 \\
    --ppm 0 \\
    --net \\
    --net-beast-reduce-interval 0 \\
    --net-connector 127.0.0.1,30005,beast_out \\
    --write-json /run/readsb \\
    --write-json-every 1 \\
    --json-location-accuracy 2 \\
    --lat ${lat} \\
    --lon ${lon}
RuntimeDirectory=readsb
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
UNIT

    systemctl daemon-reload
    systemctl enable --now readsb
    mkdir -p "${CONFIG_DIR}"
    touch "${CONFIG_DIR}/.installed-readsb"
    BEAST_SOURCE="readsb"
    ok "readsb installed and started"
}

# ── 2. Configure ────────────────────────────────────────────────────────────────

configure() {
    step 2 "Configuration"

    if [[ -f "$ENV_FILE" ]]; then
        info "Existing config found at ${ENV_FILE}"
        if can_prompt; then
            read -rp "  Overwrite? [y/N] " answer < /dev/tty
            [[ "${answer,,}" != "y" ]] && { ok "Keeping existing config"; return; }
        else
            ok "Keeping existing config"
            return
        fi
    fi

    echo -e "\n  ${BOLD}Where is your antenna located?${NC}"
    echo -e "  ${DIM}Tip: Right-click your location on Google Maps to copy coordinates${NC}"
    prompt_value FEEDER_LAT "Latitude (e.g. 44.9778)" ""
    prompt_value FEEDER_LON "Longitude (e.g. -93.2650)" ""
    prompt_value FEEDER_ALT "Antenna altitude ASL (e.g. 280m or 920ft)" "0"

    # Convert feet to meters if suffix provided
    if [[ "$FEEDER_ALT" =~ ^([0-9]+\.?[0-9]*)ft$ ]]; then
        local feet="${BASH_REMATCH[1]}"
        FEEDER_ALT=$(awk "BEGIN {printf \"%.1f\", $feet * 0.3048}")
        info "Converted ${feet}ft → ${FEEDER_ALT}m"
    elif [[ "$FEEDER_ALT" =~ ^([0-9]+\.?[0-9]*)m$ ]]; then
        FEEDER_ALT="${BASH_REMATCH[1]}"
    fi

    if ! is_float "$FEEDER_LAT" || ! is_float "$FEEDER_LON"; then
        err "Invalid coordinates"
        exit 1
    fi

    local default_id
    default_id="feeder-$(hostname -s | tr '[:upper:]' '[:lower:]')"
    prompt_value FEEDER_ID "Feeder name (e.g. feeder-mypi)" "$default_id"

    # Auto-detect dashboard port conflict — keep bumping until we find a free port
    if [[ -z "$HTTP_PORT_SET" ]]; then
        while ss -tlnp 2>/dev/null | grep -q ":${HTTP_PORT} "; do
            warn "Port ${HTTP_PORT} is already in use"
            HTTP_PORT=$((HTTP_PORT + 1))
        done
        if [[ "$HTTP_PORT" != "8080" ]]; then
            info "Using port ${HTTP_PORT} for dashboard"
            if can_prompt; then
                prompt_value HTTP_PORT "Dashboard port" "$HTTP_PORT"
            fi
        fi
    fi

    mkdir -p "${CONFIG_DIR}"
    cat > "${ENV_FILE}" <<CONF
# ADS-B Feeder — generated $(date -Iseconds)
FEEDER_ID=${FEEDER_ID}
BEAST_HOST=${BEAST_HOST}
BEAST_PORT=${BEAST_PORT}
NATS_MODE=${NATS_MODE}
NATS_HOST=${NATS_HOST}
NATS_PORT=${NATS_PORT}
NATS_PATH=${NATS_PATH}
FEEDER_LAT=${FEEDER_LAT}
FEEDER_LON=${FEEDER_LON}
FEEDER_ALT=${FEEDER_ALT}
HTTP_PORT=${HTTP_PORT}
CONF

    ok "Config saved to ${ENV_FILE}"
}

# ── 3. Download & Install Binary ───────────────────────────────────────────────

install_feeder() {
    step 3 "Installing feeder"

    mkdir -p "${INSTALL_DIR}"

    # Download/copy binary to temp location first
    local tmp_binary
    tmp_binary=$(mktemp /tmp/adsb-feeder.XXXXXX)

    if [[ -n "$BINARY_PATH" && -f "$BINARY_PATH" ]]; then
        info "Using local binary: ${BINARY_PATH}"
        if [[ "$BINARY_PATH" == *.gz ]]; then
            gunzip -c "$BINARY_PATH" > "$tmp_binary"
        else
            cp "$BINARY_PATH" "$tmp_binary"
        fi
    else
        info "Downloading latest release..."
        if command -v curl &>/dev/null; then
            curl -fSL --progress-bar "$DOWNLOAD_URL" | gunzip > "$tmp_binary"
        elif command -v wget &>/dev/null; then
            wget -q --show-progress -O - "$DOWNLOAD_URL" | gunzip > "$tmp_binary"
        else
            err "Need curl or wget to download. Install one or use --binary <path>"
            rm -f "$tmp_binary"
            exit 1
        fi
    fi

    chmod +x "$tmp_binary"

    # Stop running service before replacing binary (avoids "Text file busy")
    if systemctl is-active --quiet adsb-feeder 2>/dev/null; then
        info "Stopping running feeder service..."
        systemctl stop adsb-feeder
        sleep 1
    fi

    mv -f "$tmp_binary" "${INSTALL_DIR}/adsb-feeder"
    ok "Binary installed to ${INSTALL_DIR}/adsb-feeder"

    useradd --system --no-create-home adsb-feeder 2>/dev/null || true
    chown -R adsb-feeder:adsb-feeder "${INSTALL_DIR}"

    cat > "${SYSTEMD_DIR}/adsb-feeder.service" <<UNIT
[Unit]
Description=ADS-B Feeder
After=network-online.target readsb.service dump1090-fa.service
Wants=network-online.target

[Service]
Type=simple
User=adsb-feeder
WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${ENV_FILE}
ExecStart=${INSTALL_DIR}/adsb-feeder
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
UNIT

    systemctl daemon-reload
    systemctl enable --now adsb-feeder
    ok "Feeder service started"
}

# ── 4. Verify ──────────────────────────────────────────────────────────────────

verify() {
    step 4 "Verifying"
    sleep 2

    local all_ok=true

    if [[ -n "$BEAST_SOURCE" ]]; then
        if ss -tlnp 2>/dev/null | grep -q ":${BEAST_PORT} "; then
            ok "ADS-B receiver (${BEAST_SOURCE}) is running"
        else
            warn "ADS-B receiver not responding"
            all_ok=false
        fi
    fi

    if systemctl is-active --quiet adsb-feeder 2>/dev/null; then
        ok "Feeder service is running"
    else
        warn "Feeder service failed to start"
        echo -e "  ${DIM}Run: journalctl -u adsb-feeder -n 20${NC}"
        all_ok=false
    fi

    local ip
    ip=$(hostname -I 2>/dev/null | awk '{print $1}')

    step 5 "Done"
    if $all_ok; then
        echo ""
        echo -e "  ${GREEN}${BOLD}Installation successful!${NC}"
    else
        echo ""
        echo -e "  ${YELLOW}Installed with warnings (see above)${NC}"
    fi

    if [[ -n "$ip" ]]; then
        echo ""
        echo -e "  ${BOLD}Dashboard:${NC}  http://${ip}:${HTTP_PORT}/"
        echo -e "  ${BOLD}Logs:${NC}       sudo journalctl -u adsb-feeder -f"
        echo -e "  ${BOLD}Uninstall:${NC}  curl -sSL https://phatfly.net/adsb-feeder/install.sh | sudo bash -s -- --uninstall"
    fi
    echo ""
}

# ── Apply env preset ─────────────────────────────────────────────────────────

if [[ -n "$ENV_PRESET" ]]; then
    case "$ENV_PRESET" in
        sandbox)
            NATS_HOST="sandbox.phatfly.net"
            NATS_PORT="4443"
            NATS_MODE="tcp"
            ;;
        prod|production)
            NATS_HOST="feeder.phatfly.net"
            NATS_PORT="4444"
            NATS_MODE="tcp"
            ;;
        *)
            echo "Unknown environment: ${ENV_PRESET} (use 'sandbox' or 'prod')" >&2
            exit 1
            ;;
    esac
fi

# ── Main ────────────────────────────────────────────────────────────────────────

main() {
    banner
    require_root
    check_platform

    if $UNINSTALL; then
        do_uninstall
    fi

    # 1. Beast source
    if ! detect_beast; then
        if $SKIP_READSB; then
            info "Skipping receiver install (--skip-readsb)"
        elif can_prompt; then
            read -rp "  Install readsb (ADS-B receiver)? [Y/n] " answer < /dev/tty
            [[ "${answer,,}" != "n" ]] && install_readsb
        else
            install_readsb
        fi
    fi

    # 2. Config
    configure

    # 3. Binary
    install_feeder

    # 4. Verify
    verify
}

main
