#!/usr/bin/env bash
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
# SecuBox-Deb :: photoprismctl
# CyberMind — https://cybermind.fr
#
# PhotoPrism host-side controller. PhotoPrism runs as a podman container inside
# a dedicated Debian LXC (default 10.100.0.130 on br-lxc, --network=host).
# Photos live on /data/shared/photos (shared with Nextcloud "PhotoLibrary").
#
# Conventions: docs/MODULE-GUIDELINES.md §7 (mirror of peertubectl/grafanactl).

set -u

readonly VERSION="1.1.0"
readonly CONFIG_FILE="${SECUBOX_PHOTOPRISM_CONFIG:-/etc/secubox/photoprism.toml}"
readonly INSTALL_LIB="${SECUBOX_INSTALL_LIB:-/usr/share/secubox/lib/photoprism/install-lxc.sh}"

readonly RED='\033[0;31m'; readonly GREEN='\033[0;32m'; readonly YELLOW='\033[1;33m'; readonly NC='\033[0m'
log()  { printf '%b[photoprism]%b %s\n' "$GREEN" "$NC" "$*"; }
warn() { printf '%b[warn]%b %s\n'    "$YELLOW" "$NC" "$*" >&2; }
err()  { printf '%b[error]%b %s\n'   "$RED"    "$NC" "$*" >&2; }

