#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C.UTF-8 LANG=C.UTF-8

RELEASE_URL="${ZENVAULT_RELEASE_URL:-https://www.zenkner-technology.de/zenvault/zenvault-latest.tar.gz}"
APP_DIR=/opt/zenvault
CONF_DIR=/etc/zenvault
DATA_DIR="${ZENVAULT_DATA_DIR:-/srv/zenvault}"
PORT="${ZENVAULT_PORT:-8000}"
WITH_TAILSCALE=0

for arg in "$@"; do
  case "$arg" in
    --tailscale) WITH_TAILSCALE=1 ;;
    --port=*) PORT="${arg#*=}" ;;
    --data=*) DATA_DIR="${arg#*=}" ;;
    -h|--help)
      echo "ZenVault Installer"
      echo "  --tailscale   Tailscale installieren und ZenVault per HTTPS im Tailnet bereitstellen"
      echo "  --port=8000   Lokaler Port"
      echo "  --data=PFAD   Datenverzeichnis (Standard /srv/zenvault)"
      exit 0 ;;
  esac
done

say() { printf '\n\033[1;36m%s\033[0m\n' "$*"; }

[ "$(id -u)" -eq 0 ] || { echo "Bitte als root ausführen"; exit 1; }
command -v apt-get >/dev/null || { echo "Nur Debian und Ubuntu werden unterstützt. Alternativ Docker verwenden."; exit 1; }

say "Pakete installieren"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq python3 python3-venv python3-dev build-essential curl ca-certificates \
  postgresql postgresql-contrib tesseract-ocr tesseract-ocr-deu tesseract-ocr-eng \
  ghostscript unpaper pngquant qpdf >/dev/null

SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" 2>/dev/null && pwd || pwd)"
if [ ! -d "$SRC_DIR/zenvault" ]; then
  say "Release herunterladen"
  TMP="$(mktemp -d)"
  curl -fsSL "$RELEASE_URL" | tar -xz -C "$TMP"
  SRC_DIR="$TMP/zenvault"
fi

say "Benutzer und Verzeichnisse"
id zenvault >/dev/null 2>&1 || useradd --system --home "$APP_DIR" --shell /usr/sbin/nologin zenvault
mkdir -p "$APP_DIR" "$CONF_DIR" "$DATA_DIR/consume" "$DATA_DIR/backups"
rm -rf "$APP_DIR/zenvault" "$APP_DIR/web"
cp -r "$SRC_DIR/zenvault" "$SRC_DIR/web" "$SRC_DIR/requirements.txt" "$APP_DIR/"
cp "$SRC_DIR/install.sh" "$APP_DIR/install.sh" 2>/dev/null || true

say "Python-Umgebung"
[ -d "$APP_DIR/.venv" ] || python3 -m venv "$APP_DIR/.venv"
"$APP_DIR/.venv/bin/pip" install -q --upgrade pip
"$APP_DIR/.venv/bin/pip" install -q -r "$APP_DIR/requirements.txt"

if [ ! -f "$CONF_DIR/zenvault.env" ]; then
  say "Datenbank einrichten"
  DB_PASS="$(python3 -c 'import secrets;print(secrets.token_hex(16))')"
  SECRET="$(python3 -c 'import secrets;print(secrets.token_hex(32))')"
  systemctl enable --now postgresql >/dev/null
  su - postgres -c "psql -tc \"SELECT 1 FROM pg_roles WHERE rolname='zenvault'\"" | grep -q 1 \
    && su - postgres -c "psql -c \"ALTER USER zenvault PASSWORD '$DB_PASS'\"" >/dev/null \
    || su - postgres -c "psql -c \"CREATE USER zenvault PASSWORD '$DB_PASS'\"" >/dev/null
  su - postgres -c "psql -tc \"SELECT 1 FROM pg_database WHERE datname='zenvault'\"" | grep -q 1 \
    || su - postgres -c "createdb -O zenvault -E UTF8 -T template0 --locale=C.UTF-8 zenvault"
  su - postgres -c "psql -d zenvault -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm'" >/dev/null
  cat > "$CONF_DIR/zenvault.env" <<EOF
