#!/usr/bin/env bash
# install_service.sh
#
# Sets up RemoteTerm for MeshCore as a persistent systemd service running as
# the current user from the current repo directory. No separate service account
# is needed. After installation, git pull and rebuilds work without any sudo -u
# gymnastics.
#
# Run from anywhere inside the repo:
#   bash scripts/install_service.sh

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

SERVICE_NAME="remoteterm"
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CURRENT_USER="$(id -un)"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
FRONTEND_MODE="build"

echo -e "${BOLD}=== RemoteTerm for MeshCore — Service Installer ===${NC}"
echo

# ── sanity checks ──────────────────────────────────────────────────────────────

if [ "$(uname -s)" != "Linux" ]; then
    echo -e "${RED}Error: this script is for Linux (systemd) only.${NC}"
    exit 1
fi

if ! command -v systemctl &>/dev/null; then
    echo -e "${RED}Error: systemd not found. This script requires a systemd-based Linux system.${NC}"
    exit 1
fi

if ! command -v uv &>/dev/null; then
    echo -e "${RED}Error: 'uv' not found. Install it first:${NC}"
    echo    "  curl -LsSf https://astral.sh/uv/install.sh | sh"
    exit 1
fi

if ! command -v python3 &>/dev/null; then
    echo -e "${RED}Error: python3 is required but was not found.${NC}"
    exit 1
fi

UV_BIN="$(command -v uv)"
UVICORN_BIN="$REPO_DIR/.venv/bin/uvicorn"

echo -e "  Installing as user : ${CYAN}${CURRENT_USER}${NC}"
echo -e "  Repo directory     : ${CYAN}${REPO_DIR}${NC}"
echo -e "  Service name       : ${CYAN}${SERVICE_NAME}${NC}"
echo -e "  uv                 : ${CYAN}${UV_BIN}${NC}"
echo

version_major() {
    local version="$1"
    version="${version#v}"
    printf '%s' "${version%%.*}"
}

require_minimum_version() {
    local tool_name="$1"
    local detected_version="$2"
    local minimum_major="$3"
    local major
    major="$(version_major "$detected_version")"
    if ! [[ "$major" =~ ^[0-9]+$ ]] || [ "$major" -lt "$minimum_major" ]; then
        echo -e "${RED}Error: ${tool_name} ${minimum_major}+ is required for a local frontend build, but found ${detected_version}.${NC}"
        exit 1
    fi
}

# ── transport selection ────────────────────────────────────────────────────────

echo -e "${BOLD}─── Transport ───────────────────────────────────────────────────────${NC}"
echo "How is your MeshCore radio connected?"
echo "  1) Serial — auto-detect port (default)"
echo "  2) Serial — specify port manually"
echo "  3) TCP (network connection)"
echo "  4) BLE (Bluetooth)"
echo
read -rp "Select transport [1-4] (default: 1): " TRANSPORT_CHOICE
TRANSPORT_CHOICE="${TRANSPORT_CHOICE:-1}"
echo

NEED_DIALOUT=false
SERIAL_PORT=""
TCP_HOST=""
TCP_PORT=""
BLE_ADDRESS=""
BLE_PIN=""

case "$TRANSPORT_CHOICE" in
    1)
        echo -e "${GREEN}Serial auto-detect selected.${NC}"
        NEED_DIALOUT=true
        ;;
    2)
        read -rp "Serial port path (default: /dev/ttyUSB0): " SERIAL_PORT
        SERIAL_PORT="${SERIAL_PORT:-/dev/ttyUSB0}"
        echo -e "${GREEN}Serial port: ${SERIAL_PORT}${NC}"
        NEED_DIALOUT=true
        ;;
    3)
        read -rp "TCP host (IP address or hostname): " TCP_HOST
        while [ -z "$TCP_HOST" ]; do
            echo -e "${RED}TCP host is required.${NC}"
            read -rp "TCP host: " TCP_HOST
        done
        read -rp "TCP port (default: 4000): " TCP_PORT
        TCP_PORT="${TCP_PORT:-4000}"
        echo -e "${GREEN}TCP: ${TCP_HOST}:${TCP_PORT}${NC}"
        ;;
    4)
        read -rp "BLE device address (e.g. AA:BB:CC:DD:EE:FF): " BLE_ADDRESS
        while [ -z "$BLE_ADDRESS" ]; do
            echo -e "${RED}BLE address is required.${NC}"
            read -rp "BLE device address: " BLE_ADDRESS
        done
        read -rsp "BLE PIN: " BLE_PIN
        echo
        while [ -z "$BLE_PIN" ]; do
            echo -e "${RED}BLE PIN is required.${NC}"
            read -rsp "BLE PIN: " BLE_PIN
            echo
        done
        echo -e "${GREEN}BLE: ${BLE_ADDRESS}${NC}"
        ;;
    *)
        echo -e "${YELLOW}Invalid selection — defaulting to serial auto-detect.${NC}"
        TRANSPORT_CHOICE=1
        NEED_DIALOUT=true
        ;;
