function cmd::identity::_rule() {
  local subcmd="${1:-show}"
  shift || true

  case "$subcmd" in
    assign)   cmd::identity::_rule_assign   "$@" ;;
    unassign) cmd::identity::_rule_unassign "$@" ;;
    show)     cmd::identity::_rule_show     "$@" ;;
    *)
      log::error "Unknown rule subcommand '${subcmd}'. Available: assign, unassign, show"
      return 1
      ;;
  esac
}
function cmd::identity::_rule_assign() {
  local name="" rule=""
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --name) name="$2"; shift 2 ;;
      --rule) rule="$2"; shift 2 ;;
      *) log::error "Unknown flag: $1"; return 1 ;;
    esac
  done

  [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
  [[ -z "$rule" ]] && { log::error "Missing required flag: --rule"; return 1; }
  identity::require_exists "$name" || return 1
  rule::exists "$rule" || { log::error "Rule not found: ${rule}"; return 1; }

  local exit_code
  identity::add_rule "$name" "$rule" || exit_code=$?

  if [[ $exit_code -eq 2 ]]; then
    log::warn "Rule '${rule}' is already assigned to identity '${name}'"
    return 0
  fi

  log::ok "Rule '${rule}' assigned to identity '${name}'"

  # Reapply rules if auto_apply
  local auto
  auto=$(identity::rule_flags "$name" "auto_apply")
  if [[ "$auto" != "false" ]]; then
    log::info "Reapplying rules for all peers in identity '${name}'..."
    identity::reapply_rules "$name"
    log::ok "Rules reapplied"
  fi

  # Warn about strict_rule
  if policy::strict_rule "$(identity::policy "$name")"; then
    log::warn "Strict rule is enabled for identity '${name}' — peer rules will not be additive"
  fi
}
function cmd::identity::_rule_unassign() {
  local name="" rule="" all=false
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --name) name="$2"; shift 2 ;;
      --rule) rule="$2"; shift 2 ;;
      --all)  all=true;  shift   ;;
      *) log::error "Unknown flag: $1"; return 1 ;;
    esac
  done

  [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
  identity::require_exists "$name" || return 1

  if $all; then
    local rules
    rules=$(identity::rules "$name")
    if [[ -z "$rules" ]]; then
      log::warn "Identity '${name}' has no rules assigned"
      return 0
    fi
    identity::clear_rules "$name"
    log::ok "All rules removed from identity '${name}'"
    cmd::identity::_reapply_after_unassign "$name"
    return 0
  fi

  [[ -z "$rule" ]] && {
    log::error "Missing required flag: --rule (or use --all to remove all)"
    return 1
  }

  identity::remove_rule "$name" "$rule"
  local exit_code=$?
  if [[ $exit_code -ne 0 ]]; then
    log::error "Rule '${rule}' is not assigned to identity '${name}'"
    return 1
  fi

  log::ok "Rule '${rule}' removed from identity '${name}'"
  cmd::identity::_reapply_after_unassign "$name"
}
function cmd::identity::_rule_show() {
  local name=""
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --name) name="$2"; shift 2 ;;
      *) log::error "Unknown flag: $1"; return 1 ;;
    esac
  done

  [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
  identity::require_exists "$name" || return 1

  local rules policy strict auto
  rules=$(identity::rules "$name")
  policy=$(identity::policy "$name")
  strict=$(identity::rule_flags "$name" "strict_rule")
  auto=$(identity::rule_flags "$name" "auto_apply")

  echo ""
  ui::row "Identity"    "$name"
  ui::row "Policy"      "$policy"
  ui::row "Strict rule" "$(ui::bool "$strict")"
  ui::row "Auto apply"  "$(ui::bool "$auto")"
  echo ""

  if [[ -z "$rules" ]]; then
    ui::row "Rules" "— none assigned"
  else
    printf "  %-20s\n" "Rules:"
    while IFS= read -r rule_name; do
      [[ -z "$rule_name" ]] && continue
      printf "    · %s\n" "$rule_name"
    done <<< "$rules"
  fi
  echo ""
}
