#!/bin/bash
#
# pput - upload documents to a paperless-ngx instance
#
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Usage: pput FILE [FILE...]
#
# Env:
#   PAPERLESS_URL         base URL of the instance (default below)
#   PAPERLESS_PASS_ENTRY  pass(1) entry holding the API token
#   PAPERLESS_TIMEOUT     seconds to wait per document (default 120)

set -euo pipefail

API="${PAPERLESS_URL:-http://172.16.34.52:8000}/api"
PASS_ENTRY="${PAPERLESS_PASS_ENTRY:-proxmox/paperless/api}"
TIMEOUT="${PAPERLESS_TIMEOUT:-120}"

case "${1-}" in
    -h|--help) cat >&2 <<'USAGE'; exit 0 ;;
usage: pput FILE [FILE...]

Upload documents to paperless-ngx and wait for each to be consumed.

Env:
  PAPERLESS_URL         base URL of the instance
  PAPERLESS_PASS_ENTRY  pass(1) entry holding the API token
  PAPERLESS_TIMEOUT     seconds to wait per document (default 120)
USAGE
    "") echo "usage: pput FILE [FILE...]" >&2; exit 2 ;;
esac

TOKEN=$(pass "$PASS_ENTRY") || { echo "cannot read token from pass: $PASS_ENTRY" >&2; exit 2; }

# Parse a /api/tasks/ response into "status<TAB>human message".
status() {
    python3 -c '
import json,sys
r = json.load(sys.stdin).get("results") or []
if not r:
    print("pending\t"); raise SystemExit
t = r[0]
d = t.get("result_data") or {}
st = (t.get("status") or "pending").lower()
if st == "success":
    msg = "doc %s" % (d.get("document_id") or (t.get("related_document_ids") or [""])[0])
elif "duplicate_of" in d:
    msg = "duplicate of doc %s%s" % (d["duplicate_of"],
          " (in trash)" if d.get("duplicate_in_trash") else "")
elif st == "failure":
    msg = d.get("error") or d.get("message") or (json.dumps(d) if d else "unknown error")
else:
    msg = ""
print("%s\t%s" % (st, msg))'
}

rc=0
for f in "$@"; do
    [ -r "$f" ] || { echo "skip (unreadable): $f" >&2; rc=1; continue; }

    task=$(curl -sf -H "Authorization: Token $TOKEN" \
                -H "Accept: application/json; version=10" \
                -F "document=@$f" \
                "$API/documents/post_document/" | tr -d '"') \
        || { echo "FAIL $f: upload rejected" >&2; rc=1; continue; }

    # ponytail: poll, paperless has no upload webhook. Raise PAPERLESS_TIMEOUT
    # if OCR of large scans outruns the ceiling.
    s=pending
    for _ in $(seq "$TIMEOUT"); do
        IFS=$'\t' read -r s info < <(curl -sf -H "Authorization: Token $TOKEN" \
            "$API/tasks/?task_id=$task" | status)
        case $s in
            success) echo "OK   $f -> $info"; break ;;
            failure) echo "FAIL $f: $info" >&2; rc=1; break ;;
        esac
        sleep 1
    done
    case $s in
        success|failure) ;;
        *) echo "TIMEOUT $f: task $task still $s after ${TIMEOUT}s" >&2; rc=1 ;;
    esac
done
exit $rc
