#!/usr/bin/env bash
# StoreAMP Linux Player — Setup & Install Script
# Usage:  curl -fsSL https://storeamp.com/downloads/setup.sh | sudo bash
#    or:  sudo bash setup.sh
set -euo pipefail

SOURCE_URL="https://storeamp.com/downloads/player-linux.tar.gz"

log()  { echo "  [setup] $*"; }
ok()   { echo "  ✓ $*"; }
warn() { echo "  ⚠ $*"; }
err()  { echo "  ✗ $*" >&2; exit 1; }

# ── 0. Root check ───────────────────────────────────────────────────────────────

if [ "$EUID" -ne 0 ]; then
  # When piped through curl, $0 is /dev/stdin — save script first, then sudo.
  _SELF="${BASH_SOURCE[0]:-}"
  if [ -z "$_SELF" ] || [ "$_SELF" = "/dev/stdin" ] || [ "$_SELF" = "bash" ]; then
    _SAVED=$(mktemp /tmp/storeamp-setup-XXXXXX.sh)
    # Re-download so we have a real file to pass to sudo.
    curl -fsSL "https://storeamp.com/downloads/setup.sh" -o "$_SAVED"
    chmod +x "$_SAVED"
    exec sudo bash "$_SAVED" "$@"
  else
    exec sudo bash "$_SELF" "$@"
  fi
fi

INSTALL_BIN="/usr/local/bin/storeamp-player"
SERVICE_FILE="/etc/systemd/system/storeamp-player.service"
ENV_FILE="/etc/storeamp/env"
SERVICE_USER="${STOREAMP_USER:-storeamp}"

# Create config directory immediately so all later steps can safely reference it.
mkdir -p /etc/storeamp

# HTTP audio streaming (Icecast2 + ffmpeg) is enabled by default.
# Pass --no-streaming to skip it and use local speakers only.
SETUP_STREAMING=yes
for _arg in "$@"; do
  [ "$_arg" = "--no-streaming" ] && SETUP_STREAMING=no
done

# ── 0b. Source directory — download source bundle if running standalone ──────

# Safe BASH_SOURCE resolution — falls back gracefully when piped.
_SELF_PATH="${BASH_SOURCE[0]:-/dev/stdin}"
if [ "$_SELF_PATH" != "/dev/stdin" ] && [ -f "$_SELF_PATH" ]; then
  SCRIPT_DIR="$(cd "$(dirname "$_SELF_PATH")" && pwd)"
else
  SCRIPT_DIR="/dev/stdin_placeholder"
fi

if [ ! -f "$SCRIPT_DIR/package.json" ]; then
  log "Running as standalone installer — downloading source…"
  SCRIPT_DIR="/opt/storeamp/player-linux"
  mkdir -p "$SCRIPT_DIR"
  if ! command -v curl &>/dev/null; then
    apt-get update -qq && apt-get install -y curl
  fi
  curl -fsSL "$SOURCE_URL" | tar -xz -C "$SCRIPT_DIR" --strip-components=0
  ok "Source downloaded to $SCRIPT_DIR"
fi

echo ""
echo "┌─────────────────────────────────────────────────────┐"
if [ "$SETUP_STREAMING" = "yes" ]; then
echo "│   StoreAMP Linux Player — Setup + Streaming         │"
else
echo "│   StoreAMP Linux Player — Setup                     │"
fi
echo "└─────────────────────────────────────────────────────┘"
echo ""

# ── 1. Dependencies ──────────────────────────────────────────────────────────

log "Updating package lists…"
apt-get update -qq

# Node.js 22+ — install via NodeSource if missing or too old.
_install_node() {
  log "Installing Node.js 22 via NodeSource…"
  if ! command -v curl &>/dev/null; then
    apt-get install -y curl
  fi
  curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
  apt-get install -y nodejs
}

if ! command -v node &>/dev/null; then
  _install_node
else
  NODE_MAJOR=$(node -e 'process.stdout.write(String(process.versions.node.split(".")[0]))')
  if [ "$NODE_MAJOR" -lt 22 ]; then
    log "Node.js $NODE_MAJOR found but 22+ required — upgrading…"
    _install_node
  fi
fi
NODE_VER=$(node -e 'process.stdout.write(process.version)')
ok "Node.js $NODE_VER ready."

if ! command -v mpv &>/dev/null; then
  log "mpv not found — installing…"
  apt-get install -y mpv
fi
ok "mpv $(mpv --version | head -1 | cut -d' ' -f2) found."

# ── 2. Build ─────────────────────────────────────────────────────────────────

cd "$SCRIPT_DIR"

log "Installing Node.js dependencies…"
npm install --prefer-offline

