#!/usr/bin/env bash
# =============================================================================
# onx-trash-send — Move a file/dir to ~/.trash/<uuid>/ with metadata sidecar
#
# Purpose:
#   Soft-delete primitive. Instead of unlink, move the target into
#   /home/<user>/.trash/<uuid>/ alongside a .meta.json describing the original
#   path and timestamp so onx-trash-restore can put it back.
#
# Input (stdin JSON):
#   {
#     "username":  "onx_xxxx",
#     "path":      "public_html/old-stuff/draft.html"   -- required; rel to home
#   }
#
# Output (stdout JSON):
#   {
#     "trash_id":      "5f3a1b6e",
#     "original_path": "public_html/old-stuff/draft.html",
#     "trash_path":    "/home/onx_xxxx/.trash/5f3a1b6e/draft.html",
#     "size_bytes":    1247,
#     "deleted_at":    "2026-05-15T12:34:56Z"
#   }
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=execution-fail
# Deployed to: /usr/local/onoxsoft/bin/onx-trash-send
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

require_cmd jq
require_cmd mv
require_cmd stat

onx_json_input

USERNAME="$(onx_json_field username)"
REL_PATH="$(onx_json_field path)"

onx_validate_username "$USERNAME"
[[ -z "${REL_PATH}" ]] && onx_die 1 "path is required"

HOME_DIR="/home/${USERNAME}"
[[ -d "$HOME_DIR" ]] || onx_die 2 "home directory missing: ${HOME_DIR}"

TRASH_ROOT="${HOME_DIR}/.trash"
mkdir -p "${TRASH_ROOT}"
chmod 0700 "${TRASH_ROOT}" 2>/dev/null || true

SRC_ABS="$(realpath -e "${HOME_DIR}/${REL_PATH#/}" 2>/dev/null)" \
    || onx_die 1 "path not found: ${REL_PATH}"

case "${SRC_ABS}" in
    "${HOME_DIR}"|"${HOME_DIR}"/*) ;;
    *) onx_die 1 "path escapes /home/${USERNAME}: ${REL_PATH}" ;;
esac

# Refuse to trash the home root or the trash itself.
[[ "${SRC_ABS}" == "${HOME_DIR}" ]]    && onx_die 1 "cannot trash home root"
[[ "${SRC_ABS}" == "${TRASH_ROOT}" ]]  && onx_die 1 "cannot trash the trash"
case "${SRC_ABS}" in
    "${TRASH_ROOT}"/*) onx_die 1 "path already inside trash" ;;
esac

# Generate a short UUID (8 hex chars from /dev/urandom).
TRASH_ID="$(od -An -N4 -txC /dev/urandom 2>/dev/null | tr -d ' \n' || \
            printf '%s' "$(date +%s)$$" | sha256sum | cut -c1-8)"
TRASH_DIR="${TRASH_ROOT}/${TRASH_ID}"
mkdir -p "${TRASH_DIR}"
chmod 0700 "${TRASH_DIR}" 2>/dev/null || true

BASENAME="$(basename "${SRC_ABS}")"
TARGET="${TRASH_DIR}/${BASENAME}"

# Size before move (cheap on file, du for dir).
SIZE=0
IS_DIR="false"
if [[ -d "${SRC_ABS}" ]]; then
    IS_DIR="true"
    SIZE="$(du -sb "${SRC_ABS}" 2>/dev/null | awk '{print $1}')"
else
    SIZE="$(stat -c '%s' "${SRC_ABS}" 2>/dev/null || echo 0)"
fi
SIZE="${SIZE:-0}"

# Cross-device safety: try mv first, fall back to cp+rm.
SRC_DEV="$(stat -c '%d' "${SRC_ABS}" 2>/dev/null || echo 0)"
DST_DEV="$(stat -c '%d' "${TRASH_DIR}" 2>/dev/null || echo 0)"

if [[ "${SRC_DEV}" == "${DST_DEV}" ]]; then
    mv -f -- "${SRC_ABS}" "${TARGET}" 2>/dev/null \
        || onx_die 3 "trash move failed: ${REL_PATH}"
else
    cp -a -- "${SRC_ABS}" "${TARGET}" 2>/dev/null \
        || onx_die 3 "cross-device cp failed: ${REL_PATH}"
    if ! rm -rf -- "${SRC_ABS}" 2>/dev/null; then
        rm -rf -- "${TARGET}" 2>/dev/null || true
        onx_die 3 "cross-device rm failed (rolled back): ${REL_PATH}"
    fi
fi

DELETED_AT="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
ORIGINAL_REL="${SRC_ABS#${HOME_DIR}/}"

# Write metadata sidecar.
jq -nc \
    --arg trash_id "${TRASH_ID}" \
    --arg original_path "${ORIGINAL_REL}" \
    --arg original_basename "${BASENAME}" \
    --argjson size_bytes "${SIZE}" \
    --argjson is_dir "$([[ "${IS_DIR}" == "true" ]] && echo true || echo false)" \
    --arg deleted_at "${DELETED_AT}" \
    --arg deleted_by "${USERNAME}" \
    '{
        trash_id: $trash_id,
        original_path: $original_path,
        original_basename: $original_basename,
        size_bytes: $size_bytes,
        is_dir: $is_dir,
        deleted_at: $deleted_at,
        deleted_by: $deleted_by
     }' > "${TRASH_DIR}/.meta.json"
chmod 0600 "${TRASH_DIR}/.meta.json" 2>/dev/null || true

# chown trash entry to home owner.
HOME_UID="$(stat -c '%u' "${HOME_DIR}" 2>/dev/null || echo "")"
HOME_GID="$(stat -c '%g' "${HOME_DIR}" 2>/dev/null || echo "")"
if [[ -n "${HOME_UID}" && -n "${HOME_GID}" ]]; then
    chown -R "${HOME_UID}:${HOME_GID}" "${TRASH_DIR}" 2>/dev/null || true
fi

onx_log "trash-send: user=${USERNAME} path='${REL_PATH}' trash_id=${TRASH_ID} size=${SIZE}"

jq -nc \
    --arg trash_id "${TRASH_ID}" \
    --arg original_path "${ORIGINAL_REL}" \
    --arg trash_path "${TARGET}" \
    --argjson size_bytes "${SIZE}" \
    --arg deleted_at "${DELETED_AT}" \
    '{
        trash_id: $trash_id,
        original_path: $original_path,
        trash_path: $trash_path,
        size_bytes: $size_bytes,
        deleted_at: $deleted_at
     }'
