#!/usr/bin/env bash
# nerf-az-boards-wi-create -- Create a new work item. Requires a type and title. Optionally set assigned-to, area, iteration, description, and a discussion comment. Returns the created work item as JSON.
# Generated from az-boards manifest. Do not edit directly.
# nerf:threat:read=remote
# nerf:threat:write=remote

if [[ "${BASH_VERSINFO[0]:-0}" -lt 4 ]]; then
  echo "error: nerf-az-boards-wi-create requires bash 4+. Found bash ${BASH_VERSION:-unknown}" >&2
  echo "  hint: on macOS, install a newer bash via 'brew install bash'" >&2
  exit 1
fi

set -euo pipefail

_NERF_DRY_RUN=""

usage() {
  cat >&2 <<'EOF'
Usage: nerf-az-boards-wi-create [--assigned-to <assigned_to>] [--area <area>] [--iteration <iteration>] [--description|-d <description>] [--discussion <discussion>] [--fields|-f <fields>] [--project|-p <project>] [-C <directory>] <type> <title>

Options:
  --assigned-to <assigned_to>
      Person to assign to (e.g. user@example.com)
  --area <area>
      Area path (e.g. MyProject\MyArea)
  --iteration <iteration>
      Iteration path (e.g. MyProject\Sprint 1)
  --description, -d <description>
      Description of the work item. Stored as HTML, so HTML markup renders (e.g. "<p>Steps:</p><ol><li>...</li></ol>"). Plain text is stored verbatim and renders as-is.
  --discussion <discussion>
      Comment to add to the work item discussion. Stored as HTML, so HTML markup renders; plain text renders as-is.
  --fields, -f <fields>
      Custom field assignment (e.g. "System.Tags=Rock")
  --project, -p <project>
      Azure DevOps project name or ID (auto-detected from the git remote if omitted)
  -C <directory>
      Resolve the Azure DevOps project from the git remote of this directory instead of cwd (must be under cwd)

Arguments:
  <type> (required)
      Work item type (e.g. Bug, Task, User Story, Feature)
  <title> (required)
      Title of the work item

Maps to: az boards work-item create --type <type> --title <title> <assigned_to> <area> <iteration> <description> <discussion> <fields> <project> --output json

Create a new work item. Requires a type and title. Optionally set assigned-to, area, iteration, description, and a discussion comment. Returns the created work item as JSON.
EOF
  exit 1
}

ASSIGNED_TO=""
_ASSIGNED_TO_SET=""
AREA=""
_AREA_SET=""
ITERATION=""
_ITERATION_SET=""
DESCRIPTION=""
_DESCRIPTION_SET=""
DISCUSSION=""
_DISCUSSION_SET=""
FIELDS=""
_FIELDS_SET=""
PROJECT=""
_PROJECT_SET=""
DIRECTORY=""
_DIRECTORY_SET=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    --assigned-to) if [[ -n "${_ASSIGNED_TO_SET}" ]]; then echo "error: --assigned-to can only be specified once" >&2; exit 1; fi; ASSIGNED_TO="$2"; _ASSIGNED_TO_SET=true; shift 2 ;;
    --area) if [[ -n "${_AREA_SET}" ]]; then echo "error: --area can only be specified once" >&2; exit 1; fi; AREA="$2"; _AREA_SET=true; shift 2 ;;
    --iteration) if [[ -n "${_ITERATION_SET}" ]]; then echo "error: --iteration can only be specified once" >&2; exit 1; fi; ITERATION="$2"; _ITERATION_SET=true; shift 2 ;;
    --description|-d) if [[ -n "${_DESCRIPTION_SET}" ]]; then echo "error: --description can only be specified once" >&2; exit 1; fi; DESCRIPTION="$2"; _DESCRIPTION_SET=true; shift 2 ;;
    --discussion) if [[ -n "${_DISCUSSION_SET}" ]]; then echo "error: --discussion can only be specified once" >&2; exit 1; fi; DISCUSSION="$2"; _DISCUSSION_SET=true; shift 2 ;;
    --fields|-f) if [[ -n "${_FIELDS_SET}" ]]; then echo "error: --fields can only be specified once" >&2; exit 1; fi; FIELDS="$2"; _FIELDS_SET=true; shift 2 ;;
    --project|-p) if [[ -n "${_PROJECT_SET}" ]]; then echo "error: --project can only be specified once" >&2; exit 1; fi; PROJECT="$2"; _PROJECT_SET=true; shift 2 ;;
    -C) if [[ -n "${_DIRECTORY_SET}" ]]; then echo "error: -C can only be specified once" >&2; exit 1; fi; DIRECTORY="$2"; _DIRECTORY_SET=true; shift 2 ;;
    --nerf-dry-run) _NERF_DRY_RUN="true"; shift 1 ;;
    -h|--help) usage ;;
    --) shift; break ;;
    *) break ;;
  esac
