#!/usr/bin/env bash
# policy: usr_smb — auto-mount network shares in user home directories.
#   usr_smb_r_<name>   mount read-only  share ~/‹name› for logged-in members
#   usr_smb_rw_<name>  mount read-write share ~/‹name› for logged-in members
# rw membership takes precedence over r for the same share name.
# Credential (server, Samba user, password) stored in IPA group description by
# ansipa-smb-setup.sh: cifs://<ipa-host>:<samba-user>:<password>
# Requires: cifs-utils installed on the client.

SMB_MOUNT_STATE="$STATE_DIR/smb-mounts"
[[ -f "$SMB_MOUNT_STATE" ]] || touch "$SMB_MOUNT_STATE"
SMB_CREDS_DIR="$STATE_DIR/smb-creds"
mkdir -p "$SMB_CREDS_DIR"
chmod 700 "$SMB_CREDS_DIR"

if command -v mount.cifs &>/dev/null; then

    # ── Discover usr_smb_r_* / usr_smb_rw_* from the already-fetched group list
    declare -A _SMB_R_GRP _SMB_RW_GRP

    while IFS= read -r _g; do
        [[ -z "$_g" ]] && continue
        if   [[ "$_g" =~ ^usr_smb_r_(.+)$  ]]; then _SMB_R_GRP["${BASH_REMATCH[1]}"]="$_g"
        elif [[ "$_g" =~ ^usr_smb_rw_(.+)$ ]]; then _SMB_RW_GRP["${BASH_REMATCH[1]}"]="$_g"
        fi
    done <<< "$_ALL_USER_GROUPS"
    unset _g

    declare -A _SMB_NAMES
    for _n in "${!_SMB_R_GRP[@]}" "${!_SMB_RW_GRP[@]}"; do _SMB_NAMES["$_n"]=1; done
    unset _n

    _smb_member() { id -nG "$1" 2>/dev/null | tr ' ' '\n' | grep -qxF "$2"; }

    declare -A _SMB_SESS
    _smb_add_sess() {
        local _u
        [[ "$2" == "loginctl" ]] && _u=$(awk '{print $3}' <<< "$1") \
                                 || _u=$(awk '{print $1}' <<< "$1")
        [[ -z "$_u" || "$_u" == "root" || "$_u" == "USER" ]] && return 0
        local _h; _h=$(getent passwd "$_u" | cut -d: -f6 2>/dev/null) || return 0
        [[ -d "$_h" ]] && _SMB_SESS["$_u"]="$_h"
    }
    if loginctl list-sessions --no-legend &>/dev/null; then
        while IFS= read -r _L; do _smb_add_sess "$_L" "loginctl"
        done < <(loginctl list-sessions --no-legend 2>/dev/null)
    else
        while IFS= read -r _L; do _smb_add_sess "$_L" "who"
        done < <(who 2>/dev/null)
    fi
    unset _L

    for _SMB_NAME in "${!_SMB_NAMES[@]}"; do
        _R_GRP="${_SMB_R_GRP[$_SMB_NAME]:-}"
        _RW_GRP="${_SMB_RW_GRP[$_SMB_NAME]:-}"

        _CRED_LINE=""
        [[ -n "$_RW_GRP" ]] && _CRED_LINE=$(_smb_parse_cred "$_RW_GRP")
        [[ -z "$_CRED_LINE" && -n "$_R_GRP" ]] && _CRED_LINE=$(_smb_parse_cred "$_R_GRP")

        if [[ -z "$_CRED_LINE" ]]; then
            warn "No credential in IPA description for share $_SMB_NAME — skipped (run ansipa-smb.service on FreeIPA container)"
            continue
        fi
        read -r _SMB_HOST _SMB_SUSER _SMB_SPASS <<< "$_CRED_LINE"

        _CREDS_FILE="$SMB_CREDS_DIR/${_SMB_NAME}.creds"
        printf 'username=%s\npassword=%s\ndomain=WORKGROUP\n' "$_SMB_SUSER" "$_SMB_SPASS" \
            > "$_CREDS_FILE"
        chmod 600 "$_CREDS_FILE"

        for _SMB_U in "${!_SMB_SESS[@]}"; do
            _SMB_LVL=""
            [[ -n "$_RW_GRP" ]] && _smb_member "$_SMB_U" "$_RW_GRP" && _SMB_LVL="rw"
            [[ -z "$_SMB_LVL" && -n "$_R_GRP" ]] && _smb_member "$_SMB_U" "$_R_GRP" && _SMB_LVL="r"
            [[ -z "$_SMB_LVL" ]] && continue

            _SMB_H="${_SMB_SESS[$_SMB_U]}"
            _SMB_MP="$_SMB_H/$_SMB_NAME"
            _SMB_SHARE="usr-${_SMB_NAME}-${_SMB_LVL}"

            if mountpoint -q "$_SMB_MP" 2>/dev/null; then
                grep -qxF "${_SMB_U}:${_SMB_NAME}" "$SMB_MOUNT_STATE" 2>/dev/null || \
                    echo "${_SMB_U}:${_SMB_NAME}" >> "$SMB_MOUNT_STATE"
                continue
            fi

            mkdir -p "$_SMB_MP"
            chown "$_SMB_U" "$_SMB_MP" 2>/dev/null || true

            if mount -t cifs "//${_SMB_HOST}/${_SMB_SHARE}" "$_SMB_MP" \
                -o "credentials=${_CREDS_FILE},uid=${_SMB_U},gid=${_SMB_U},file_mode=0644,dir_mode=0755,nounix,noserverino" \
                2>/dev/null; then
                log "Mounted //${_SMB_HOST}/${_SMB_SHARE} → $_SMB_MP for $_SMB_U"
                grep -qxF "${_SMB_U}:${_SMB_NAME}" "$SMB_MOUNT_STATE" 2>/dev/null || \
                    echo "${_SMB_U}:${_SMB_NAME}" >> "$SMB_MOUNT_STATE"
            else
                warn "Failed to mount //${_SMB_HOST}/${_SMB_SHARE} for $_SMB_U"
                rmdir "$_SMB_MP" 2>/dev/null || true
            fi
        done
    done
    unset _SMB_NAME _R_GRP _RW_GRP _CRED_LINE _SMB_HOST _SMB_SUSER _SMB_SPASS \
          _CREDS_FILE _SMB_U _SMB_H _SMB_MP _SMB_SHARE _SMB_LVL

    _NEW_SMB_MOUNTS=()
    while IFS=: read -r _OLD_USER _OLD_NAME; do
        [[ -z "$_OLD_USER" || -z "$_OLD_NAME" ]] && continue
        _OLD_HOME=$(getent passwd "$_OLD_USER" | cut -d: -f6 2>/dev/null) || continue
        _OLD_MPT="$_OLD_HOME/$_OLD_NAME"

        _STILL_MEMBER=false
        if [[ -n "${_SMB_R_GRP[$_OLD_NAME]+x}" ]] && \
           _smb_member "$_OLD_USER" "${_SMB_R_GRP[$_OLD_NAME]}"; then
            _STILL_MEMBER=true
        elif [[ -n "${_SMB_RW_GRP[$_OLD_NAME]+x}" ]] && \
           _smb_member "$_OLD_USER" "${_SMB_RW_GRP[$_OLD_NAME]}"; then
            _STILL_MEMBER=true
        fi

        if [[ "$_STILL_MEMBER" == true ]]; then
            _NEW_SMB_MOUNTS+=("${_OLD_USER}:${_OLD_NAME}")
        else
            umount -l "$_OLD_MPT" 2>/dev/null || true
            rmdir "$_OLD_MPT" 2>/dev/null || true
            log "Unmounted ${_OLD_MPT} for ${_OLD_USER} (left usr_smb_*_${_OLD_NAME})"
        fi
    done < "$SMB_MOUNT_STATE"
    unset _OLD_USER _OLD_NAME _OLD_HOME _OLD_MPT _STILL_MEMBER

    if [[ ${#_NEW_SMB_MOUNTS[@]} -gt 0 ]]; then
        printf '%s\n' "${_NEW_SMB_MOUNTS[@]}" | sort -u > "$SMB_MOUNT_STATE"
    else
        > "$SMB_MOUNT_STATE"
    fi

    rm -f "$SMB_CREDS_DIR"/*.creds 2>/dev/null || true

    unset _SMB_R_GRP _SMB_RW_GRP _SMB_NAMES _SMB_SESS _NEW_SMB_MOUNTS

else
    warn "mount.cifs not found — install cifs-utils to enable usr_smb_* policies"
    [[ -s "$SMB_MOUNT_STATE" ]] && \
        warn "smb-mounts state is non-empty — cannot revert existing mounts without cifs-utils" || true
fi
