#!/bin/sh
set -eu

SOURCE_DIR=${POBSYNC_SOURCE_DIR:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
APP_DIR=${POBSYNC_APP_DIR:-/opt/pobsync/app}
VENV_DIR=${POBSYNC_VENV_DIR:-/opt/pobsync/venv}
ENV_FILE=${POBSYNC_ENV_FILE:-/etc/pobsync/pobsync.env}
SERVICE_USER=${POBSYNC_SERVICE_USER:-pobsync}
SERVICE_GROUP=${POBSYNC_SERVICE_GROUP:-pobsync}
INSTALL_EXTRAS=${POBSYNC_INSTALL_EXTRAS:-}
SERVER_NAME=${POBSYNC_SERVER_NAME:-_}
ALLOWED_HOSTS=${POBSYNC_ALLOWED_HOSTS:-localhost,127.0.0.1}
CSRF_TRUSTED_ORIGINS=${POBSYNC_CSRF_TRUSTED_ORIGINS:-}
BACKUP_ROOT=${POBSYNC_BACKUP_ROOT:-/backups}
WEB_BIND=${POBSYNC_WEB_BIND:-127.0.0.1:8010}
FORCE_ENV=0
INSTALL_OS_PACKAGES=1
WITH_NGINX=0

while [ "$#" -gt 0 ]; do
    case "$1" in
        --source-dir)
            SOURCE_DIR=$2
            shift 2
            ;;
        --app-dir)
            APP_DIR=$2
            shift 2
            ;;
        --venv-dir)
            VENV_DIR=$2
            shift 2
            ;;
        --env-file)
            ENV_FILE=$2
            shift 2
            ;;
        --service-user)
            SERVICE_USER=$2
            shift 2
            ;;
        --service-group)
            SERVICE_GROUP=$2
            shift 2
            ;;
        --backup-root)
            BACKUP_ROOT=$2
            shift 2
            ;;
        --allowed-hosts)
            ALLOWED_HOSTS=$2
            shift 2
            ;;
        --csrf-trusted-origins)
            CSRF_TRUSTED_ORIGINS=$2
            shift 2
            ;;
        --web-bind)
            WEB_BIND=$2
            shift 2
            ;;
        --force-env)
            FORCE_ENV=1
            shift
            ;;
        --no-install-os-packages)
            INSTALL_OS_PACKAGES=0
            shift
            ;;
        --install-extras)
            INSTALL_EXTRAS=$2
            shift 2
            ;;
        --with-nginx)
            WITH_NGINX=1
            shift
            ;;
        --server-name)
            SERVER_NAME=$2
            shift 2
            ;;
        *)
            echo "Unknown argument: $1" >&2
            exit 2
            ;;
    esac
done

if [ "$(id -u)" -ne 0 ]; then
    echo "Run this installer as root." >&2
    exit 1
fi

install_os_packages() {
    if [ "$INSTALL_OS_PACKAGES" -ne 1 ]; then
        return
    fi

    if command -v apt-get >/dev/null 2>&1; then
        packages="python3 python3-venv python3-pip rsync openssh-client"
        if [ "$WITH_NGINX" -eq 1 ]; then
            packages="$packages nginx"
        fi
        if [ "$INSTALL_EXTRAS" = "mariadb" ] || [ "$INSTALL_EXTRAS" = "[mariadb]" ] || [ "$INSTALL_EXTRAS" = ".[mariadb]" ]; then
            packages="$packages default-libmysqlclient-dev build-essential pkg-config"
        fi
        apt-get update
        apt-get install -y --no-install-recommends $packages
        return
    fi

    echo "No supported package manager found; install python3, python3-venv, rsync, and openssh-client manually." >&2
}

install_os_packages

if ! command -v python3 >/dev/null 2>&1; then
    echo "python3 is required." >&2
    exit 1
fi

if ! command -v rsync >/dev/null 2>&1; then
    echo "rsync is required." >&2
    exit 1
fi

if ! command -v ssh >/dev/null 2>&1; then
    echo "openssh-client is required." >&2
    exit 1
fi

if [ ! -f "$SOURCE_DIR/manage.py" ]; then
    echo "Source directory does not look like a pobsync checkout: $SOURCE_DIR" >&2
    exit 1
fi

if ! getent group "$SERVICE_GROUP" >/dev/null 2>&1; then
    groupadd --system "$SERVICE_GROUP"
fi

if ! id "$SERVICE_USER" >/dev/null 2>&1; then
    useradd --system --home /var/lib/pobsync --shell /usr/sbin/nologin --gid "$SERVICE_GROUP" "$SERVICE_USER"