esac
echo

# ── frontend install mode ──────────────────────────────────────────────────────

echo -e "${BOLD}─── Frontend Assets ─────────────────────────────────────────────────${NC}"
echo "How should the frontend be installed?"
echo "  1) Build locally with npm (default, latest code, requires node/npm)"
echo "  2) Download prebuilt frontend (fastest)"
echo
read -rp "Select frontend mode [1-2] (default: 1): " FRONTEND_CHOICE
FRONTEND_CHOICE="${FRONTEND_CHOICE:-1}"
echo

case "$FRONTEND_CHOICE" in
    1)
        FRONTEND_MODE="build"
        echo -e "${GREEN}Using local frontend build.${NC}"
        ;;
    2)
        FRONTEND_MODE="prebuilt"
        echo -e "${GREEN}Using prebuilt frontend download.${NC}"
        ;;
    *)
        FRONTEND_MODE="build"
        echo -e "${YELLOW}Invalid selection — defaulting to local frontend build.${NC}"
        ;;
esac
echo

# ── bots ──────────────────────────────────────────────────────────────────────

echo -e "${BOLD}─── Bot System ──────────────────────────────────────────────────────${NC}"
echo -e "${YELLOW}Warning:${NC} The bot system executes arbitrary Python code on the server."
echo    "It is not recommended on untrusted networks. You can always enable"
echo    "it later by editing the service file."
echo
read -rp "Enable bots? [y/N]: " ENABLE_BOTS
ENABLE_BOTS="${ENABLE_BOTS:-N}"
echo

ENABLE_AUTH="N"
AUTH_USERNAME=""
AUTH_PASSWORD=""

if [[ "$ENABLE_BOTS" =~ ^[Yy] ]]; then
    echo -e "${GREEN}Bots enabled.${NC}"
    echo

    echo -e "${BOLD}─── HTTP Basic Auth ─────────────────────────────────────────────────${NC}"
    echo "With bots enabled, HTTP Basic Auth is strongly recommended if this"
    echo "service will be accessible beyond your local machine."
    echo
    read -rp "Set up HTTP Basic Auth? [Y/n]: " ENABLE_AUTH
    ENABLE_AUTH="${ENABLE_AUTH:-Y}"
    echo

    if [[ "$ENABLE_AUTH" =~ ^[Yy] ]]; then
        read -rp "Username: " AUTH_USERNAME
        while [ -z "$AUTH_USERNAME" ]; do
            echo -e "${RED}Username cannot be empty.${NC}"
            read -rp "Username: " AUTH_USERNAME
        done
        read -rsp "Password: " AUTH_PASSWORD
        echo
        while [ -z "$AUTH_PASSWORD" ]; do
            echo -e "${RED}Password cannot be empty.${NC}"
            read -rsp "Password: " AUTH_PASSWORD
            echo
        done
        echo -e "${GREEN}Basic Auth configured for user '${AUTH_USERNAME}'.${NC}"
        echo -e "${YELLOW}Note:${NC} Basic Auth credentials are not safe over plain HTTP."
        echo    "See README_ADVANCED.md for HTTPS setup."
    fi
else
    echo -e "${GREEN}Bots disabled.${NC}"
fi
echo

# ── python dependencies ────────────────────────────────────────────────────────

echo -e "${YELLOW}Installing Python dependencies (uv sync)...${NC}"
cd "$REPO_DIR"
uv sync
echo -e "${GREEN}Dependencies ready.${NC}"
echo

