#!/bin/bash
set -euo pipefail

# Configure the one explicitly managed church printer. The Ricoh Aficio MP
# C3502 supports PCL 6 as standard; Debian Trixie's compressed Foomatic
# database supplies this generic color PCL 6/PCL XL path without vendor code.

QUEUE="Elmer"
LEGACY_QUEUE="Classroom_Color"
DEFAULT_URI="socket://10.10.0.155:9100"
DRIVER="foomatic-db-compressed-ppds:0/ppd/foomatic-ppd/Generic-PCL_6_PCL_XL_Printer-pxlcolor.ppd"
DESCRIPTION="Elmer"
# Blank on purpose. CUPS shows Location under the queue name in every
# print dialog, and the teacher-facing identity of this printer is
# simply "Elmer".
LOCATION=""
MAKE_DEFAULT=true
COMMAND_TIMEOUT=10

usage() {
    cat <<'USAGE'
Usage: classroom-printer-setup [--no-default] [PRINTER-IP-OR-URI]

Examples:
  sudo classroom-printer-setup
  sudo classroom-printer-setup 10.10.0.155
  sudo classroom-printer-setup socket://printer.example.org:9100

With no address, configures the church Ricoh as Elmer at
socket://10.10.0.155:9100.

An IP address or hostname uses JetDirect/AppSocket on port 9100. Explicit
socket://, ipp://, ipps:// and lpd:// URIs are also accepted.
USAGE
}

log() {
    echo "[classroom-printer-setup] $1"
}

fail() {
    log "ERROR: $1" >&2
    exit 1
}

if [[ "${CLASSROOM_PRINTER_SETUP_TESTING:-false}" != "true" && $EUID -ne 0 ]]; then
    fail "run this command as root: sudo classroom-printer-setup"
fi

if [[ "${1:-}" == "--no-default" ]]; then
    MAKE_DEFAULT=false
    shift
fi

