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

usage() {
  cat <<'EOF' >&2
Usage:
  ladill-hosting-admin self-check
  ladill-hosting-admin mkdir <path>
  ladill-hosting-admin chown <owner:group> <path>
  ladill-hosting-admin chmod <mode> <path>
  ladill-hosting-admin write-file <path> <base64-content>
  ladill-hosting-admin symlink <target> <link>
  ladill-hosting-admin nginx-test
  ladill-hosting-admin reload-nginx
  ladill-hosting-admin certbot-webroot <email> <domain> <webroot>
  ladill-hosting-admin certbot-renew
  ladill-hosting-admin run-cmd <command>
  ladill-hosting-admin read-file <path>
EOF
  exit 64
}

require_abs_path() {
  local path="${1:-}"

  if [[ -z "$path" || "${path#/}" == "$path" ]]; then
    echo "Expected an absolute path, got: $path" >&2
    exit 64
  fi
}

ensure_domain() {
  local value="${1:-}"

  if [[ ! "$value" =~ ^[A-Za-z0-9.-]+$ ]]; then
    echo "Invalid domain: $value" >&2
    exit 64
  fi
}

ensure_owner_group() {
  local value="${1:-}"

  if [[ ! "$value" =~ ^[A-Za-z_][A-Za-z0-9_-]*:[A-Za-z_][A-Za-z0-9_-]*$ ]]; then
    echo "Invalid owner:group value: $value" >&2
    exit 64
  fi
}

ensure_mode() {
  local value="${1:-}"

  if [[ ! "$value" =~ ^[0-7]{3,4}$ && ! "$value" =~ ^[ugoa,+-=rwxX]+$ ]]; then
    echo "Invalid chmod mode: $value" >&2
    exit 64
  fi
}

command="${1:-}"

case "$command" in
  self-check)
    exit 0
    ;;
  mkdir)
    [[ $# -eq 2 ]] || usage
    require_abs_path "$2"
    exec mkdir -p "$2"
    ;;
  chown)
    [[ $# -eq 3 ]] || usage
    ensure_owner_group "$2"
    require_abs_path "$3"
    exec chown -R "$2" "$3"
    ;;
  chmod)
    [[ $# -eq 3 ]] || usage
    ensure_mode "$2"
    require_abs_path "$3"
    exec chmod "$2" "$3"
    ;;
  write-file)
    [[ $# -eq 3 ]] || usage
    require_abs_path "$2"
    tmpfile="$(mktemp)"
    trap 'rm -f "$tmpfile"' EXIT
    printf '%s' "$3" | base64 --decode > "$tmpfile"
    install -m 0644 "$tmpfile" "$2"
    rm -f "$tmpfile"
    trap - EXIT
    ;;
  symlink)
    [[ $# -eq 3 ]] || usage
    require_abs_path "$2"
    require_abs_path "$3"
    exec ln -sfn "$2" "$3"
    ;;
  nginx-test)
    exec nginx -t
    ;;
  reload-nginx)
    exec systemctl reload nginx
    ;;
  certbot-webroot)
    [[ $# -eq 4 ]] || usage
    ensure_domain "$3"
    require_abs_path "$4"
    exec certbot certonly --webroot --non-interactive --agree-tos --no-eff-email -m "$2" -w "$4" -d "$3" -d "www.$3"
    ;;
  certbot-renew)
    exec certbot renew --quiet --no-random-sleep-on-renew
    ;;
  run-cmd)
    [[ $# -ge 2 ]] || usage
    shift
    exec bash -c "$*"
    ;;
  read-file)
    [[ $# -eq 2 ]] || usage
    require_abs_path "$2"
    exec cat "$2"
    ;;
  *)
    usage
    ;;
esac
