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

# Non-secret installer for the 188 user-level AWOOOI runner service. It never
# registers a runner, never reads .runner contents, and does not start the
# service unless --enable is explicitly requested after registration exists.

RUNNER_USER="${RUNNER_USER:-$(id -un)}"
RUNNER_HOME="${RUNNER_HOME:-${HOME}}"
RUNNER_DIR="${RUNNER_DIR:-${RUNNER_HOME}/act-runner-awoooi}"
RUNNER_BINARY="${RUNNER_BINARY:-${RUNNER_DIR}/act_runner}"
RUNNER_CONFIG="${RUNNER_CONFIG:-${RUNNER_DIR}/config.yaml}"
RUNNER_REGISTRATION="${RUNNER_REGISTRATION:-${RUNNER_DIR}/.runner}"
ENABLE_SENTINEL="${ENABLE_SENTINEL:-${RUNNER_DIR}/.awoooi-non110-runner-enabled}"
SERVICE_NAME="${SERVICE_NAME:-awoooi-non110-runner.service}"
ROLLBACK_SERVICE_NAME="${ROLLBACK_SERVICE_NAME:-awoooi-non110-runner-rollback.service}"
AUTOSTART_SERVICE_NAME="${AUTOSTART_SERVICE_NAME:-awoooi-non110-runner-autostart.service}"
AUTOSTART_PATH_NAME="${AUTOSTART_PATH_NAME:-awoooi-non110-runner-autostart.path}"
KEEPALIVE_SERVICE_NAME="${KEEPALIVE_SERVICE_NAME:-awoooi-non110-runner-keepalive.service}"
KEEPALIVE_TIMER_NAME="${KEEPALIVE_TIMER_NAME:-awoooi-non110-runner-keepalive.timer}"
KEEPALIVE_INTERVAL_SECONDS="${KEEPALIVE_INTERVAL_SECONDS:-15}"
USER_SERVICE_DIR="${USER_SERVICE_DIR:-${RUNNER_HOME}/.config/systemd/user}"
RUNNER_LABELS="${RUNNER_LABELS:-awoooi-non110-host:host,awoooi-non110-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04}"
WRITE_CONFIG_IF_MISSING="${WRITE_CONFIG_IF_MISSING:-1}"
RESTORE_BINARY_IF_MISSING="${RESTORE_BINARY_IF_MISSING:-1}"
CPU_QUOTA="${CPU_QUOTA:-200%}"
MEMORY_HIGH="${MEMORY_HIGH:-6G}"
MEMORY_MAX="${MEMORY_MAX:-8G}"
TASKS_MAX="${TASKS_MAX:-512}"
PRESSURE_GUARD="${PRESSURE_GUARD:-${RUNNER_HOME}/.local/bin/awoooi-wait-host-web-build-pressure.sh}"
PRESSURE_GUARD_ATTEMPTS="${PRESSURE_GUARD_ATTEMPTS:-1}"
PRESSURE_GUARD_SLEEP_SECONDS="${PRESSURE_GUARD_SLEEP_SECONDS:-0}"

ACTION="check"
if [ "$#" -gt 0 ]; then
  case "$1" in
    --check|--apply|--enable|--rollback)
      ACTION="${1#--}"
      shift
      ;;
    *)
      echo "usage: $0 [--check|--apply|--enable|--rollback]" >&2
      exit 2
      ;;
  esac
fi

service_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$SERVICE_NAME"
}

rollback_service_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$ROLLBACK_SERVICE_NAME"
}

autostart_service_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_SERVICE_NAME"
}

autostart_path_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_PATH_NAME"
}

keepalive_service_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$KEEPALIVE_SERVICE_NAME"
}

keepalive_timer_path() {
  printf '%s/%s\n' "$USER_SERVICE_DIR" "$KEEPALIVE_TIMER_NAME"
}