log "Compiling TypeScript…"
npm run build

ok "Build complete."

# ── 3. Install binary ────────────────────────────────────────────────────────

INSTALL_DIR="/opt/storeamp/player-linux"
log "Installing to $INSTALL_DIR …"
mkdir -p "$INSTALL_DIR"
cp "$SCRIPT_DIR/dist/index.js" "$INSTALL_DIR/index.js"
# Copy node_modules so native addons (dbus-next) are resolvable at runtime.
# Guard against SCRIPT_DIR == INSTALL_DIR (standalone install case).
if [ "$SCRIPT_DIR" != "$INSTALL_DIR" ]; then
  cp -r "$SCRIPT_DIR/node_modules" "$INSTALL_DIR/node_modules"
fi

# Write a small shell wrapper at /usr/local/bin so it's on PATH.
cat > "$INSTALL_BIN" <<EOF
#!/bin/sh
exec node "$INSTALL_DIR/index.js" "\$@"
EOF
chmod +x "$INSTALL_BIN"
ok "Binary installed at $INSTALL_BIN (app dir: $INSTALL_DIR)."

# ── 4. Create system user (if it doesn't exist) ──────────────────────────────

if ! id "$SERVICE_USER" &>/dev/null; then
  log "Creating system user '$SERVICE_USER'…"
  useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER"
  ok "User '$SERVICE_USER' created."
else
  ok "User '$SERVICE_USER' already exists."
fi

# Add to audio-related groups only if they exist on this system.
for _grp in audio pulse-access pipewire; do
  if getent group "$_grp" &>/dev/null; then
    usermod -aG "$_grp" "$SERVICE_USER" 2>/dev/null || true
  fi
done

# Enable lingering so the user's D-Bus session (needed for Bluetooth media
# controls via MPRIS) starts at boot even without an interactive login.
loginctl enable-linger "$SERVICE_USER" 2>/dev/null || true
ok "Linger enabled for '$SERVICE_USER' (D-Bus session starts at boot)."

# ── 5. Environment file ──────────────────────────────────────────────────────

if [ ! -f "$ENV_FILE" ]; then
  cat > "$ENV_FILE" <<'EOF'
# StoreAMP Linux Player environment
# Edit this file, then: sudo systemctl restart storeamp-player

STOREAMP_TOKEN=your-auth-token-here
STOREAMP_VOLUME=90
EOF
  chmod 640 "$ENV_FILE"
  ok "Created $ENV_FILE — EDIT THIS FILE before enabling the service."
else
  ok "$ENV_FILE already exists (not overwritten)."
fi

# ── 5b. Disk cache directory ─────────────────────────────────────────────────

log "Creating disk cache directory…"
mkdir -p /var/cache/storeamp/tracks
chown -R "$SERVICE_USER:$SERVICE_USER" /var/cache/storeamp
chmod 750 /var/cache/storeamp/tracks
ok "Cache directory: /var/cache/storeamp/tracks"

# ── 5c. Schedule file (opening hours) ────────────────────────────────────────

SCHEDULE_FILE="/etc/storeamp/schedule.json"
if [ ! -f "$SCHEDULE_FILE" ]; then
  cat > "$SCHEDULE_FILE" <<'EOF'
{
  "timezone": "Europe/London",
  "schedule": {
    "monday":    { "open": "08:00", "close": "17:00" },
    "tuesday":   { "open": "08:00", "close": "17:00" },
    "wednesday": { "open": "08:00", "close": "17:00" },
    "thursday":  { "open": "08:00", "close": "17:00" },
    "friday":    { "open": "08:00", "close": "17:00" },
    "saturday":  { "open": "09:00", "close": "17:00" },
    "sunday":    null
  }
}
EOF
  chmod 644 "$SCHEDULE_FILE"
  ok "Created $SCHEDULE_FILE — edit to match your opening hours."
else
  ok "$SCHEDULE_FILE already exists (not overwritten)."
fi

# ── 6. Prevent suspend / lid-close sleep ─────────────────────────────────────

log "Configuring system to ignore lid close and idle suspend…"
mkdir -p /etc/systemd/logind.conf.d
cat > /etc/systemd/logind.conf.d/storeamp.conf <<'EOF'
[Login]
# Do not suspend when the laptop lid is closed.
HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore
# Do not suspend due to inactivity.
IdleAction=ignore
EOF
# SIGHUP reloads logind config without terminating active desktop sessions.
# A full restart would kill the current session (blank screen on re-login).
systemctl kill -s HUP systemd-logind
ok "Lid-close and idle suspend disabled."

