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

# Read-only readiness check for splitting the shared 110 Gitea runner pool.
# Run on 110, or from a workstation:
#   ssh 192.168.0.110 'bash -s' < ops/runner/check-runner-isolation-readiness.sh

PRIMARY_RUNNER_DIR="${PRIMARY_RUNNER_DIR:-/home/wooo/act-runner}"
PRIMARY_SERVICE_NAME="${PRIMARY_SERVICE_NAME:-gitea-act-runner-host.service}"
SPLIT_RUNNER_DIRS="${SPLIT_RUNNER_DIRS:-/home/wooo/act-runner-awoooi /home/wooo/act-runner-shared /home/wooo/act-runner-ewoooc}"
SPLIT_SERVICE_NAMES="${SPLIT_SERVICE_NAMES:-gitea-act-runner-awoooi.service gitea-act-runner-shared.service gitea-act-runner-ewoooc.service}"

section() {
  printf '\n== %s ==\n' "$1"
}

unit_exists() {
  local unit="$1"
  local load_state
  load_state="$(systemctl --user show "$unit" -p LoadState --value 2>/dev/null || true)"
  if [ -n "$load_state" ] && [ "$load_state" != "not-found" ]; then
    return 0
  fi
  load_state="$(systemctl show "$unit" -p LoadState --value 2>/dev/null || true)"
  [ -n "$load_state" ] && [ "$load_state" != "not-found" ]
}

unit_state() {
  local unit="$1"
  local load_state
  load_state="$(systemctl --user show "$unit" -p LoadState --value 2>/dev/null || true)"
  if [ -n "$load_state" ] && [ "$load_state" != "not-found" ]; then
    printf 'scope=user '
    systemctl --user show "$unit" -p LoadState -p ActiveState -p SubState -p MainPID --no-pager 2>/dev/null | tr '\n' ' '
    printf '\n'
    return 0
  fi
  load_state="$(systemctl show "$unit" -p LoadState --value 2>/dev/null || true)"
  if [ -n "$load_state" ] && [ "$load_state" != "not-found" ]; then
    printf 'scope=system '
    systemctl show "$unit" -p LoadState -p ActiveState -p SubState -p MainPID --no-pager 2>/dev/null | tr '\n' ' '
    printf '\n'
    return 0
  fi
  printf 'scope=missing ActiveState=missing\n'
}

extract_labels() {
  local config_path="$1"
  awk '
    /^[[:space:]]*labels:[[:space:]]*$/ {
      in_labels=1
      next
    }
    in_labels && /^[[:space:]]*-[[:space:]]*/ {
      line=$0
      sub(/^[[:space:]]*-[[:space:]]*"/, "", line)
      sub(/^[[:space:]]*-[[:space:]]*/, "", line)
      sub(/"[[:space:]]*$/, "", line)
      print line
      next
    }
    in_labels && /^[^[:space:]]/ {
      in_labels=0
    }
  ' "$config_path"
}

label_owner() {
  local label="$1"
  local label_name="${label%%:*}"
  case "$label_name" in
    awoooi-host)
      printf 'awoooi_dedicated'
      ;;
    ewoooc-host)
      printf 'foreign_dedicated'
      ;;
    ubuntu-latest|ubuntu-22.04|ubuntu-24.04|self-hosted)
      printf 'shared_queue'
      ;;
    *)
      printf 'unknown_or_custom'
      ;;
  esac
}

print_primary_runner() {
  section "primary runner"
  printf 'primary_runner_dir=%s\n' "$PRIMARY_RUNNER_DIR"
  printf 'primary_service=%s %s\n' "$PRIMARY_SERVICE_NAME" "$(unit_state "$PRIMARY_SERVICE_NAME")"

  if [ -d "$PRIMARY_RUNNER_DIR" ]; then
    find "$PRIMARY_RUNNER_DIR" -maxdepth 1 -mindepth 1 \
      -printf 'primary_file=%f type=%y mode=%M\n' 2>/dev/null | sort || true
  else
    printf 'primary_runner_dir_exists=false\n'
  fi

  if [ -f "${PRIMARY_RUNNER_DIR}/.runner" ]; then
    printf 'primary_registration_file=present\n'
  else
    printf 'primary_registration_file=missing\n'
  fi
}