if [[ $# -gt 1 || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
    usage
    [[ $# -le 1 ]] && exit 0
    exit 2
fi

address="${1:-$DEFAULT_URI}"

case "$address" in
    socket://*|ipp://*|ipps://*|lpd://*)
        uri="$address"
        ;;
    *://*)
        fail "unsupported printer URI scheme: $address"
        ;;
    *)
        if [[ ! "$address" =~ ^[A-Za-z0-9._:-]+$ ]]; then
            fail "printer address contains unsupported characters: $address"
        fi
        uri="socket://${address}:9100"
        ;;
esac

for command in timeout lpadmin lpinfo lpoptions lpstat cupsenable cupsaccept; do
    command -v "$command" >/dev/null 2>&1 || \
        fail "$command is missing; reinstall the ekklesia-classroom package"
done

run_bounded() {
    timeout \
        --signal=TERM \
        --kill-after=2s \
        "${COMMAND_TIMEOUT}s" \
        "$@"
}

disable_discovery() {
    command -v systemctl >/dev/null 2>&1 || return 0

    # cups-browsed creates local queues for advertised printers. CUPS can also
    # enumerate DNS-SD destinations through Avahi even without cups-browsed,
    # so disable both Avahi activation paths on this single-purpose appliance.
    run_bounded systemctl disable --now cups-browsed.service \
        >/dev/null 2>&1 || true
    run_bounded systemctl disable --now \
        avahi-daemon.socket avahi-daemon.service >/dev/null 2>&1 || true
    run_bounded systemctl mask \
        avahi-daemon.socket avahi-daemon.service >/dev/null 2>&1 || true
}

disable_discovery

if ! run_bounded lpstat -r >/dev/null 2>&1; then
    command -v systemctl >/dev/null 2>&1 && \
        run_bounded systemctl start cups.service >/dev/null 2>&1 || true

    # systemctl can return as the service begins starting. Give the local
    # scheduler a short, bounded chance to create its socket.
    for _ in {1..20}; do
        run_bounded lpstat -r >/dev/null 2>&1 && break
        sleep 0.25
    done
fi

run_bounded lpstat -r >/dev/null 2>&1 || \
    fail "CUPS is not running; check: systemctl status cups"

if run_bounded lpstat -p "$LEGACY_QUEUE" >/dev/null 2>&1; then
    log "removing legacy ${LEGACY_QUEUE} queue"
    run_bounded lpadmin -x "$LEGACY_QUEUE" || \
        fail "CUPS could not remove legacy queue ${LEGACY_QUEUE}"
fi

device="$(run_bounded lpstat -v "$QUEUE" 2>/dev/null || true)"
status="$(run_bounded lpstat -p "$QUEUE" 2>/dev/null || true)"
accepting="$(run_bounded lpstat -a "$QUEUE" 2>/dev/null || true)"
default="$(run_bounded lpstat -d 2>/dev/null || true)"
details="$(run_bounded lpstat -l -p "$QUEUE" 2>/dev/null || true)"
options="$(run_bounded lpoptions -p "$QUEUE" -l 2>/dev/null || true)"

if grep -Fq ": ${uri}" <<< "$device" \
        && grep -Fq "printer ${QUEUE}" <<< "$status" \
        && grep -Fq " enabled " <<< " ${status} " \
        && grep -Fq "${QUEUE} accepting requests" <<< "$accepting" \
        && grep -Fq "system default destination: ${QUEUE}" <<< "$default" \
        && grep -Fq "Description: ${DESCRIPTION}" <<< "$details" \
        && grep -Eq '^[[:space:]]*Location:[[:space:]]*$' <<< "$details" \
        && grep -Eq '^PrintoutMode/.*:.*\*Normal([[:space:]]|$)' <<< "$options" \
        && grep -Eq '^ColorModel/.*:.*\*Color([[:space:]]|$)' <<< "$options"; then
    log "${QUEUE} is already correctly configured."
    exit 0
fi

models="$(run_bounded lpinfo -m)" || \
    fail "CUPS could not list installed printer drivers"

if ! grep -q "^${DRIVER} " <<< "$models"; then
    fail "the Debian generic color PCL 6 driver is not installed"
fi

log "configuring ${QUEUE} at ${uri}"

# Repeating this command updates the same named queue; it never creates a
# second destination. None of these operations connects to the printer.
run_bounded lpadmin \
    -p "$QUEUE" \
    -v "$uri" \
    -m "$DRIVER" \
    -D "$DESCRIPTION" \
    -L "$LOCATION" || fail "CUPS could not configure ${QUEUE}"

# CUPS on Trixie does not reliably retain PPD choices supplied in the same
# request that selects the driver. Apply the physically verified defaults in a
# second request after the PPD exists.
run_bounded lpadmin \
    -p "$QUEUE" \
    -o PrintoutMode=Normal \
    -o ColorModel=Color || fail "CUPS could not set the color defaults for ${QUEUE}"

options="$(run_bounded lpoptions -p "$QUEUE" -l 2>/dev/null || true)"

grep -Eq '^PrintoutMode/.*:.*\*Normal([[:space:]]|$)' <<< "$options" \
    || fail "CUPS did not retain PrintoutMode=Normal for ${QUEUE}"
grep -Eq '^ColorModel/.*:.*\*Color([[:space:]]|$)' <<< "$options" \
    || fail "CUPS did not retain ColorModel=Color for ${QUEUE}"

run_bounded cupsenable "$QUEUE" || fail "CUPS could not enable ${QUEUE}"
run_bounded cupsaccept "$QUEUE" || fail "CUPS could not accept jobs for ${QUEUE}"

if [[ "$MAKE_DEFAULT" == true ]]; then
    run_bounded lpadmin -d "$QUEUE" || \
        fail "CUPS could not make ${QUEUE} the default"
fi

log "${QUEUE} is configured, enabled and accepting jobs."

if [[ "$MAKE_DEFAULT" == true ]]; then
    log "${QUEUE} is the system default printer."
fi

log "Print defaults: PrintoutMode=Normal, ColorModel=Color."
log "The printer may remain offline until it is reachable; this does not affect boot."