metadata_path() {
  local path="$1"
  if [ -e "$path" ]; then
    stat -c 'PATH=%n exists=1 type=%F mode=%a size=%s' "$path" 2>/dev/null || printf 'PATH=%s exists=1 stat=unavailable\n' "$path"
    return 0
  fi
  printf 'PATH=%s exists=0\n' "$path"
}

write_runner_service() {
  cat >"$(service_path)" <<EOF
[Unit]
Description=AWOOOI non-110 Gitea runner user service, capacity 1
After=default.target
ConditionPathExists=${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}

[Service]
Type=simple
WorkingDirectory=${RUNNER_DIR}
Environment=HOME=${RUNNER_HOME}
ExecStartPre=/usr/bin/test -x ${RUNNER_BINARY}
ExecStartPre=/usr/bin/test -S /var/run/docker.sock
ExecStartPre=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStartPre=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=${RUNNER_BINARY} daemon --config ${RUNNER_CONFIG}
Restart=always
RestartSec=20
KillSignal=SIGINT
TimeoutStartSec=120
TimeoutStopSec=3700
CPUQuota=${CPU_QUOTA}
MemoryHigh=${MEMORY_HIGH}
MemoryMax=${MEMORY_MAX}
TasksMax=${TASKS_MAX}
NoNewPrivileges=true

[Install]
WantedBy=default.target
EOF
}

write_default_config() {
  if [ "$WRITE_CONFIG_IF_MISSING" != "1" ] || [ -s "$RUNNER_CONFIG" ]; then
    return 0
  fi
  umask 077
  cat >"$RUNNER_CONFIG" <<EOF
log:
  level: info

runner:
  file: ${RUNNER_REGISTRATION}
  capacity: 1
  envs: {}
  env_file: ""
  timeout: 3h
  shutdown_timeout: 1h
  insecure: false
  fetch_timeout: 5s
  fetch_interval: 2s
  fetch_interval_max: 5s
  labels:
$(printf '%s' "$RUNNER_LABELS" | tr ',' '\n' | awk '{ printf "    - \"%s\"\n", $0 }')

cache:
  enabled: false

container:
  network: ""
  privileged: false
  valid_volumes: []
  docker_host: "unix:///var/run/docker.sock"
  force_pull: false
  force_rebuild: false
  require_docker: true

host:
  workdir_parent: ${RUNNER_DIR}/host-workdir

metrics:
  enabled: false
  addr: "127.0.0.1:9101"
EOF
  printf 'CONFIG_WRITE_PERFORMED=1 path=%s secret_values_collected=false\n' "$RUNNER_CONFIG"
}

restore_binary_from_disabled() {
  if [ "$RESTORE_BINARY_IF_MISSING" != "1" ] || [ -x "$RUNNER_BINARY" ]; then
    return 0
  fi
  local source=""
  if [ -n "${ACT_RUNNER_SOURCE:-}" ]; then
    source="$ACT_RUNNER_SOURCE"
  else
    source="$(find "$RUNNER_HOME" -maxdepth 1 -type d -name "$(basename "$RUNNER_DIR")-disabled-*" -print 2>/dev/null \
      | sort -r \
      | while IFS= read -r dir; do
          if [ -x "${dir}/act_runner" ]; then
            printf '%s/act_runner\n' "$dir"
            break
          fi
        done)"
  fi
  if [ -n "$source" ] && [ -x "$source" ]; then
    install -m 0755 "$source" "$RUNNER_BINARY"
    printf 'BINARY_RESTORE_PERFORMED=1 source=%s target=%s\n' "$source" "$RUNNER_BINARY"
    return 0
  fi
  printf 'BINARY_RESTORE_PERFORMED=0 reason=no_disabled_binary_source target=%s\n' "$RUNNER_BINARY"
}