ZENVAULT_SECRET_KEY=$SECRET
ZENVAULT_DATABASE_URL=postgresql+psycopg://zenvault:$DB_PASS@localhost:5432/zenvault
ZENVAULT_DATA_DIR=$DATA_DIR
ZENVAULT_CONSUME_DIR=$DATA_DIR/consume
ZENVAULT_OCR_LANGUAGES=deu+eng
ZENVAULT_OCR_ENABLED=true
ZENVAULT_MAX_UPLOAD_MB=100
EOF
  chmod 600 "$CONF_DIR/zenvault.env"
fi
chown -R zenvault:zenvault "$APP_DIR"
chown zenvault:zenvault "$DATA_DIR"
find "$DATA_DIR" -mindepth 1 -maxdepth 1 ! -name lost+found -exec chown -R zenvault:zenvault {} +
chown root:zenvault "$CONF_DIR/zenvault.env"
chmod 640 "$CONF_DIR/zenvault.env"

say "Dienste einrichten"
cat > /etc/systemd/system/zenvault-api.service <<EOF
[Unit]
Description=ZenVault API
After=network.target postgresql.service

[Service]
User=zenvault
WorkingDirectory=$APP_DIR
EnvironmentFile=$CONF_DIR/zenvault.env
ExecStart=$APP_DIR/.venv/bin/uvicorn zenvault.main:app --host 0.0.0.0 --port $PORT --proxy-headers --workers 2
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/zenvault-worker.service <<EOF
[Unit]
Description=ZenVault Worker
After=network.target postgresql.service

[Service]
User=zenvault
WorkingDirectory=$APP_DIR
EnvironmentFile=$CONF_DIR/zenvault.env
ExecStart=$APP_DIR/.venv/bin/python -m zenvault.worker
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

cat > /usr/local/bin/zenvault-backup <<EOF
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C.UTF-8 LANG=C.UTF-8
STAMP=\$(date +%Y%m%d-%H%M)
su - postgres -c "pg_dump -Fc zenvault" > "$DATA_DIR/backups/zenvault-\$STAMP.dump"
find "$DATA_DIR/backups" -name 'zenvault-*.dump' -mtime +14 -delete
EOF
chmod 755 /usr/local/bin/zenvault-backup

cat > /etc/systemd/system/zenvault-backup.service <<EOF
[Unit]
Description=ZenVault Datenbank-Backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/zenvault-backup
EOF

cat > /etc/systemd/system/zenvault-backup.timer <<EOF
[Unit]
Description=ZenVault Backup täglich

[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

systemctl daemon-reload
systemctl enable --now zenvault-api zenvault-worker zenvault-backup.timer >/dev/null
systemctl restart zenvault-api zenvault-worker

if [ "$WITH_TAILSCALE" -eq 1 ]; then
  say "Tailscale einrichten"
  command -v tailscale >/dev/null || curl -fsSL https://tailscale.com/install.sh | sh
  tailscale status >/dev/null 2>&1 || tailscale up
  tailscale serve --bg "$PORT"
  ADDR="https://$(tailscale status --json | python3 -c 'import sys,json;print(json.load(sys.stdin)["Self"]["DNSName"].rstrip("."))')"
else
  ADDR="http://$(hostname -I | awk '{print $1}'):$PORT"
fi

for i in $(seq 1 30); do
  curl -fs "http://127.0.0.1:$PORT/api/status" >/dev/null && break
  sleep 1
done

say "ZenVault läuft"
echo "Adresse: $ADDR"
echo "Beim ersten Aufruf legst du das Administratorkonto an."
echo "Konfiguration: $CONF_DIR/zenvault.env"
echo "Daten: $DATA_DIR"
echo "Update: dieses Skript mit einer neueren Version erneut ausführen."
