#!/usr/bin/env bash
set -euo pipefail

CONF="${1:-/etc/mount_shares.conf}"

need_pkg() {
  dpkg -s "$1" &>/dev/null || {
    echo "Installing $1..."
    apt-get update -y -qq
    apt-get install -y -qq "$1"
  }
}

write_if_changed() {
  local file="$1" tmp
  tmp="$(mktemp)"
  cat >"$tmp"
  if [[ -f "$file" ]] && cmp -s "$file" "$tmp"; then
    echo "Unchanged $file"
    rm -f "$tmp"
  else
    install -o root -g root -m 0644 "$tmp" "$file"
    echo "Created $file"
  fi
}

unit_name_for_path() {
  # Systemd path-escaped unit (like /media/appdata -> media-appdata.mount)
  local p="$1"
  p="${p#/}"           # strip leading /
  p="${p//\//-}"       # / -> -
  echo "$p"
}

# --- Defaults ---
NFS_DEFAULT_OPTS="vers=4.1,proto=tcp,nconnect=1,rsize=65536,wsize=65536,timeo=30,retrans=2,hard,_netdev,nosuid,nodev"
NFS_DEFAULT_IDLE="600"

BINDFS_DEFAULT_OPTS="force-user=102222,force-group=103333,create-for-user=dbi,create-for-group=dbi,perms=u=rwx:g=rwx:o=rwx,create-with-perms=0775,chown-ignore,chgrp-ignore"

declare -a NFS_NAMES=()
declare -A NFS_SERVER NFS_EXPORT NFS_WHERE NFS_OPTS NFS_IDLE

declare -a BIND_NAMES=()
declare -A BIND_SRC BIND_DEST BIND_OPTS

if [[ ! -f "$CONF" ]]; then
  echo "Config not found: $CONF" >&2
  exit 1
fi

# --- Parse config ---
while IFS= read -r raw; do
  line="${raw%%#*}"; line="${line//[$'\t\r\n']/ }"
  [[ -z "${line// }" ]] && continue

  read -r kind rest <<<"$line"
  declare -A kv=()
  for tok in $rest; do
    [[ "$tok" != *"="* ]] && continue
    k="${tok%%=*}"; v="${tok#*=}"
    kv["$k"]="$v"
  done

  case "$kind" in
    nfs)
      name="${kv[name]:-}"
      server="${kv[server]:-}"
      exportp="${kv[export]:-}"
      where="${kv[where]:-/media/${name}}"
      opts="${kv[opts]:-$NFS_DEFAULT_OPTS}"
      idle="${kv[idle]:-$NFS_DEFAULT_IDLE}"
      [[ -z "$name" || -z "$server" || -z "$exportp" ]] && { echo "Invalid nfs line: $raw" >&2; continue; }
      NFS_NAMES+=("$name")
      NFS_SERVER["$name"]="$server"
      NFS_EXPORT["$name"]="$exportp"
      NFS_WHERE["$name"]="$where"
      NFS_OPTS["$name"]="$opts"
      NFS_IDLE["$name"]="$idle"
      ;;
    bindfs)
      name="${kv[name]:-}"
      src="${kv[src]:-/media/${name}}"
      dest="${kv[dest]:-/lxc_shares/${name}}"
      opts="${kv[opts]:-$BINDFS_DEFAULT_OPTS}"
      [[ -z "$name" ]] && { echo "Invalid bindfs line: $raw" >&2; continue; }
      BIND_NAMES+=("$name")
      BIND_SRC["$name"]="$src"
      BIND_DEST["$name"]="$dest"
      BIND_OPTS["$name"]="$opts"
      ;;
    *)
      echo "Unknown kind '$kind' in: $raw" >&2
      ;;
  esac
done < "$CONF"

# --- Ensure packages ---
need_pkg nfs-common
need_pkg bindfs

# --- lxc_shares tmpfs (only if any bindfs dest lives under /lxc_shares) ---
need_lxc_tmpfs=0
for n in "${BIND_NAMES[@]:-}"; do
  [[ "${BIND_DEST[$n]}" == /lxc_shares/* ]] && { need_lxc_tmpfs=1; break; }
done

if (( need_lxc_tmpfs )); then
  mkdir -p /lxc_shares
  write_if_changed /etc/systemd/system/lxc_shares.mount <<'EOF'
[Unit]
Description=tmpfs for LXC bind overlays
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target

[Mount]
What=tmpfs
Where=/lxc_shares
Type=tmpfs
Options=mode=0755,size=2G,nosuid,nodev

[Install]
WantedBy=multi-user.target
EOF
  systemctl enable --now lxc_shares.mount
fi

# --- Generate NFS mount + automount ---
for name in "${NFS_NAMES[@]:-}"; do
  where="${NFS_WHERE[$name]}"
  unit="$(unit_name_for_path "$where")"
  mnt="/etc/systemd/system/${unit}.mount"
  aut="/etc/systemd/system/${unit}.automount"
  mkdir -p "$(dirname "$where")"
  mkdir -p "$where"

  write_if_changed "$mnt" <<EOF
[Unit]
Description=NFS ${name} (nfs4)
After=network-online.target
Wants=network-online.target

[Mount]
What=${NFS_SERVER[$name]}:${NFS_EXPORT[$name]}
Where=$where
Type=nfs4
Options=${NFS_OPTS[$name]}

[Install]
WantedBy=multi-user.target
EOF

  write_if_changed "$aut" <<EOF
[Unit]
Description=Automount $where
Before=${unit}.mount

[Automount]
Where=$where
TimeoutIdleSec=${NFS_IDLE[$name]}

[Install]
WantedBy=multi-user.target
EOF

  systemctl enable --now "${unit}.automount"
done

# --- Generate bindfs services ---
for name in "${BIND_NAMES[@]:-}"; do
  src="${BIND_SRC[$name]}"
  dest="${BIND_DEST[$name]}"
  dest_unit_dep="$(unit_name_for_path "$src")"   # e.g. media-backup
  svc="/etc/systemd/system/bindfs-lxcshare-${name}.service"
  mkdir -p "$dest"

  write_if_changed "$svc" <<EOF
[Unit]
Description=bindfs overlay -> ${dest}
RequiresMountsFor=${dest%/*} ${src}
After=${dest%/*/*}/$(basename ${dest%/*}).mount ${dest_unit_dep}.mount

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=-/bin/umount -l ${dest}
ExecStart=/usr/bin/mkdir -p ${dest}
ExecStart=/usr/bin/bindfs ${BIND_OPTS[$name]} ${src} ${dest}
ExecStop=/bin/umount -l ${dest}
TimeoutStartSec=30
TimeoutStopSec=10

[Install]
WantedBy=multi-user.target
EOF

  systemctl enable --now "bindfs-lxcshare-${name}.service"
done

systemctl daemon-reload
echo "✅ Done. Units generated from $CONF"