#!/usr/bin/env bash
# install-network_drive.sh — Auto-mount Synology (SMB/CIFS) shares under /mnt/Synology.
# Hardened: safe input handling, no eval-on-username, hostname validation,
# fstab managed via begin/end markers (idempotent re-run), creds file 0600,
# GNOME dock pinning is best-effort.

set -euo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME="${0##*/}"
DRY_RUN=0
SERVER_ADDR=""
SMB_USER=""
SMB_PASS=""
MASTER_DIR="/mnt/Synology"

usage() {
  cat <<EOF
Usage: sudo $SCRIPT_NAME [options]

Discovers SMB shares on a Synology NAS and adds them to /etc/fstab so they
auto-mount under $MASTER_DIR. Creates a desktop launcher and (best-effort)
pins it to the top of the GNOME Dock.

Options:
  --server HOST_OR_IP    Synology address (skips prompt).
  --user USERNAME        SMB username (skips prompt).
  --password-stdin       Read SMB password from stdin (skips prompt).
                         (Otherwise the script prompts on the controlling tty.)
  --mount-root DIR       Override parent directory (default: $MASTER_DIR).
  --dry-run              Print actions without executing.
  --help, -h             Show this help.
EOF
}

log()  { printf '\033[1;34m[%s]\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*"; }
warn() { printf '\033[1;33m[%s] WARN:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; }
die()  { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; }
run()  { if (( DRY_RUN )); then printf '  DRY-RUN: %s\n' "$*"; else eval "$@"; fi; }
trap 'rc=$?; (( rc )) && printf "\033[1;31m[%s] failed at line %s (exit %d)\033[0m\n" "${SCRIPT_NAME%.sh}" "$LINENO" "$rc" >&2' ERR

PASS_FROM_STDIN=0
while (( $# )); do
  case "$1" in
    --server)         SERVER_ADDR="${2:?}"; shift ;;
    --user)           SMB_USER="${2:?}"; shift ;;
    --password-stdin) PASS_FROM_STDIN=1 ;;
    --mount-root)     MASTER_DIR="${2:?}"; shift ;;
    --dry-run)        DRY_RUN=1 ;;
    -h|--help)        usage; exit 0 ;;
    *) die "Unknown argument: $1 (try --help)" ;;
  esac
  shift
done

(( EUID == 0 )) || die "Must run as root. Try: sudo $SCRIPT_NAME"

[[ -r /etc/os-release ]] || die "/etc/os-release not found."
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
  *ubuntu*|*debian*) : ;;
  *) die "Unsupported distro: ${PRETTY_NAME:-unknown}." ;;
esac

ACTUAL_USER="${SUDO_USER:-${USER:-}}"
[[ -n "$ACTUAL_USER" && "$ACTUAL_USER" != "root" ]] || die "Run via sudo as a regular user."
# Use getent so we don't depend on eval/~expansion or shell glob safety.
USER_ENTRY="$(getent passwd "$ACTUAL_USER")" || die "User '$ACTUAL_USER' not found in passwd."
USER_HOME="$(awk -F: '{print $6}' <<<"$USER_ENTRY")"
USER_ID="$(awk -F: '{print $3}' <<<"$USER_ENTRY")"
USER_GID="$(awk -F: '{print $4}' <<<"$USER_ENTRY")"

export DEBIAN_FRONTEND=noninteractive
log "Installing cifs-utils, smbclient..."
run "apt-get update -qq"
run "apt-get install -y cifs-utils smbclient"

# --- Collect creds ---
[[ -n "$SERVER_ADDR" ]] || read -rp "Synology NAS address or IP: " SERVER_ADDR </dev/tty
SERVER_ADDR="${SERVER_ADDR#smb://}"
SERVER_ADDR="${SERVER_ADDR#//}"
SERVER_ADDR="${SERVER_ADDR%/}"
[[ "$SERVER_ADDR" =~ ^[A-Za-z0-9._-]+$ ]] || die "Invalid host/IP: '$SERVER_ADDR'"

[[ -n "$SMB_USER" ]] || read -rp "Synology username: " SMB_USER </dev/tty
[[ "$SMB_USER" =~ ^[A-Za-z0-9._@-]+$ ]] || die "Invalid SMB username."

if (( PASS_FROM_STDIN )); then
  IFS= read -r SMB_PASS
else
  read -rsp "Synology password: " SMB_PASS </dev/tty
  echo
fi
[[ -n "$SMB_PASS" ]] || die "Password is empty."

# --- Credentials file ---
CRED_FILE="$USER_HOME/.smbcredentials_synology"
log "Writing credentials to $CRED_FILE (mode 0600)..."
if (( DRY_RUN )); then
  printf '  DRY-RUN: write %s\n' "$CRED_FILE"
else
  umask 077
  {
    printf 'username=%s\n' "$SMB_USER"
    printf 'password=%s\n' "$SMB_PASS"
  } >"$CRED_FILE"
  chown "$USER_ID:$USER_GID" "$CRED_FILE"
  chmod 0600 "$CRED_FILE"
