#!/bin/bash
# ==============================================================================================
# ============================= Recreate Shares ================================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Creates share directories on the correct disks after a fresh unRAID install
# or disk rebuild. Reads all .cfg files from /boot/config/shares/ and creates
# the corresponding directories on each disk listed in the shareInclude setting.
# The array must be started before running — /mnt/user must be mounted.
#
# Typically run on HOST2 after a full disk replacement or fresh install where
# share folders were lost but /boot/config/shares/*.cfg files were restored.
#
# ==============================================================================================
# OPERATIONAL MODEL
# ==============================================================================================
#
# For each share .cfg file:
#   1. Reads shareInclude= to determine which disks own this share
#   2. Creates /mnt/diskN/ShareName/ on each listed disk if it doesn't exist
#   3. Places a .recovery marker file in /mnt/user/ShareName/ via the union filesystem
#
# .recovery Marker
#   Signals to rsync.sh that this is a fresh share with no existing data.
#   rsync.sh checks for .recovery before running with --delete:
#     .recovery present → rsync WITHOUT --delete (new files only, nothing removed)
#     .recovery absent  → rsync WITH --delete (normal mirror mode)
#
#   Self-cleaning: after the first successful rsync the source side has no .recovery
#   file, so the second nightly run deletes it from the mirror, restoring normal
#   --delete behaviour automatically. No manual cleanup needed.
#
# ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# The .cfg Files Are the Source of Truth
#   Directories are recreated from /boot/config/shares/*.cfg rather than from a list in
#   Varaverk's conf. Those files are Unraid's own record of what a share is and which disks
#   it spans — anything Varaverk maintained separately would be a second copy free to drift.
#
# Create Only, Never Delete
#   Missing directories are created and existing ones left alone. This runs after a rebuild,
#   when the operator's mental model of what should exist may be out of date; removing
#   anything on that basis is how a recovery step becomes a data loss step.
#
# Array Must Be Started
#   Refuses to run without /mnt/user mounted. Creating share directories against an
#   unmounted array writes them into the underlying root filesystem, which then shadows the
#   real shares once the array does mount.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
# Single Instance Lock
#   acquire_lock prevents duplicate runs placing duplicate .recovery markers.
#
# Root Required
#   mkdir on /mnt/diskN requires root.
#
# Array Mount Check
#   Exits cleanly if the array is not started — /mnt/user not mounted means
#   all share operations would fail silently.
#
# Per-Disk Guards
#   Missing disks are skipped with a warning and the rest continue — a single
#   offline disk does not abort the full run.
#
# Empty Config Guard
#   Warns if no share .cfg files are found — catches the case where
#   /boot/config/shares/ was not restored.
#
# Notification Validated
#   platform_require_cmd confirms the notify script is present before use.
#
# ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
# No Varaverk config vars. Everything is read from Unraid's own share definitions:
#
#   /boot/config/shares/*.cfg
#       One file per share. shareInclude names the disks the share spans; the directory is
#       created on each of them. A share with no shareInclude spans all array disks.
#
#   /mnt/user
#       Must be mounted — see Array Must Be Started above.
#
# Deliberately not driven by HOST*_*_SYNC_SHARES: this recreates every share the server
# knows about, not only the ones Varaverk syncs.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# recreate_shares.sh
#     Read all .cfg files, create share directories, place .recovery markers.
#
# recreate_shares.sh --dry-run
#     Show what directories and markers would be created. No changes.
#
# recreate_shares.sh --log
#     Verbose output per share and per disk.
#
# recreate_shares.sh --status
#     Show which shares exist in config and which directories exist on disk.
#
# ==============================================================================================

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

source "$SCRIPT_DIR/../../../load_config.sh"

parse_args "$@"

SHARE_CFG_DIR="/boot/config/shares"
MARKER_FILE=".recovery"

CREATED=()
SKIPPED=()
FAILED=()

# ==============================================================================================
# ━━━ Setup ━━━
# ==============================================================================================
if [[ "$EUID" -ne 0 ]]; then
    error "Must be run as root — mkdir on /mnt/diskN requires root"
    exit 1
fi

platform_require_cmd \
    "/usr/local/emhttp/plugins/dynamix/scripts/notify" \
    "" "" \
    "unRAID notify script" || warn "unRAID notify script not found — native notifications disabled"