fi

mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")" "$APP_DIR" "$BACKUP_ROOT"
chown "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
chmod 0750 /var/lib/pobsync /var/log/pobsync

if [ "$SOURCE_DIR" != "$APP_DIR" ]; then
    rsync -a --delete \
        --exclude .git \
        --exclude .venv \
        --exclude __pycache__ \
        --exclude .pytest_cache \
        --exclude .mypy_cache \
        --exclude var \
        "$SOURCE_DIR"/ "$APP_DIR"/
fi

python3 -m venv "$VENV_DIR"
"$VENV_DIR/bin/python" -m pip install --upgrade pip
case "$INSTALL_EXTRAS" in
    "")
        pip_target=$APP_DIR
        ;;
    mariadb)
        pip_target="$APP_DIR[mariadb]"
        ;;
    \[*\])
        pip_target="$APP_DIR$INSTALL_EXTRAS"
        ;;
    .\[*\])
        pip_target="$APP_DIR${INSTALL_EXTRAS#.}"
        ;;
    *)
        echo "Unsupported install extras: $INSTALL_EXTRAS" >&2
        exit 2
        ;;
esac
"$VENV_DIR/bin/python" -m pip install -e "$pip_target"

if [ ! -f "$ENV_FILE" ] || [ "$FORCE_ENV" -eq 1 ]; then
    secret=$("$VENV_DIR/bin/python" -c "import secrets; print(secrets.token_urlsafe(48))")
    cat > "$ENV_FILE" <<EOF
POBSYNC_DJANGO_DEBUG=0
POBSYNC_DJANGO_SECRET_KEY=$secret
POBSYNC_DJANGO_ALLOWED_HOSTS=$ALLOWED_HOSTS
POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS

POBSYNC_HOME=/var/lib/pobsync
POBSYNC_BACKUP_ROOT=$BACKUP_ROOT
POBSYNC_SQLITE_PATH=/var/lib/pobsync/pobsync.sqlite3
POBSYNC_STATIC_ROOT=/var/lib/pobsync/static

POBSYNC_WEB_BIND=$WEB_BIND
POBSYNC_GUNICORN_WORKERS=2
POBSYNC_GUNICORN_TIMEOUT=120
POBSYNC_WORKER_INTERVAL=15
POBSYNC_SCHEDULER_INTERVAL=60
EOF
    chmod 0640 "$ENV_FILE"
    chown "root:$SERVICE_GROUP" "$ENV_FILE"
    echo "Wrote $ENV_FILE."
else
    echo "Keeping existing $ENV_FILE. Use --force-env to rewrite it."
fi

install_unit() {
    src=$1
    dest=$2
    sed \
        -e "s|@POBSYNC_APP_DIR@|$APP_DIR|g" \
        -e "s|@POBSYNC_VENV_DIR@|$VENV_DIR|g" \
        -e "s|@POBSYNC_ENV_FILE@|$ENV_FILE|g" \
        -e "s|@POBSYNC_USER@|$SERVICE_USER|g" \
        -e "s|@POBSYNC_GROUP@|$SERVICE_GROUP|g" \
        "$src" > "$dest"
    chmod 0644 "$dest"
}

install_unit "$APP_DIR/deploy/systemd/pobsync-web.service" /etc/systemd/system/pobsync-web.service
install_unit "$APP_DIR/deploy/systemd/pobsync-worker.service" /etc/systemd/system/pobsync-worker.service
install_unit "$APP_DIR/deploy/systemd/pobsync-scheduler.service" /etc/systemd/system/pobsync-scheduler.service

systemctl daemon-reload
"$VENV_DIR/bin/python" "$APP_DIR/manage.py" migrate --noinput
"$VENV_DIR/bin/python" "$APP_DIR/manage.py" collectstatic --noinput --clear
systemctl enable --now pobsync-web.service pobsync-worker.service pobsync-scheduler.service

if [ "$WITH_NGINX" -eq 1 ]; then
    if ! command -v nginx >/dev/null 2>&1; then
        echo "nginx is not installed; skipping nginx config." >&2
    else
        sed "s|@POBSYNC_SERVER_NAME@|$SERVER_NAME|g" "$APP_DIR/deploy/nginx/pobsync.conf" > /etc/nginx/sites-available/pobsync.conf
        ln -sf /etc/nginx/sites-available/pobsync.conf /etc/nginx/sites-enabled/pobsync.conf
        nginx -t
        systemctl reload nginx
    fi
fi

systemctl --no-pager --full status pobsync-web.service pobsync-worker.service pobsync-scheduler.service || true
