function cmd::inspect::_rule_info() {
  local name="${1:-}"
  local rule
  rule=$(peers::get_meta "$name" "rule")
  [[ -z "$rule" ]] && return 0
  rule::exists "$rule" || return 0

  cmd::inspect::_section "Rule: ${rule}"

  local rule_file
  rule_file="$(rule::path "$rule")"

  # Check for inheritance
  local extends_raw=()
  mapfile -t extends_raw < <(json::get "$rule_file" "extends" 2>/dev/null || true)

  if [[ ${#extends_raw[@]} -gt 0 && -n "${extends_raw[0]:-}" ]]; then
    # Show inheritance tree
    for base_name in "${extends_raw[@]}"; do
      [[ -z "$base_name" ]] && continue
      printf "\n    \033[0;37m↳ %s\033[0m\n" "$base_name"

      local base_allows base_blocks
      base_allows=$(rule::get "$base_name" "allow_ports")$'\n'$(rule::get "$base_name" "allow_ips")
      base_blocks=$(rule::get "$base_name" "block_ips")$'\n'$(rule::get "$base_name" "block_ports")

      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "+" "$e"
      done <<< "$base_allows"

      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "-" "$e"
      done <<< "$base_blocks"

      local base_dns
      base_dns=$(rule::get_own "$base_name" "dns_redirect")
      [[ "${base_dns,,}" == "true" ]] && \
        printf "      \033[0;36m↺\033[0m DNS → %s\n" "$(config::dns)"
    done

    # Own rules
    local own_allows own_blocks
    own_allows=$(json::get "$rule_file" "allow_ports" 2>/dev/null)$'\n'$(json::get "$rule_file" "allow_ips" 2>/dev/null)
    own_blocks=$(json::get "$rule_file" "block_ips" 2>/dev/null)$'\n'$(json::get "$rule_file" "block_ports" 2>/dev/null)
    local has_own=false

    while IFS= read -r e; do [[ -n "$e" ]] && has_own=true && break; done <<< "$own_allows$own_blocks"

    if $has_own; then
      printf "\n    \033[0;37mOwn:\033[0m\n"
      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "+" "$e"
      done <<< "$own_allows"

      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "-" "$e"
      done <<< "$own_blocks"
    fi

  else
    # No inheritance — flat view
    local allow_ports allow_ips block_ips block_ports
    allow_ports=$(rule::get "$rule" "allow_ports")
    allow_ips=$(rule::get "$rule" "allow_ips")
    block_ips=$(rule::get "$rule" "block_ips")
    block_ports=$(rule::get "$rule" "block_ports")

    if [[ -n "$allow_ports" || -n "$allow_ips" ]]; then
      printf "\n"
      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "+" "$e"
      done <<< "$allow_ports"$'\n'"$allow_ips"
    fi

    if [[ -n "$block_ips" || -n "$block_ports" ]]; then
      printf "\n"
      while IFS= read -r e; do
        [[ -z "$e" ]] && continue
        net::print_entry "-" "$e"
      done <<< "$block_ips"$'\n'"$block_ports"
    fi

    if [[ -z "$allow_ports" && -z "$allow_ips" && \
          -z "$block_ips"   && -z "$block_ports" ]]; then
      printf "\n    full access (no restrictions)\n"
    fi

    local dns_redirect
    dns_redirect=$(rule::get_own "$rule" "dns_redirect")
    [[ "${dns_redirect,,}" == "true" ]] && \
      printf "\n    \033[0;36m↺\033[0m DNS → %s\n" "$(config::dns)"
  fi

  return 0
}

function cmd::inspect::_blocks_info() {
  local name="${1:-}"
  block::has_file "$name" || return 0

  cmd::inspect::_section "Peer Blocks"

  local blocked_direct
  blocked_direct=$(block::is_blocked_direct "$name")
  [[ "$blocked_direct" == "true" ]] && \
    printf "    \033[1;31m🚫\033[0m blocked directly\n"

  local blocked_groups
  blocked_groups=$(block::get_groups "$name")
  [[ -n "$blocked_groups" ]] && \
    printf "    \033[1;31m🚫\033[0m blocked by groups: %s\n" "$blocked_groups"

  block::format_rules "$name"

  return 0
}