# Disable systemd sleep targets as an additional safeguard.
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target 2>/dev/null || true
ok "Suspend/hibernate systemd targets masked."

# ── 7. systemd service ───────────────────────────────────────────────────────

log "Installing systemd service…"
sed "s/User=storeamp/User=$SERVICE_USER/" "$SCRIPT_DIR/storeamp-player.service" \
  > "$SERVICE_FILE"
systemctl daemon-reload
ok "Systemd service installed."

# ── 8. (Optional) Network audio streaming (HTTP — paste URL into VLC) ────────

if [ "$SETUP_STREAMING" = "yes" ]; then
  log "Setting up HTTP audio streaming (Icecast2 + ffmpeg)…"

  # Pre-seed debconf so icecast2 installs non-interactively (no wizard prompts).
  if command -v debconf-set-selections &>/dev/null; then
    cat <<'DEBCONF' | debconf-set-selections
icecast2 icecast2/icecast-setup boolean true
icecast2 icecast2/hostname string localhost
icecast2 icecast2/sourcepassword string storeamp-source
icecast2 icecast2/relaypassword string storeamp-relay
icecast2 icecast2/adminpassword string storeamp-admin
DEBCONF
  fi
  DEBIAN_FRONTEND=noninteractive apt-get install -y icecast2 ffmpeg

  # Load ALSA loopback kernel module — mpv writes to one side, ffmpeg reads
  # from the other and encodes it for the HTTP stream.
  modprobe snd-aloop pcm_substreams=2
  if ! grep -q "^snd-aloop" /etc/modules 2>/dev/null; then
    echo "snd-aloop" >> /etc/modules
  fi
  ok "ALSA loopback module (snd-aloop) loaded."

  sleep 1
  LOOPBACK_CARD=$(aplay -l 2>/dev/null | awk '/Loopback/{print $2}' | tr -d ':' | head -1)
  [ -z "$LOOPBACK_CARD" ] && LOOPBACK_CARD="Loopback"
  ok "ALSA Loopback: card $LOOPBACK_CARD"

  # Write a minimal Icecast2 config.
  cat > /etc/icecast2/icecast.xml <<'ICEEOF'
<icecast>
  <location>StoreAMP</location>
  <admin>admin@localhost</admin>
  <limits>
    <clients>25</clients>
    <sources>1</sources>
    <queue-size>524288</queue-size>
    <burst-size>65536</burst-size>
  </limits>
  <authentication>
    <source-password>storeamp-source</source-password>
    <admin-user>admin</admin-user>
    <admin-password>storeamp-admin</admin-password>
  </authentication>
  <listen-socket>
    <port>8000</port>
  </listen-socket>
  <http-headers>
    <header name="Access-Control-Allow-Origin" value="*" />
  </http-headers>
  <paths>
    <basedir>/usr/share/icecast2</basedir>
    <logdir>/var/log/icecast2</logdir>
    <webroot>/usr/share/icecast2/web</webroot>
    <adminroot>/usr/share/icecast2/admin</adminroot>
  </paths>
  <logging>
    <loglevel>1</loglevel>
    <accesslog>access.log</accesslog>
    <errorlog>error.log</errorlog>
  </logging>
</icecast>
ICEEOF
  ok "Icecast2 configured (/etc/icecast2/icecast.xml)."

  # Enable Icecast2 in its defaults file (needed on Debian/Ubuntu).
  sed -i 's/^ENABLE=.*/ENABLE=true/' /etc/default/icecast2 2>/dev/null || true

  # Write a systemd service that runs ffmpeg to capture the ALSA loopback and
  # push an MP3 stream to Icecast2.
  cat > /etc/systemd/system/storeamp-stream.service <<EOF
[Unit]
Description=StoreAMP Audio Stream (ffmpeg → Icecast2)
After=icecast2.service storeamp-player.service
Wants=icecast2.service storeamp-player.service

[Service]
# Give Icecast2 a moment to be ready before connecting.
ExecStartPre=/bin/sleep 3
ExecStart=/usr/bin/ffmpeg \\
  -hide_banner -loglevel warning \\
  -f alsa -i hw:${LOOPBACK_CARD},1,0 \\
  -acodec libmp3lame -b:a 128k -ar 44100 -ac 2 \\
  -content_type audio/mpeg \\
  -f mp3 "icecast://source:storeamp-source@localhost:8000/storeamp"
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target
EOF
  ok "storeamp-stream.service written."

  # Tell the StoreAMP player to route mpv audio to the ALSA loopback write-side.
  if ! grep -q "STOREAMP_STREAM_AUDIO_DEVICE" "$ENV_FILE" 2>/dev/null; then
    cat >> "$ENV_FILE" <<EOF