fi

# --- Query shares ---
log "Discovering shares on //$SERVER_ADDR..."
if (( DRY_RUN )); then
  SHARE_LIST=$'home\nphoto\nvideo'
else
  SHARE_LIST="$(smbclient -L "//$SERVER_ADDR" -U "$SMB_USER%$SMB_PASS" -g 2>/dev/null \
    | awk -F'|' '$1=="Disk" {print $2}' || true)"
fi
[[ -n "$SHARE_LIST" ]] || die "No shares returned. Check host, credentials, or network."

# --- Parent mount dir ---
run "mkdir -p '$MASTER_DIR'"
run "chown '$USER_ID:$USER_GID' '$MASTER_DIR'"

# --- Backup fstab once ---
if [[ ! -f /etc/fstab.bak.synology ]]; then
  run "cp /etc/fstab /etc/fstab.bak.synology"
  log "Backed up fstab -> /etc/fstab.bak.synology"
fi

MARK_BEGIN="# >>> synology-master >>> (managed by ${SCRIPT_NAME})"
MARK_END="# <<< synology-master <<<"
# Remove any previous managed block (so re-run replaces, not appends).
if grep -qF "$MARK_BEGIN" /etc/fstab; then
  if (( DRY_RUN )); then
    printf '  DRY-RUN: strip previous managed block from /etc/fstab\n'
  else
    sed -i "\|$MARK_BEGIN|,\|$MARK_END|d" /etc/fstab
  fi
fi

log "Writing managed block to /etc/fstab..."
FSTAB_BLOCK="$MARK_BEGIN"$'\n'
while IFS= read -r SHARE; do
  [[ -z "$SHARE" || "$SHARE" == "IPC\$" || "$SHARE" == "print\$" ]] && continue
  MOUNT_POINT="$MASTER_DIR/$SHARE"
  run "mkdir -p '$MOUNT_POINT'"
  run "chown '$USER_ID:$USER_GID' '$MOUNT_POINT'"
  FSTAB_BLOCK+="//${SERVER_ADDR}/${SHARE} ${MOUNT_POINT} cifs credentials=${CRED_FILE},uid=${USER_ID},gid=${USER_GID},_netdev,nofail,x-systemd.automount,x-systemd.idle-timeout=60 0 0"$'\n'
done <<<"$SHARE_LIST"
FSTAB_BLOCK+="$MARK_END"$'\n'

if (( DRY_RUN )); then
  printf '  DRY-RUN: append fstab block:\n%s\n' "$FSTAB_BLOCK"
else
  printf '%s' "$FSTAB_BLOCK" >>/etc/fstab
fi

log "Reloading systemd and mounting..."
run "systemctl daemon-reload"
run "mount -a -t cifs"

# --- Desktop entry ---
APPS_DIR="$USER_HOME/.local/share/applications"
DESKTOP_FILENAME="synology-master.desktop"
DESKTOP_FILE="$APPS_DIR/$DESKTOP_FILENAME"
run "install -d -o '$USER_ID' -g '$USER_GID' -m 0755 '$APPS_DIR'"

if (( DRY_RUN )); then
  printf '  DRY-RUN: write %s\n' "$DESKTOP_FILE"
else
  cat >"$DESKTOP_FILE" <<EOF
[Desktop Entry]
Name=Synology NAS
Comment=Open Synology Master Directory
Exec=xdg-open ${MASTER_DIR}
Icon=folder-remote
Terminal=false
Type=Application
Categories=Network;FileTools;
EOF
  chown "$USER_ID:$USER_GID" "$DESKTOP_FILE"
  chmod 0755 "$DESKTOP_FILE"
fi

# --- Best-effort GNOME dock pin ---
if (( ! DRY_RUN )) && sudo -u "$ACTUAL_USER" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$USER_ID/bus" gsettings list-keys org.gnome.shell >/dev/null 2>&1; then
  log "Pinning to top of GNOME dock..."
  CURRENT_FAVS="$(sudo -u "$ACTUAL_USER" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$USER_ID/bus" gsettings get org.gnome.shell favorite-apps 2>/dev/null || echo '[]')"
  if [[ "$CURRENT_FAVS" != *"$DESKTOP_FILENAME"* ]]; then
    CLEAN_FAVS="${CURRENT_FAVS#@as }"
    if [[ "$CLEAN_FAVS" == "[]" || -z "$CLEAN_FAVS" ]]; then
      NEW_FAVS="['$DESKTOP_FILENAME']"
    else
      NEW_FAVS="['$DESKTOP_FILENAME', ${CLEAN_FAVS:1}"
    fi
    sudo -u "$ACTUAL_USER" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$USER_ID/bus" \
      gsettings set org.gnome.shell favorite-apps "$NEW_FAVS" || warn "Dock pin failed (non-fatal)."
  else
    log "Already pinned."
  fi
else
  log "GNOME not detected (or no active dbus session); skipping dock pin."
fi

log "Done. Shares mounted under $MASTER_DIR."