print_label_owners() {
  section "primary label owners"
  local config_path="${PRIMARY_RUNNER_DIR}/config.yaml"
  if [ ! -r "$config_path" ]; then
    printf 'config_readable=false\n'
    return 0
  fi

  local labels=()
  while IFS= read -r label; do
    [ -n "$label" ] && labels+=("$label")
  done < <(extract_labels "$config_path")

  if [ "${#labels[@]}" -eq 0 ]; then
    printf 'labels_found=0\n'
    return 0
  fi

  local owner
  local mixed_owner_classes=0
  local has_awoooi=0
  local has_foreign=0
  local has_shared=0
  for label in "${labels[@]}"; do
    owner="$(label_owner "$label")"
    printf 'label=%s owner=%s\n' "$label" "$owner"
    case "$owner" in
      awoooi_dedicated) has_awoooi=1 ;;
      foreign_dedicated) has_foreign=1 ;;
      shared_queue) has_shared=1 ;;
    esac
  done

  if [ "$((has_awoooi + has_foreign + has_shared))" -gt 1 ]; then
    mixed_owner_classes=1
  fi
  printf 'mixed_owner_classes=%s\n' "$mixed_owner_classes"
}

print_split_targets() {
  section "split target readiness"
  local ready_dirs=0
  local total_dirs=0
  local dir
  for dir in $SPLIT_RUNNER_DIRS; do
    total_dirs=$((total_dirs + 1))
    if [ -d "$dir" ] && [ -f "${dir}/.runner" ] && [ -f "${dir}/config.yaml" ]; then
      ready_dirs=$((ready_dirs + 1))
      printf 'split_dir=%s status=registered\n' "$dir"
    elif [ -d "$dir" ]; then
      printf 'split_dir=%s status=incomplete\n' "$dir"
    else
      printf 'split_dir=%s status=missing\n' "$dir"
    fi
  done

  local ready_services=0
  local total_services=0
  local service
  for service in $SPLIT_SERVICE_NAMES; do
    total_services=$((total_services + 1))
    if unit_exists "$service"; then
      ready_services=$((ready_services + 1))
      printf 'split_service=%s %s\n' "$service" "$(unit_state "$service")"
    else
      printf 'split_service=%s scope=missing ActiveState=missing\n' "$service"
    fi
  done

  printf 'registered_split_dirs=%s/%s\n' "$ready_dirs" "$total_dirs"
  printf 'installed_split_services=%s/%s\n' "$ready_services" "$total_services"
}

print_active_tasks() {
  section "active tasks"
  if ! command -v docker >/dev/null 2>&1; then
    printf 'docker=unavailable\n'
    return 0
  fi
  local tasks
  tasks="$(docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' 2>/dev/null | awk '$1 ~ /^GITEA-ACTIONS-TASK-/ { print }' || true)"
  if [ -n "$tasks" ]; then
    printf '%s\n' "$tasks"
  else
    printf 'active_action_containers=none\n'
  fi
}

print_verdict() {
  section "verdict"
  local config_path="${PRIMARY_RUNNER_DIR}/config.yaml"
  local mixed=0
  if [ ! -r "$config_path" ]; then
    printf 'isolation_ready=unknown\n'
    printf 'blocker=primary_config_unreadable\n'
    printf 'safe_next_step=run_on_110_or_set_PRIMARY_RUNNER_DIR\n'
    return 0
  fi

  local owners
  owners="$(extract_labels "$config_path" | while IFS= read -r label; do printf '%s\n' "$(label_owner "$label")"; done | sort -u | wc -l | tr -d ' ')"
  if [ "${owners:-0}" -gt 1 ]; then
    mixed=1
  fi

  local split_registered=0
  local dir
  for dir in $SPLIT_RUNNER_DIRS; do
    if [ -d "$dir" ] && [ -f "${dir}/.runner" ] && [ -f "${dir}/config.yaml" ]; then
      split_registered=$((split_registered + 1))
    fi
  done

  if [ "$mixed" -eq 1 ] && [ "$split_registered" -eq 0 ]; then
    printf 'isolation_ready=false\n'
    printf 'blocker=single_registered_runner_with_mixed_owner_labels\n'
    printf 'safe_next_step=register_additional_runner_dirs_before_removing_live_labels\n'
  elif [ "$mixed" -eq 1 ]; then
    printf 'isolation_ready=partial\n'
    printf 'blocker=split_services_not_fully_installed_or_not_verified\n'
    printf 'safe_next_step=drain_then_move_labels_after_split_runner_smoke\n'
  else
    printf 'isolation_ready=true\n'
    printf 'blocker=none\n'
  fi
}

main() {
  section "audit metadata"
  printf 'host=%s\n' "$(hostname 2>/dev/null || printf unknown)"
  printf 'user=%s\n' "$(id -un 2>/dev/null || printf unknown)"
  printf 'timestamp=%s\n' "$(date -Is 2>/dev/null || date)"
  printf 'read_only=true\n'

  print_primary_runner
  print_label_owners
  print_split_targets
  print_active_tasks
  print_verdict
}

main "$@"
