#!/usr/bin/env bash
set -Eeuo pipefail

die() { echo "postgres driver: $*" >&2; exit 1; }

load_config() {
    : "${DRIVER_CONFIG:?DRIVER_CONFIG is required}"
    [[ -r "$DRIVER_CONFIG" ]] || die "cannot read $DRIVER_CONFIG"
    set -a
    # shellcheck disable=SC1090
    source "$DRIVER_CONFIG"
    if [[ -n "${DRIVER_SECRET_FILE:-}" ]]; then
        [[ -r "$DRIVER_SECRET_FILE" ]] || die "cannot read $DRIVER_SECRET_FILE"
        # shellcheck disable=SC1090
        source "$DRIVER_SECRET_FILE"
    fi
    set +a
    : "${PGHOST:?PGHOST is required}"; : "${PGPORT:?PGPORT is required}"; : "${PGUSER:?PGUSER is required}"
    PG_COMPRESSION="${PG_COMPRESSION:-client-gzip:level=6}"
    PG_CHECKPOINT="${PG_CHECKPOINT:-fast}"
}

prepare() {
    local destination="$1"
    [[ -d "$destination" ]] || die "staging payload does not exist: $destination"
    [[ -z "$(find "$destination" -mindepth 1 -print -quit)" ]] || die "staging payload is not empty"
    pg_isready -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" || die "local PostgreSQL is unavailable"
    pg_basebackup --host="$PGHOST" --port="$PGPORT" --username="$PGUSER" \
        --pgdata="$destination" --format=tar --wal-method=stream \
        --compress="$PG_COMPRESSION" --checkpoint="$PG_CHECKPOINT" \
        --manifest-checksums=SHA256 --label="$BACKUP_NAME"
}

connectivitycheck() {
    command -v pg_basebackup >/dev/null || die "pg_basebackup is unavailable"
    pg_isready -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" || die "local PostgreSQL is unavailable"
}

healthcheck() { connectivitycheck; echo "OK: local PostgreSQL can produce a base backup"; }

wal_archive() {
    local wal_path="$1" temporary
    : "${EXPORTER_EXEC:?EXPORTER_EXEC is required}"
    mkdir -p "${STAGING_ROOT}/${INSTANCE_NAME}"
    temporary="$(mktemp "${STAGING_ROOT}/${INSTANCE_NAME}/.wal.XXXXXX.gz")"
    if ! gzip -c "$wal_path" >"$temporary" || \
        ! "$EXPORTER_EXEC" put-file "$temporary" "wal/$(basename "$wal_path").gz"; then
        rm -f -- "$temporary"; return 1
    fi
    rm -f -- "$temporary"
}

wal_restore() {
    local wal_name="$1" destination="$2" temporary
    : "${EXPORTER_EXEC:?EXPORTER_EXEC is required}"
    mkdir -p "${STAGING_ROOT}/${INSTANCE_NAME}"
    temporary="$(mktemp "${STAGING_ROOT}/${INSTANCE_NAME}/.wal-restore.XXXXXX.gz")"
    if ! "$EXPORTER_EXEC" get-file "wal/${wal_name}.gz" "$temporary" || \
        ! gzip -dc "$temporary" >"$destination"; then
        rm -f -- "$temporary"; return 1
    fi
    rm -f -- "$temporary"
}

main() {
    load_config
    case "${1:-}" in
        prepare) [[ $# -eq 2 ]] || exit 64; prepare "$2" ;;
        connectivitycheck) connectivitycheck ;;
        healthcheck) healthcheck ;;
        wal-archive) [[ $# -eq 2 ]] || exit 64; wal_archive "$2" ;;
        wal-restore) [[ $# -eq 3 ]] || exit 64; wal_restore "$2" "$3" ;;
        *) die "unsupported command: ${1:-none}" ;;
    esac
}

main "$@"
