#!/bin/bash

# Per-location directory layout helpers. Each backup location is one
# directory under configs/backup/locations/<idx>/ containing:
#
#   location.config   — sourced at startup, holds CFG_BACKUP_LOC_<idx>_*
#                       including PASSWORD (auto-randomized from
#                       RANDOMIZEDPASSWORD<N> on first install)
#   ssh.key           — private SSH key when AUTH=key (chmod 0600)
#   kopia.config      — kopia adapter's connection state (chmod 0600)
#
# Everything for one location is co-located here so add/remove operations
# are mkdir / rm of one directory.

backupLocationsDir()
{
    echo "$configs_dir/backup/locations"
}

backupLocationDir()
{
    local idx="$1"
    echo "$(backupLocationsDir)/$idx"
}

backupLocationConfig()
{
    local idx="$1"
    echo "$(backupLocationDir "$idx")/location.config"
}

backupLocationSshKey()
{
    local idx="$1"
    echo "$(backupLocationDir "$idx")/ssh.key"
}

backupLocationKopiaConfig()
{
    local idx="$1"
    echo "$(backupLocationDir "$idx")/kopia.config"
}

# Owner used when chowning per-location files. Falls back to sudo_user_name
# when docker_install_user hasn't been resolved (CLI startup before
# checkInstallTypeRequirement runs).
backupLocationOwner()
{
    echo "${docker_install_user:-${sudo_user_name:-libreportal}}"
}

backupLocationEnsureDir()
{
    local idx="$1"
    local dir
    dir=$(backupLocationDir "$idx")
    local owner
    owner=$(backupLocationOwner)
    runFileOp mkdir -p "$dir"
    runFileOp chown "$owner":"$owner" "$dir"
    runFileOp chmod 0700 "$dir"
}

backupLocationResolvedPath()
{
    local idx="$1"
    local mode
    mode=$(resticLocationField "$idx" PATH_MODE)
    if [[ "$mode" == "auto" ]]; then
        # Base dir is the configurable Default Backup Location (Backup Engine
        # config); each location gets its own numbered subfolder.
        local base="${CFG_BACKUP_DEFAULT_PATH:-${backup_dir:-$docker_dir/backups}}"
        echo "${base%/}/${idx}"
    else
        resticLocationField "$idx" PATH
    fi
}

# Safety guard for LOCAL backup locations — especially external/removable drives.
# Engine-agnostic; call before init or any backup write. Returns non-zero only on
# the mount failure (so the caller refuses to write), warns (non-fatal) otherwise.
#   - Filesystem warning: the ownership model chowns the repo to the backup user,
#     which needs POSIX permissions. FAT/exFAT/NTFS can't, so warn.
#   - Mount-presence refusal: when the location sets REQUIRE_MOUNT=true (an
#     external/removable drive), refuse if the path isn't on a real mount — else
#     restic would silently write to the underlying dir on the SYSTEM disk and
#     fill it when the drive is unplugged.
backupLocationLocalGuard()
{
    local idx="$1"
    [[ -z "$idx" ]] && return 0
    [[ "$(resticLocationType "$idx")" == "local" ]] || return 0

    local base probe
    base=$(backupLocationResolvedPath "$idx"); base="${base%/}"
    [[ -z "$base" ]] && return 0
    # Probe the nearest EXISTING ancestor (the repo dir may not exist yet).
    probe="$base"
    while [[ "$probe" != "/" && ! -d "$probe" ]]; do probe="$(dirname "$probe")"; done

    if command -v findmnt >/dev/null 2>&1; then
        local fstype
        fstype=$(findmnt -no FSTYPE --target "$probe" 2>/dev/null | tail -1)
        case "$fstype" in
            vfat|exfat|ntfs|ntfs3|msdos|fuseblk)
                isNotice "Backup location $(resticLocationName "$idx"): '$probe' is $fstype — no POSIX ownership/permissions; the repo chown may fail. Prefer ext4/xfs/btrfs." ;;
        esac
    fi

    if [[ "$(resticLocationField "$idx" REQUIRE_MOUNT)" == "true" ]]; then
        local tgt=""
        command -v findmnt >/dev/null 2>&1 && tgt=$(findmnt -no TARGET --target "$probe" 2>/dev/null | tail -1)
        if [[ -z "$tgt" || "$tgt" == "/" ]]; then
            isError "Backup location $(resticLocationName "$idx"): REQUIRE_MOUNT is set but '$base' is not on a mounted drive (target: ${tgt:-unknown}). Refusing to back up to the system disk — mount the drive and retry."
            return 1
        fi
    fi
    return 0
}