# Network streaming: mpv routes audio via ALSA loopback → ffmpeg → Icecast2.
# Remove this line to disable streaming and use local speakers only.
STOREAMP_STREAM_AUDIO_DEVICE=hw:${LOOPBACK_CARD},0,0
EOF
  fi

  systemctl daemon-reload
  systemctl enable icecast2 storeamp-stream
  systemctl restart icecast2 || true
  systemctl restart storeamp-stream || true
  ok "Streaming services enabled."

  SERVER_IP=$(hostname -I | awk '{print $1}')
  echo ""
  echo "  ┌───────────────────────────────────────────────────────────┐"
  echo "  │  Stream URL (paste into VLC or any media player):        │"
  echo "  │                                                           │"
  echo "  │    http://${SERVER_IP}:8000/storeamp                │"
  echo "  │                                                           │"
  echo "  └───────────────────────────────────────────────────────────┘"
  echo ""
  echo "  Note: restart storeamp-player after setup to apply the new audio device:"
  echo "    sudo systemctl restart storeamp-player"
  echo ""
fi

# ── Auth token acquisition ───────────────────────────────────────────────────
# If the env file already has a real token, skip this step entirely.

_existing_token=$(grep -E '^STOREAMP_TOKEN=' "$ENV_FILE" 2>/dev/null | head -1 | cut -d= -f2-)
if echo "$_existing_token" | grep -qE '^your-auth-token-here$|^$'; then
  _existing_token=""
fi

if [ -n "$_existing_token" ]; then
  ok "Auth token already present in $ENV_FILE — skipping authentication."
  _do_auth="no"
else
  _do_auth="yes"
fi

if [ "$_do_auth" = "yes" ]; then
  # Accept code non-interactively (useful for headless/CI installs).
  JOIN_CODE="${STOREAMP_JOIN_CODE:-}"

  if [ -z "$JOIN_CODE" ]; then
    # Try to prompt only if we have a real TTY (won't work with curl | bash piped).
    if [ -t 0 ]; then
      echo ""
      echo "  ┌─────────────────────────────────────────────────────────────┐"
      echo "  │  Authenticate this player                                   │"
      echo "  │                                                             │"
      echo "  │  Open the StoreAMP admin panel and go to:                  │"
      echo "  │    Store player link → Generate player link → Copy code     │"
      echo "  │                                                             │"
      echo "  │  Paste the join code below (or press Enter to skip).        │"
      echo "  └─────────────────────────────────────────────────────────────┘"
      echo ""
      printf "  Join code: "
      read -r JOIN_CODE </dev/tty || JOIN_CODE=""
      JOIN_CODE=$(echo "$JOIN_CODE" | tr -d '[:space:]')
    fi
  fi

  if [ -n "$JOIN_CODE" ]; then
    log "Authenticating player with join code…"
    if storeamp-player --join "$JOIN_CODE"; then
      ok "Player authenticated and token saved."
      _do_auth="done"
    else
      warn "Authentication failed. Run manually after setup:"
      warn "  sudo storeamp-player --join <code>"
    fi
  else
    warn "No join code provided. Run after setup:"
    warn "  sudo storeamp-player --join <code>"
    warn "  (Get the code from StoreAMP admin → Store player link)"
  fi
fi

# ── Enable + start the service ───────────────────────────────────────────────

systemctl daemon-reload
systemctl enable storeamp-player 2>/dev/null || true
systemctl restart storeamp-player 2>/dev/null || true
ok "storeamp-player enabled and started."

# ── Done ─────────────────────────────────────────────────────────────────────

SERVER_IP=$(hostname -I | awk '{print $1}')
echo ""
echo "┌──────────────────────────────────────────────────────────────┐"
echo "│  Setup complete!                                             │"
echo "│                                                              │"
if [ "$_do_auth" = "done" ]; then
echo "│  ✓ Player is authenticated and running.                     │"
echo "│    Watch live logs:                                          │"
echo "│      sudo journalctl -u storeamp-player -f                  │"
else
echo "│  Next step — authenticate this player:                      │"
echo "│    1. Open StoreAMP admin → Store player link               │"
echo "│    2. Click Generate player link → Copy code                │"
echo "│    3. Run:                                                   │"
echo "│         sudo storeamp-player --join <code>                  │"
echo "│         sudo systemctl restart storeamp-player              │"
fi
if [ "$SETUP_STREAMING" = "yes" ]; then
echo "│                                                              │"
echo "│  Stream URL (VLC / any player):                             │"
printf "│    http://%-44s│\n" "${SERVER_IP}:8000/storeamp  "
fi
echo "└──────────────────────────────────────────────────────────────┘"
echo ""