acquire_lock

# detect_hosts() sets MY_ID — used in summary
detect_hosts

log "$ICON_GEAR Config: cfg-dir=${SHARE_CFG_DIR} marker=${MARKER_FILE}"
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no directories or markers will be created"

# ==============================================================================================
# ━━━ Status ━━━
# ==============================================================================================
if [[ "$SHOW_STATUS" == true ]]; then
    echo ""
    echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
    echo "$ICON_HOST   Identity:  $MY_ID ($LOCAL_SERVER_NAME)"
    echo "$ICON_DISK   Cfg dir:   $SHARE_CFG_DIR"
    echo "$ICON_DISK   Marker:    $MARKER_FILE"
    echo ""

    if ! mountpoint -q /mnt/user; then
        warn "Array: NOT STARTED — /mnt/user not mounted"
    else
        echo "  Array: started ✅"
    fi

    echo ""
    echo "━━━ Share Config Files ━━━"
    CFG_COUNT=0
    for cfg in "$SHARE_CFG_DIR"/*.cfg; do
        [[ ! -f "$cfg" ]] && continue
        (( CFG_COUNT++ ))
        SHARE_NAME=$(basename "$cfg" .cfg)
        INCLUDE=$(grep '^shareInclude=' "$cfg" 2>/dev/null | cut -d'"' -f2)
        MARKER_EXISTS="no"
        [[ -f "/mnt/user/${SHARE_NAME}/${MARKER_FILE}" ]] && MARKER_EXISTS="yes"
        echo "  $ICON_DISK $SHARE_NAME — disks: ${INCLUDE:-none} — recovery marker: $MARKER_EXISTS"
    done
    [[ "$CFG_COUNT" -eq 0 ]] && warn "No .cfg files found in $SHARE_CFG_DIR"
    echo "━━━━━━━━━━━━━━━━━━━━━━━"
    exit 0
fi

# ==============================================================================================
# ━━━ Pre-flight ━━━
# ==============================================================================================
# Array must be started — /mnt/user must be mounted
if ! mountpoint -q /mnt/user; then
    error "Array is not started — /mnt/user is not mounted"
    warn "Start the array in the unRAID UI before running this script"
    notify "Recreate shares failed on $(hostname) — array is not started" \
        "Recreate Shares" "warning"
    exit 1
fi
echo "Array is started — /mnt/user is mounted ✅"

# Check share cfg directory exists and has files
if [[ ! -d "$SHARE_CFG_DIR" ]]; then
    error "Share config directory not found: $SHARE_CFG_DIR"
    error "Is /boot mounted? Is this the correct server?"
    exit 1
fi

CFG_FILES=("$SHARE_CFG_DIR"/*.cfg)
if [[ ! -f "${CFG_FILES[0]}" ]]; then
    warn "No share .cfg files found in $SHARE_CFG_DIR"
    warn "Nothing to recreate — are share configs present on /boot?"
    exit 0
fi

log "Found ${#CFG_FILES[@]} share .cfg file(s) in $SHARE_CFG_DIR"

# ==============================================================================================
# ━━━ Recreate Shares ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_DISK Recreate Shares — $MY_ID ━━━"
echo ""

for cfg in "${CFG_FILES[@]}"; do
    [[ ! -f "$cfg" ]] && continue
    SHARE_NAME=$(basename "$cfg" .cfg)
    INCLUDE=$(grep '^shareInclude=' "$cfg" 2>/dev/null | cut -d'"' -f2)

    echo "━━━ $ICON_DISK $SHARE_NAME ━━━"

    if [[ -z "$INCLUDE" ]]; then
        warn "$SHARE_NAME — no shareInclude in .cfg — skipping"
        SKIPPED+=("$SHARE_NAME")
        echo ""
        continue
    fi

    log "$SHARE_NAME — disks: $INCLUDE"

    SHARE_OK=true
    DIRS_CREATED=0
    DIRS_EXISTED=0

    # Create directory on each listed disk
    IFS=',' read -ra DISKS <<< "$INCLUDE"
    for disk in "${DISKS[@]}"; do
        disk="${disk// /}"    # trim whitespace
        [[ -z "$disk" ]] && continue

        DISK_MOUNT="/mnt/${disk}"
        DISK_PATH="${DISK_MOUNT}/${SHARE_NAME}"

        # Verify disk is mounted
        if ! mountpoint -q "$DISK_MOUNT" 2>/dev/null; then
            warn "$disk not mounted — skipping $DISK_PATH"
            continue
        fi

        if [[ -d "$DISK_PATH" ]]; then
            log "$disk/$SHARE_NAME already exists — skipping"
            (( DIRS_EXISTED++ ))
        else
            if [[ "$DRY_RUN" == true ]]; then
                warn "DRY RUN — would create: $DISK_PATH"
                (( DIRS_CREATED++ ))
            elif mkdir -p "$DISK_PATH"; then
                echo "Created: $DISK_PATH ✅"
                (( DIRS_CREATED++ ))
            else
                error "Failed to create: $DISK_PATH"
                SHARE_OK=false
            fi
        fi
    done

    # Place .recovery marker via /mnt/user (union filesystem)
    MARKER_PATH="/mnt/user/${SHARE_NAME}/${MARKER_FILE}"

    if [[ "$SHARE_OK" == true ]]; then
        if [[ -f "$MARKER_PATH" ]]; then
            log ".recovery marker already exists in $SHARE_NAME"
            CREATED+=("$SHARE_NAME")
        elif [[ "$DRY_RUN" == true ]]; then
            warn "DRY RUN — would place marker: $MARKER_PATH"
            CREATED+=("$SHARE_NAME")
        elif touch "$MARKER_PATH" 2>/dev/null; then
            echo "Marker placed: $MARKER_PATH ✅"
            CREATED+=("$SHARE_NAME")
        else
            warn "$SHARE_NAME — could not place .recovery marker"
            warn "Share directory may not be visible via /mnt/user yet"
            warn "Try: touch /mnt/user/${SHARE_NAME}/.recovery manually after verifying share"
            SKIPPED+=("$SHARE_NAME")
        fi
    else
        FAILED+=("$SHARE_NAME")
    fi

    [[ "$DIRS_CREATED" -gt 0 ]] && warn "$SHARE_NAME — created $DIRS_CREATED dir(s) on disk"
    [[ "$DIRS_EXISTED" -gt 0 ]] && log "$SHARE_NAME — $DIRS_EXISTED dir(s) already existed"
    echo ""
done

# ==============================================================================================
# ━━━ Summary ━━━
# ==============================================================================================
echo "━━━━━ $ICON_SUMMARY RECREATE SHARES SUMMARY ━━━━━"
echo "$ICON_HOST  Identity: $MY_ID ($LOCAL_SERVER_NAME)"
echo ""

[[ ${#CREATED[@]} -gt 0 ]] && warn "Created + marked: ${CREATED[*]}"
[[ ${#SKIPPED[@]} -gt 0 ]] && warn "Skipped:          ${SKIPPED[*]}"
[[ ${#FAILED[@]} -gt 0 ]]  && echo "$ICON_ERROR Failed:  ${FAILED[*]}"

echo ""
echo "  Created:  ${#CREATED[@]}"
echo "  Skipped:  ${#SKIPPED[@]}"
echo "  Failed:   ${#FAILED[@]}"

if [[ "$DRY_RUN" == false && ${#CREATED[@]} -gt 0 ]]; then
    echo ""
    echo "━━━ Next Steps ━━━"
    echo "  1. $ICON_HEALTH Verify shares are visible in unRAID UI"
    echo "  2. $ICON_SYNC   Run initial rsync push from HOST1 → HOST2"
    echo "          rsync.sh will detect .recovery markers and skip --delete"
    echo "          Normal --delete mode restores automatically on second nightly run"
    echo "  3. $ICON_GEAR   No manual config changes needed — markers self-clean ✅"
fi

echo ""
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — no changes made"
elif [[ ${#FAILED[@]} -gt 0 ]]; then
    echo "$ICON_ERROR Status: completed with failures"
    notify "Recreate shares failed on $(hostname) ($MY_ID) — failed: ${FAILED[*]}" \
        "Recreate Shares" "warning"
    exit 1
else
    echo "$ICON_DONE Status: done — ${#CREATED[@]} created, ${#SKIPPED[@]} skipped"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"