#!/usr/bin/env bash
# pdf-txt — extract clean text from OCR'd PDFs, recursively
#
# Usage:  pdf-txt <path> [<path>...]
#
#   <path> can be a .pdf file or a directory (walked recursively).
#   For each PDF with a text layer, writes a sibling .txt file using
#   pdftotext -layout, with "=== Page N ===" markers inserted.
#   Skips PDFs without a text layer.
#   Skips PDFs whose .txt is newer than the source.

set -eu

die()  { printf "ERROR: %s\n" "$*" >&2; exit 1; }
need() { command -v "$1" >/dev/null 2>&1 || die "Missing: $1 (apt install $2)"; }

need pdftotext poppler-utils
need find       findutils
need awk        gawk

processed=0; skipped_no_ocr=0; skipped_existing=0; failed=0

extract_one() {
    local pdf="$1"
    local txt="${pdf%.[Pp][Dd][Ff]}.txt"

    if [ -f "$txt" ] && [ "$txt" -nt "$pdf" ]; then
        printf "  up-to-date  %s\n" "$pdf"
        skipped_existing=$((skipped_existing + 1))
        return 0
    fi

    # OCR/text-layer detection: sample first 3 pages
    local tmp; tmp=$(mktemp)
    pdftotext -l 3 "$pdf" "$tmp" 2>/dev/null || true
    local nchars; nchars=$(tr -d '[:space:]' < "$tmp" | wc -c)
    rm -f "$tmp"

    if [ "$nchars" -lt 50 ]; then
        printf "  no OCR      %s\n" "$pdf"
        skipped_no_ocr=$((skipped_no_ocr + 1))
        return 0
    fi

    if pdftotext -layout "$pdf" - 2>/dev/null | awk '
        BEGIN { page = 1; printf "=== Page %d ===\n\n", page }
        /\014/ { page++; printf "\n=== Page %d ===\n\n", page; next }
        { print }
    ' > "$txt"; then
        printf "  extracted   %s\n" "$txt"
        processed=$((processed + 1))
    else
        rm -f "$txt"
        printf "  FAILED      %s\n" "$pdf" >&2
        failed=$((failed + 1))
    fi
}

walk() {
    local target="$1"
    if [ -f "$target" ]; then
        case "$target" in
            *.pdf|*.PDF) extract_one "$target" ;;
            *) printf "  not a PDF   %s\n" "$target" >&2 ;;
        esac
    elif [ -d "$target" ]; then
        while IFS= read -r -d '' pdf; do
            extract_one "$pdf"
        done < <(find "$target" -type f -iname '*.pdf' -print0 | sort -z)
    else
        printf "  not found   %s\n" "$target" >&2
    fi
}

[ $# -ge 1 ] || die "Usage: pdf-txt <path> [<path>...]"

for arg in "$@"; do walk "$arg"; done

printf "\nDone.  processed=%d  no_ocr=%d  up_to_date=%d  failed=%d\n" \
    "$processed" "$skipped_no_ocr" "$skipped_existing" "$failed"