write_rollback_service() {
  cat >"$(rollback_service_path)" <<EOF
[Unit]
Description=Rollback AWOOOI non-110 user Gitea runner to inactive

[Service]
Type=oneshot
ExecStart=-/usr/bin/systemctl --user stop ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${KEEPALIVE_SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${KEEPALIVE_SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${AUTOSTART_PATH_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${AUTOSTART_PATH_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${AUTOSTART_SERVICE_NAME}
ExecStart=-/usr/bin/rm -f ${ENABLE_SENTINEL}
RemainAfterExit=no
EOF
}

write_autostart_units() {
  cat >"$(autostart_service_path)" <<EOF
[Unit]
Description=Enable AWOOOI non-110 runner after registration metadata appears
ConditionPathExists=!${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}
ConditionPathExists=${RUNNER_BINARY}

[Service]
Type=oneshot
ExecStart=/usr/bin/test -x ${RUNNER_BINARY}
ExecStart=/usr/bin/test -s ${RUNNER_CONFIG}
ExecStart=/usr/bin/test -s ${RUNNER_REGISTRATION}
ExecStart=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStart=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=/usr/bin/touch ${ENABLE_SENTINEL}
ExecStart=/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user start ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable --now ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user disable --now ${AUTOSTART_PATH_NAME}
RemainAfterExit=no
EOF

  cat >"$(autostart_path_path)" <<EOF
[Unit]
Description=Watch AWOOOI non-110 runner registration metadata

[Path]
PathExists=${RUNNER_REGISTRATION}
Unit=${AUTOSTART_SERVICE_NAME}

[Install]
WantedBy=default.target
EOF
}

write_keepalive_units() {
  cat >"$(keepalive_service_path)" <<EOF
[Unit]
Description=Keep AWOOOI non-110 runner active while enable sentinel exists
ConditionPathExists=${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}
ConditionPathExists=${RUNNER_BINARY}

[Service]
Type=oneshot
ExecStart=/usr/bin/test -x ${RUNNER_BINARY}
ExecStart=/usr/bin/test -s ${RUNNER_CONFIG}
ExecStart=/usr/bin/test -s ${RUNNER_REGISTRATION}
ExecStart=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStart=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=/usr/bin/systemctl --user daemon-reload
ExecStart=-/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user start ${SERVICE_NAME}
RemainAfterExit=no
EOF

  cat >"$(keepalive_timer_path)" <<EOF
[Unit]
Description=Periodically verify AWOOOI non-110 runner user service is active

[Timer]
OnBootSec=30s
OnUnitInactiveSec=${KEEPALIVE_INTERVAL_SECONDS}s
AccuracySec=10s
Unit=${KEEPALIVE_SERVICE_NAME}

[Install]
WantedBy=timers.target
EOF
}

systemd_user_reload() {
  systemctl --user daemon-reload
}

readback() {
  printf 'AWOOOI_NON110_USER_INSTALLER action=%s\n' "$ACTION"
  printf 'runner_user=%s\n' "$RUNNER_USER"
  printf 'runner_home=%s\n' "$RUNNER_HOME"
  printf 'runner_dir=%s\n' "$RUNNER_DIR"
  printf 'service_name=%s\n' "$SERVICE_NAME"
  printf 'rollback_service_name=%s\n' "$ROLLBACK_SERVICE_NAME"
  printf 'autostart_service_name=%s\n' "$AUTOSTART_SERVICE_NAME"
  printf 'autostart_path_name=%s\n' "$AUTOSTART_PATH_NAME"
  printf 'keepalive_service_name=%s\n' "$KEEPALIVE_SERVICE_NAME"
  printf 'keepalive_timer_name=%s\n' "$KEEPALIVE_TIMER_NAME"
  printf 'pressure_guard=%s\n' "$PRESSURE_GUARD"
  printf 'pressure_guard_attempts=%s\n' "$PRESSURE_GUARD_ATTEMPTS"
  printf 'pressure_guard_sleep_seconds=%s\n' "$PRESSURE_GUARD_SLEEP_SECONDS"
  printf 'secret_values_collected=false\n'
  printf 'runner_token_read=false\n'
  printf 'raw_runner_registration_read=false\n'
  loginctl show-user "$RUNNER_USER" -p Linger 2>/dev/null || true
  metadata_path "$RUNNER_DIR"
  metadata_path "$RUNNER_BINARY"
  metadata_path "$RUNNER_CONFIG"
  metadata_path "$RUNNER_REGISTRATION"
  metadata_path "$ENABLE_SENTINEL"
  printf 'RUNNER_REGISTRATION content_read=false\n'
  metadata_path "$(service_path)"
  metadata_path "$(rollback_service_path)"
  metadata_path "$(autostart_service_path)"
  metadata_path "$(autostart_path_path)"
  metadata_path "$(keepalive_service_path)"
  metadata_path "$(keepalive_timer_path)"
  systemctl --user show "$SERVICE_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
  systemctl --user show "$ROLLBACK_SERVICE_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
  systemctl --user show "$AUTOSTART_PATH_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
  systemctl --user show "$KEEPALIVE_TIMER_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
}

apply_units() {
  mkdir -p "$RUNNER_DIR" "$USER_SERVICE_DIR"
  restore_binary_from_disabled
  write_default_config
  write_runner_service
  write_rollback_service
  write_autostart_units
  write_keepalive_units
  chmod 0644 \
    "$(service_path)" \
    "$(rollback_service_path)" \
    "$(autostart_service_path)" \
    "$(autostart_path_path)" \
    "$(keepalive_service_path)" \
    "$(keepalive_timer_path)"
  systemd_user_reload
  if registration_ready; then
    printf 'AUTOSTART_PATH_ENABLE_PERFORMED=0 reason=registration_ready_requires_explicit_enable\n'
  else
    systemctl --user enable --now "$AUTOSTART_PATH_NAME" >/dev/null
    printf 'AUTOSTART_PATH_ENABLE_PERFORMED=1\n'
  fi
  printf 'APPLY_PERFORMED=1\n'
  printf 'SERVICE_START_PERFORMED=0\n'
  printf 'SERVICE_ENABLE_PERFORMED=0\n'
}

registration_ready() {
  [ -x "$RUNNER_BINARY" ] && [ -s "$RUNNER_CONFIG" ] && [ -s "$RUNNER_REGISTRATION" ]
}

enable_runner() {
  apply_units
  if [ "${AWOOOI_NON110_ENABLE:-0}" != "1" ]; then
    echo "Refusing --enable without AWOOOI_NON110_ENABLE=1" >&2
    exit 1
  fi
  if ! registration_ready; then
    echo "Refusing --enable: binary/config/.runner metadata is not complete" >&2
    exit 1
  fi
  touch "$ENABLE_SENTINEL"
  systemctl --user reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user reset-failed "$AUTOSTART_SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user disable --now "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
  systemctl --user enable --now "$KEEPALIVE_TIMER_NAME"
  systemctl --user enable "$SERVICE_NAME"
  systemctl --user start "$SERVICE_NAME"
  printf 'SERVICE_ENABLE_PERFORMED=1\n'
  printf 'SERVICE_START_PERFORMED=1\n'
  printf 'KEEPALIVE_TIMER_ENABLE_PERFORMED=1\n'
}

rollback_runner() {
  systemctl --user stop "$KEEPALIVE_TIMER_NAME" >/dev/null 2>&1 || true
  systemctl --user disable "$KEEPALIVE_TIMER_NAME" >/dev/null 2>&1 || true
  systemctl --user stop "$KEEPALIVE_SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user reset-failed "$KEEPALIVE_SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user stop "$SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user disable "$SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true
  systemctl --user stop "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
  systemctl --user disable "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
  systemctl --user reset-failed "$AUTOSTART_SERVICE_NAME" >/dev/null 2>&1 || true
  rm -f "$ENABLE_SENTINEL"
  printf 'ROLLBACK_PERFORMED=1\n'
}

case "$ACTION" in
  check)
    ;;
  apply)
    apply_units
    ;;
  enable)
    enable_runner
    ;;
  rollback)
    rollback_runner
    ;;
esac

readback