# ── frontend assets ────────────────────────────────────────────────────────────

if [ "$FRONTEND_MODE" = "build" ]; then
    if ! command -v node &>/dev/null; then
        echo -e "${RED}Error: node is required for a local frontend build but was not found.${NC}"
        echo -e "${YELLOW}Tip:${NC} Re-run the installer and choose the prebuilt frontend option, or install Node.js 18+ and npm 9+."
        exit 1
    fi
    if ! command -v npm &>/dev/null; then
        echo -e "${RED}Error: npm is required for a local frontend build but was not found.${NC}"
        echo -e "${YELLOW}Tip:${NC} Re-run the installer and choose the prebuilt frontend option, or install Node.js 18+ and npm 9+."
        exit 1
    fi

    NODE_VERSION="$(node -v)"
    NPM_VERSION="$(npm -v)"
    require_minimum_version "Node.js" "$NODE_VERSION" 18
    require_minimum_version "npm" "$NPM_VERSION" 9

    echo -e "${YELLOW}Building frontend locally with Node ${NODE_VERSION} and npm ${NPM_VERSION}...${NC}"
    (
        cd "$REPO_DIR/frontend"
        npm install
        npm run build
    )
else
    echo -e "${YELLOW}Fetching prebuilt frontend...${NC}"
    python3 "$REPO_DIR/scripts/fetch_prebuilt_frontend.py"
fi
echo

# ── data directory ─────────────────────────────────────────────────────────────

mkdir -p "$REPO_DIR/data"

# ── serial port access ─────────────────────────────────────────────────────────

if [ "$NEED_DIALOUT" = true ]; then
    if ! id -nG "$CURRENT_USER" | grep -qw dialout; then
        echo -e "${YELLOW}Adding ${CURRENT_USER} to the 'dialout' group for serial port access...${NC}"
        sudo usermod -aG dialout "$CURRENT_USER"
        echo -e "${GREEN}Done. You may need to log out and back in for this to take effect for${NC}"
        echo -e "${GREEN}manual runs; the service itself handles it via SupplementaryGroups.${NC}"
        echo
    else
        echo -e "${GREEN}User ${CURRENT_USER} is already in the 'dialout' group.${NC}"
        echo
    fi
fi

# ── systemd service file ───────────────────────────────────────────────────────

if sudo systemctl is-active --quiet "$SERVICE_NAME"; then
    echo -e "${YELLOW}${SERVICE_NAME} is currently running; stopping it before applying changes...${NC}"
    sudo systemctl stop "$SERVICE_NAME"
    echo
fi

echo -e "${YELLOW}Writing systemd service file to ${SERVICE_FILE}...${NC}"

generate_service_file() {
    echo "[Unit]"
    echo "Description=RemoteTerm for MeshCore"
    echo "After=network.target"
    echo ""
    echo "[Service]"
    echo "Type=simple"
    echo "User=${CURRENT_USER}"
    echo "WorkingDirectory=${REPO_DIR}"
    echo "ExecStart=${UVICORN_BIN} app.main:app --host 0.0.0.0 --port 8000"
    echo "Restart=always"
    echo "RestartSec=5"
    echo "Environment=MESHCORE_DATABASE_PATH=${REPO_DIR}/data/meshcore.db"

    # Transport
    case "$TRANSPORT_CHOICE" in
        2) echo "Environment=MESHCORE_SERIAL_PORT=${SERIAL_PORT}" ;;
        3)
            echo "Environment=MESHCORE_TCP_HOST=${TCP_HOST}"
            echo "Environment=MESHCORE_TCP_PORT=${TCP_PORT}"
            ;;
        4)
            echo "Environment=MESHCORE_BLE_ADDRESS=${BLE_ADDRESS}"
            echo "Environment=MESHCORE_BLE_PIN=${BLE_PIN}"
            ;;
    esac

    # Bots
    if [[ ! "$ENABLE_BOTS" =~ ^[Yy] ]]; then
        echo "Environment=MESHCORE_DISABLE_BOTS=true"
    fi

    # Basic auth
    if [[ "$ENABLE_BOTS" =~ ^[Yy] ]] && [[ "$ENABLE_AUTH" =~ ^[Yy] ]]; then
        echo "Environment=MESHCORE_BASIC_AUTH_USERNAME=${AUTH_USERNAME}"
        echo "Environment=MESHCORE_BASIC_AUTH_PASSWORD=${AUTH_PASSWORD}"
    fi

    # Serial group access
    if [ "$NEED_DIALOUT" = true ]; then
        echo "SupplementaryGroups=dialout"
    fi

    echo ""
    echo "[Install]"
    echo "WantedBy=multi-user.target"
}

