#!/bin/bash

###############################################################################
# Load Configuration from json
###############################################################################

# Require the config‑file path as the first argument:
CONFIG_FILE="$1"

if [[ -z "$CONFIG_FILE" ]]; then
  echo "[ERROR] No path to config file given"
  exit 1
fi

# Ensure the file actually exists:
if [[ ! -f "$CONFIG_FILE" ]]; then
  echo "[ERROR] Config file '$CONFIG_FILE' not found."
  exit 1
fi

# Ensure jq is installed before proceeding.
if ! command -v jq >/dev/null 2>&1; then
    echo "[ERROR] 'jq' is not installed. Please install jq and try again."
    exit 1
fi

# Ensure an NFS mount helper is available before doing any work.
if ! command -v mount.nfs >/dev/null 2>&1 && \
   ! command -v mount.nfs4 >/dev/null 2>&1 && \
   [ ! -x /sbin/mount.nfs ] && [ ! -x /usr/sbin/mount.nfs ]; then
    echo "[ERROR] NFS client utilities are missing (mount.nfs/mount.nfs4 not found)."
    echo "[ERROR] Install the 'nfs-common' package on this host and re-run the script."
    exit 1
fi

# extract the server names at the top level:
SERVERS=($(jq -r 'keys[]' "$CONFIG_FILE"))

###############################################################################
# Function Definitions
###############################################################################
# Check if the SSH tunnel on a given local port is active
is_tunnel_active() {
    local port=$1
    timeout 1 bash -c "</dev/tcp/localhost/${port}" &>/dev/null
}

# Check if the given mount point is currently mounted
is_nfs_mounted() {
    local mount_point=$1
    local fstype
    fstype=$(findmnt -rn -T "${mount_point}" -o FSTYPE 2>/dev/null)
    [[ "${fstype}" == nfs* ]]
}

# Check if the mount point directory is accessible (i.e. can be listed)
is_mount_accessible() {
    local mount_point=$1
    ls -1 "${mount_point}" >/dev/null 2>&1
}

# Run the NFS mount command and verify it really succeeded.
mount_nfs_share() {
    local mount_point=$1
    local nfs_share=$2
    local local_port=$3
    local mount_opts="ro,port=${local_port},nolock,soft,timeo=5,retrans=3"
    local mount_output

    if ! mount_output=$(sudo mount -t nfs -o "${mount_opts}" 127.0.0.1:"${nfs_share}" "${mount_point}" 2>&1); then
        echo "[ERROR] Failed to mount ${nfs_share} at ${mount_point}: ${mount_output}"
        return 1
    fi

    if ! is_nfs_mounted "${mount_point}"; then
        echo "[ERROR] Mount command returned success but ${mount_point} is not an active NFS mount."
        echo "[DEBUG] Mount output: ${mount_output}"
        return 1
    fi

    if ! is_mount_accessible "${mount_point}"; then
        echo "[ERROR] ${mount_point} is mounted but not accessible (check tunnel/NFS server)."
        return 1
    fi

    echo "[SUCCESS] NFS share mounted successfully at ${mount_point}."
}

###############################################################################
# Main Loop: Process Each Server and Its Mount Points
###############################################################################
for server in "${SERVERS[@]}"; do
    SSH_USER=$(jq -r ".[\"${server}\"].SSH_USER" "$CONFIG_FILE")
    SSH_SERVER=$(jq -r ".[\"${server}\"].SSH_SERVER" "$CONFIG_FILE")
    SSH_SERVER_PORT=$(jq -r ".[\"${server}\"].SSH_SERVER_PORT" "$CONFIG_FILE")
    REMOTE_NFS_PORT=$(jq -r ".[\"${server}\"].REMOTE_NFS_PORT" "$CONFIG_FILE")
    LOCAL_PORT_BASE=$(jq -r ".[\"${server}\"].LOCAL_PORT_BASE" "$CONFIG_FILE")

    readarray -t MOUNT_POINTS < <(jq -r ".[\"${server}\"].MOUNT_POINTS[]" "$CONFIG_FILE")
    readarray -t NFS_SHARES < <(jq -r ".[\"${server}\"].NFS_SHARES[]" "$CONFIG_FILE")

    echo "-------------------------------------------------"
    echo "[INFO] Processing server: ${SSH_SERVER}"

    # Loop over each mount configuration for the current server.
    for i in "${!MOUNT_POINTS[@]}"; do
        MOUNT_POINT="${MOUNT_POINTS[$i]}"
        NFS_SHARE="${NFS_SHARES[$i]}"
        # Calculate a unique local port: base + index offset
        LOCAL_PORT=$(( LOCAL_PORT_BASE + i ))

        echo "-------------------------------------------------"
        echo "[INFO] Setting up mount for ${MOUNT_POINT}"
        echo "[INFO] NFS Share: ${NFS_SHARE}"
        echo "[INFO] Using local port: ${LOCAL_PORT}"

        # Check and (re)establish the SSH tunnel if needed.
        if ! is_tunnel_active "${LOCAL_PORT}"; then
            echo "[INFO] SSH Tunnel on port ${LOCAL_PORT} is down. Attempting to reconnect..."
            ssh -f -N -L "${LOCAL_PORT}:localhost:${REMOTE_NFS_PORT}" \
                -o ExitOnForwardFailure=yes \
                -p "${SSH_SERVER_PORT}" \
                "${SSH_USER}@${SSH_SERVER}"

            if is_tunnel_active "${LOCAL_PORT}"; then
                echo "[SUCCESS] SSH Tunnel established on local port ${LOCAL_PORT}."
            else
                echo "[ERROR] Failed to establish SSH tunnel for mount ${MOUNT_POINT}!"
                continue  # Skip mounting for this configuration if tunnel fails
            fi
        else
            echo "[INFO] SSH Tunnel already active on port ${LOCAL_PORT}."
        fi

        # Ensure the mount point directory exists
        if [ ! -d "${MOUNT_POINT}" ]; then
            echo "[INFO] Creating mount point directory: ${MOUNT_POINT}"
            sudo mkdir -p "${MOUNT_POINT}"
        fi

        # Check if the NFS share is mounted and accessible.
        if is_nfs_mounted "${MOUNT_POINT}"; then
            if ! is_mount_accessible "${MOUNT_POINT}"; then
                echo "[WARNING] Mount point ${MOUNT_POINT} is not accessible. Attempting to remount..."
                if sudo umount "${MOUNT_POINT}"; then
                    sleep 2
                    if mount_nfs_share "${MOUNT_POINT}" "${NFS_SHARE}" "${LOCAL_PORT}"; then
                        echo "[SUCCESS] Remounted successfully and folder is now accessible."
                    else
                        echo "[ERROR] Remount failed, folder still not accessible."
                    fi
                else
                    echo "[ERROR] Failed to unmount ${MOUNT_POINT} during remount attempt."
                fi
            else
                echo "[INFO] NFS share is mounted and accessible at ${MOUNT_POINT}."
            fi
        else
            echo "[INFO] NFS share is not mounted at ${MOUNT_POINT}. Attempting to mount..."
            mount_nfs_share "${MOUNT_POINT}" "${NFS_SHARE}" "${LOCAL_PORT}"
        fi

    done
done

echo "-------------------------------------------------"
echo "[INFO] All server mount configurations processed."