config_get() {
    local key="$1" default="${2:-}" raw=""
    [ -f "$CONFIG_FILE" ] && raw=$(grep -E "^[[:space:]]*${key}[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null | head -1)
    [ -z "$raw" ] && { echo "$default"; return; }
    local val
    val=$(echo "$raw" | cut -d= -f2- | sed 's/[[:space:]]*#.*$//' \
        | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' | tr -d '"' | tr -d "'")
    [ -z "$val" ] && echo "$default" || echo "$val"
}

LXC_NAME=$(config_get "name" "photoprism")
LXC_IP=$(config_get "ip" "10.100.0.130")
LXC_PATH=$(config_get "path" "/data/lxc")
HTTP_PORT=$(config_get "http_port" "2342")
PUBLIC_HOSTNAME=$(config_get "public_hostname" "photoprism.gk2.secubox.in")

lxc_state() {
    lxc-info -n "$LXC_NAME" -P "$LXC_PATH" 2>/dev/null \
        | awk -F: '/^State:/ { gsub(/ /,"",$2); print tolower($2) }'
}
lxc_running() { [ "$(lxc_state)" = "running" ]; }
svc() { lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- systemctl "$@" photoprism.service; }

cmd_install() {
    [ -f "$INSTALL_LIB" ] || { err "install script not found at $INSTALL_LIB"; exit 1; }
    log "Running LXC bootstrap from $INSTALL_LIB ..."
    SECUBOX_LXC_NAME="$LXC_NAME" SECUBOX_LXC_IP="$LXC_IP" SECUBOX_LXC_PATH="$LXC_PATH" \
    SECUBOX_PHOTOPRISM_HOSTNAME="$PUBLIC_HOSTNAME" \
        bash "$INSTALL_LIB"
    log "Done. Try 'photoprismctl status'."
}

cmd_status() {
    printf 'LXC %s          : %s\n' "$LXC_NAME" "$(lxc_state || echo absent)"
    if lxc_running; then
        printf 'photoprism.service : %s\n' "$(svc is-active 2>/dev/null || echo unknown)"
        if curl -fsS -o /dev/null --max-time 3 "http://$LXC_IP:$HTTP_PORT/" 2>/dev/null; then
            printf 'HTTP %s:%s     : responding\n' "$LXC_IP" "$HTTP_PORT"
        else
            printf 'HTTP %s:%s     : NOT responding\n' "$LXC_IP" "$HTTP_PORT"
        fi
        printf 'index timer        : %s\n' "$(lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- systemctl is-active photoprism-index.timer 2>/dev/null || echo unknown)"
    fi
    printf 'public URL         : https://%s/\n' "$PUBLIC_HOSTNAME"
}

cmd_start()   { lxc_running || lxc-start -n "$LXC_NAME" -P "$LXC_PATH"; svc start;   log "started"; }
cmd_stop()    { lxc_running && svc stop || true;                                     log "stopped"; }
cmd_restart() { lxc_running || lxc-start -n "$LXC_NAME" -P "$LXC_PATH"; svc restart; log "restarted"; }
cmd_logs()    { lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- journalctl -u photoprism -n "${1:-50}" --no-pager; }

cmd_index() {
    lxc_running || { err "LXC not running"; exit 1; }
    log "Triggering PhotoPrism index (picks up new Nextcloud-synced photos) ..."
    lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- podman exec photoprism photoprism index "$@"
}

cmd_reload() {
    if nginx -t 2>/dev/null; then
        systemctl reload nginx 2>/dev/null && log "host nginx reloaded" || warn "reload failed"
    else
        err "nginx -t failed; not reloading"; exit 1
    fi
}

# Provisioning push (#410): called by secubox-user-sync. Password via
# $SECUBOX_USER_PASSWORD (piped over stdin, never argv on the host). Idempotent:
# resets an existing user's password, or creates a new one scoped to a per-user
# base path (originals/<user> = /data/shared/photos/<user>). `admin` is left
# unrestricted (management); regular users are confined to their folder.
cmd_user_provision() {
    local username="${1:-}" role="${2:-user}"
    local password="${SECUBOX_USER_PASSWORD:-}"
    [ -z "$username" ] && { err "usage: SECUBOX_USER_PASSWORD=... photoprismctl user-provision <user> [role]"; return 1; }
    [ -z "$password" ] && { err "SECUBOX_USER_PASSWORD not set"; return 1; }
    case "$username" in *[!a-zA-Z0-9._-]*) err "invalid username"; return 1 ;; esac
    lxc_running || { err "LXC not running"; return 1; }

    local shared; shared=$(config_get "shared_photos" "/data/shared/photos")
    mkdir -p "$shared/$username" && chmod 0777 "$shared/$username"

    local pp_role="user"; [ "$role" = "admin" ] && pp_role="admin"
    local verb opts
    if lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- podman exec photoprism photoprism users ls 2>/dev/null | grep -qw "$username"; then
        verb="mod"; opts=""
        log "Resetting PhotoPrism password for $username"
    else
        verb="add"
        # PhotoPrism CE only offers the admin role for free; other roles need a
        # paid membership. So: admin → --superadmin; everyone else → the default
        # role, scoped by --upload-path (the only per-user scoping CE provides).
        if [ "$pp_role" = "admin" ]; then
            opts="--superadmin"
        else
            opts="--upload-path $username"
        fi
        log "Creating PhotoPrism user $username (role=$pp_role)"
    fi
    printf '%s\n' "$password" | lxc-attach -n "$LXC_NAME" -P "$LXC_PATH" -- \
        podman exec -i photoprism sh -c "read -r PPW; photoprism users $verb -p \"\$PPW\" $opts \"$username\""
}

cmd_help() {
    cat <<EOF
photoprismctl $VERSION — SecuBox PhotoPrism (podman-in-LXC) controller

Usage: photoprismctl <verb> [args]

  install            Provision the LXC + podman + PhotoPrism (idempotent)
  status             LXC + service + HTTP reachability + index timer
  start|stop|restart Control photoprism.service inside the LXC
  index [args]       Run an immediate incremental index now
  user-provision <user> [role]  Create/sync a user (SECUBOX_USER_PASSWORD env)
  logs [N]           Tail N lines of photoprism journal (default 50)
  reload             Reload host nginx
  help               This message

Config: $CONFIG_FILE  — LXC $LXC_NAME @ $LXC_IP, public https://$PUBLIC_HOSTNAME/
Photos: /data/shared/photos (shared with Nextcloud "PhotoLibrary").
EOF
}

main() {
    local noun="${1:-help}"; shift || true
    case "$noun" in
        install|status|start|stop|restart|index|logs|reload) "cmd_${noun}" "$@" ;;
        user-provision) cmd_user_provision "$@" ;;
        help|-h|--help) cmd_help ;;
        *) err "unknown verb: $noun"; cmd_help; exit 1 ;;
    esac
}

main "$@"