generate_service_file | sudo tee "$SERVICE_FILE" > /dev/null

echo -e "${GREEN}Service file written.${NC}"
echo

# ── enable and start ───────────────────────────────────────────────────────────

echo -e "${YELLOW}Reloading systemd and applying ${SERVICE_NAME}...${NC}"
sudo systemctl daemon-reload
sudo systemctl enable "$SERVICE_NAME"
sudo systemctl start "$SERVICE_NAME"
echo

# ── status check ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}Service status:${NC}"
sudo systemctl status "$SERVICE_NAME" --no-pager -l || true
echo

# ── summary ────────────────────────────────────────────────────────────────────

echo -e "${GREEN}${BOLD}=== Installation complete! ===${NC}"
echo
echo -e "RemoteTerm is running at ${CYAN}http://$(hostname -I | awk '{print $1}'):8000${NC}"
echo

case "$TRANSPORT_CHOICE" in
    1) echo -e "  Transport : ${CYAN}Serial (auto-detect)${NC}" ;;
    2) echo -e "  Transport : ${CYAN}Serial (${SERIAL_PORT})${NC}" ;;
    3) echo -e "  Transport : ${CYAN}TCP (${TCP_HOST}:${TCP_PORT})${NC}" ;;
    4) echo -e "  Transport : ${CYAN}BLE (${BLE_ADDRESS})${NC}" ;;
esac
if [ "$FRONTEND_MODE" = "build" ]; then
    echo -e "  Frontend  : ${GREEN}Built locally${NC}"
else
    echo -e "  Frontend  : ${YELLOW}Prebuilt download${NC}"
fi

if [[ "$ENABLE_BOTS" =~ ^[Yy] ]]; then
    echo -e "  Bots      : ${YELLOW}Enabled${NC}"
    if [[ "$ENABLE_AUTH" =~ ^[Yy] ]]; then
        echo -e "  Basic Auth: ${GREEN}Enabled (user: ${AUTH_USERNAME})${NC}"
    else
        echo -e "  Basic Auth: ${YELLOW}Not configured${NC}"
    fi
else
    echo -e "  Bots      : ${GREEN}Disabled${NC} (edit ${SERVICE_FILE} to enable)"
fi
echo

if [ "$FRONTEND_MODE" = "prebuilt" ]; then
    echo -e "${YELLOW}Note:${NC} A prebuilt frontend has been fetched and installed. It may lag"
    echo    "behind the latest code. To build the frontend from source for the most"
    echo    "up-to-date features later, run:"
    echo
    echo -e "  ${CYAN}cd ${REPO_DIR}/frontend && npm install && npm run build${NC}"
    echo
fi

echo -e "${BOLD}─── Quick Reference ─────────────────────────────────────────────────${NC}"
echo
echo -e "${YELLOW}Update to latest and restart:${NC}"
echo -e "  cd ${REPO_DIR}"
echo -e "  git pull"
echo -e "  uv sync"
echo -e "  cd frontend && npm install && npm run build && cd .."
echo -e "  sudo systemctl restart ${SERVICE_NAME}"
echo
echo -e "${YELLOW}Refresh prebuilt frontend only (skips local build):${NC}"
echo -e "  python3 ${REPO_DIR}/scripts/fetch_prebuilt_frontend.py"
echo -e "  sudo systemctl restart ${SERVICE_NAME}"
echo
echo -e "${YELLOW}View live logs (useful for troubleshooting):${NC}"
echo -e "  sudo journalctl -u ${SERVICE_NAME} -f"
echo
echo -e "${YELLOW}Service control:${NC}"
echo -e "  sudo systemctl start|stop|restart|status ${SERVICE_NAME}"
echo -e "${BOLD}─────────────────────────────────────────────────────────────────────${NC}"