done

_TYPE_SET=""
if [[ $# -gt 0 ]]; then
  TYPE="$1"
  _TYPE_SET=true
  shift
else
  TYPE=""
fi
_TITLE_SET=""
if [[ $# -gt 0 ]]; then
  TITLE="$1"
  _TITLE_SET=true
  shift
else
  TITLE=""
fi
if [[ $# -gt 0 ]]; then
  echo "error: nerf-az-boards-wi-create: unexpected extra arguments: $*" >&2
  echo "  hint: switches and options must come before positional arguments" >&2
  exit 1
fi

_nerf_check_path() {
  local _label=$1 _input=$2 _tests=$3
  local _cwd _canonical
  case "$_input" in
    *$'\n'*|*$'\r'*|*$'\t'*)
      echo "error: nerf-az-boards-wi-create: ${_label}: contains illegal control character" >&2
      echo "  hint: paths must not contain newlines, carriage returns, or tabs" >&2
      return 1 ;;
  esac
  _cwd=$(realpath -- "$PWD") || {
    echo "error: nerf-az-boards-wi-create: failed to canonicalize cwd '$PWD'" >&2
    echo "  hint: invoke from a valid directory" >&2
    return 1
  }
  _canonical=$(realpath -m -- "$_input") || {
    echo "error: nerf-az-boards-wi-create: ${_label}: failed to canonicalize '${_input}'" >&2
    echo "  hint: pass a syntactically valid path" >&2
    return 1
  }
  if [[ ",$_tests," == *",under_cwd,"* ]]; then
    # Skip the prefix check when cwd is root: every absolute path qualifies, and the
    # naive prefix comparison would build "//" and reject otherwise-valid paths.
    if [[ "$_cwd" != "/" && "$_canonical" != "$_cwd" && "$_canonical" != "$_cwd"/* ]]; then
      echo "error: nerf-az-boards-wi-create: ${_label}: 'under_cwd' failed: '${_input}'" >&2
      echo "  resolves to '${_canonical}', not under '${_cwd}'" >&2
      echo "  hint: pass a path inside the current workspace" >&2
      echo "  hint: symlinks are followed -- if the link's target is outside the workspace it is rejected" >&2
      return 1
    fi
  fi
  if [[ ",$_tests," == *",exists,"* ]] && [[ ! -e "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'exists' failed: '${_input}' does not exist" >&2
    echo "  hint: create the path or pass an existing one" >&2
    return 1
  fi
  if [[ ",$_tests," == *",not_exists,"* ]] && [[ -e "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'not_exists' failed: '${_input}' already exists" >&2
    echo "  hint: choose a different path or remove the existing one first" >&2
    return 1
  fi
  if [[ ",$_tests," == *",file,"* ]] && [[ ! -f "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'file' failed: '${_input}' is not a regular file" >&2
    echo "  hint: pass a regular file path (not a directory, symlink-to-dir, device, or missing path)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",dir,"* ]] && [[ ! -d "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'dir' failed: '${_input}' is not a directory" >&2
    echo "  hint: pass a directory path (not a regular file or missing path)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",symlink,"* ]] && [[ ! -L "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'symlink' failed: '${_input}' is not a symlink" >&2
    echo "  hint: pass a symbolic link (the test does not follow the link)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",not_symlink,"* ]] && [[ -L "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'not_symlink' failed: '${_input}' is a symlink" >&2
    echo "  hint: pass a real path, not a symlink (the test does not follow the link)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",readable,"* ]] && [[ ! -r "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'readable' failed: '${_input}' is not readable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
  if [[ ",$_tests," == *",writable,"* ]] && [[ ! -w "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'writable' failed: '${_input}' is not writable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
  if [[ ",$_tests," == *",executable,"* ]] && [[ ! -x "$_input" ]]; then
    echo "error: nerf-az-boards-wi-create: ${_label}: 'executable' failed: '${_input}' is not executable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
}

if [[ -n "${_DIRECTORY_SET}" ]]; then
  _nerf_check_path 'option -C' "${DIRECTORY}" 'under_cwd' || exit 1
fi

if [[ -n "${_TYPE_SET}" ]] && [[ "${TYPE}" == -* ]]; then
  echo "error: nerf-az-boards-wi-create: <type> cannot start with '-'" >&2
  echo "  hint: use -- before positional arguments if needed" >&2
  exit 1
fi

if [[ -z "${TYPE}" ]]; then
  echo "error: nerf-az-boards-wi-create: missing required argument <type>" >&2
  echo "  hint: provide a value for <type>" >&2
  usage
fi

if [[ -n "${_TITLE_SET}" ]] && [[ "${TITLE}" == -* ]]; then
  echo "error: nerf-az-boards-wi-create: <title> cannot start with '-'" >&2
  echo "  hint: use -- before positional arguments if needed" >&2
  exit 1
fi

if [[ -z "${TITLE}" ]]; then
  echo "error: nerf-az-boards-wi-create: missing required argument <title>" >&2
  echo "  hint: provide a value for <title>" >&2
  usage
fi

_nerf_pre() {
  if [[ -n "${_DIRECTORY_SET}" ]]; then
    _URL=$(git -C "${DIRECTORY}" remote get-url origin 2>/dev/null) \
      || { echo "error: -C: no 'origin' remote in '${DIRECTORY}'" >&2; return 1; }
    _PROJ=$(echo "${_URL}" | sed -nE 's|.*dev\.azure\.com/[^/]+/([^/]+)/_git/.*|\1|p; s|.*://[^/]*visualstudio\.com/(DefaultCollection/)?([^/]+)/_git/.*|\2|p; s|.*:v3/[^/]+/([^/]+)/.*|\1|p')
    _PROJ="${_PROJ//%20/ }"
    if [[ -z "${_PROJ}" ]]; then
      echo "error: -C: could not parse Azure DevOps project from remote URL '${_URL}'" >&2
      return 1
    fi
    if [[ -z "${_PROJECT_SET}" ]]; then
      PROJECT="${_PROJ}"
      _PROJECT_SET=true
    fi
  fi
}

_nerf_pre_rc=0
_nerf_pre || _nerf_pre_rc=$?
if [ $_nerf_pre_rc -ne 0 ]; then
  echo "error: nerf-az-boards-wi-create: pre-hook failed (exit code $_nerf_pre_rc)" >&2
  exit $_nerf_pre_rc
fi

if [[ "$_NERF_DRY_RUN" == "true" ]]; then
  _NERF_DRY_CMD=(az boards work-item create --type "${TYPE}" --title "${TITLE}" ${_ASSIGNED_TO_SET:+"--assigned-to"} ${_ASSIGNED_TO_SET:+"$ASSIGNED_TO"} ${_AREA_SET:+"--area"} ${_AREA_SET:+"$AREA"} ${_ITERATION_SET:+"--iteration"} ${_ITERATION_SET:+"$ITERATION"} ${_DESCRIPTION_SET:+"--description"} ${_DESCRIPTION_SET:+"$DESCRIPTION"} ${_DISCUSSION_SET:+"--discussion"} ${_DISCUSSION_SET:+"$DISCUSSION"} ${_FIELDS_SET:+"--fields"} ${_FIELDS_SET:+"$FIELDS"} ${_PROJECT_SET:+"--project"} ${_PROJECT_SET:+"$PROJECT"} --output json)
  printf 'dry-run:'
  for _a in "${_NERF_DRY_CMD[@]}"; do printf " %q" "$_a"; done
  echo
  exit 0
fi

exec az boards work-item create --type "${TYPE}" --title "${TITLE}" ${_ASSIGNED_TO_SET:+"--assigned-to"} ${_ASSIGNED_TO_SET:+"$ASSIGNED_TO"} ${_AREA_SET:+"--area"} ${_AREA_SET:+"$AREA"} ${_ITERATION_SET:+"--iteration"} ${_ITERATION_SET:+"$ITERATION"} ${_DESCRIPTION_SET:+"--description"} ${_DESCRIPTION_SET:+"$DESCRIPTION"} ${_DISCUSSION_SET:+"--discussion"} ${_DISCUSSION_SET:+"$DISCUSSION"} ${_FIELDS_SET:+"--fields"} ${_FIELDS_SET:+"$FIELDS"} ${_PROJECT_SET:+"--project"} ${_PROJECT_SET:+"$PROJECT"} --output json
