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

# csharp-maturity-scorecard.sh
#
# Purpose:
#   Measure C# code maturity with a simple evidence-based scorecard.
#   The script prompts for scores, optionally collects evidence notes, and
#   produces a concise report that can guide refactoring and release decisions.
#
# Scoring scale:
#   0 = no meaningful control
#   1 = ad hoc or inconsistent
#   2 = partially defined, with gaps
#   3 = mostly consistent and documented
#   4 = strong, repeatable, and verified
#
# Usage:
#   ./csharp-maturity-scorecard.sh
#   ./csharp-maturity-scorecard.sh --project "Billing Service"
#   ./csharp-maturity-scorecard.sh --scope "src/Billing.Api" --output report.txt
#
# Notes:
#   - No destructive actions are performed.
#   - The script does not inspect code automatically; it helps you record a repeatable
#     maturity assessment using your own evidence.

show_help() {
  cat <<'EOF'
Usage:
  csharp-maturity-scorecard.sh [--project NAME] [--scope TEXT] [--output FILE] [--threshold N]

Options:
  --project NAME     Human-readable project or service name.
  --scope TEXT       Measurement boundary, such as a project path or service name.
  --output FILE      Write the report to a file instead of stdout.
  --threshold N      Flag dimensions at or below this score as priorities (default: 2).
  -h, --help         Show this help message.

Interactive mode:
  If a score is not provided via environment variables, the script will prompt for it.

Environment variables:
  MCS_PROJECT
  MCS_SCOPE
  MCS_THRESHOLD
  MCS_OUTPUT
  MCS_DESIGN_CLARITY
  MCS_TESTABILITY
  MCS_DEPENDENCY_HYGIENE
  MCS_ERROR_HANDLING
  MCS_OBSERVABILITY
  MCS_SECURITY_POSTURE
  MCS_DELIVERY_STABILITY
EOF
}

trim() {
  local s="${1:-}"
  s="${s#${s%%[![:space:]]*}}"
  s="${s%${s##*[![:space:]]}}"
  printf '%s' "$s"
}

is_integer() {
  [[ "${1:-}" =~ ^[0-9]+$ ]]
}

validate_score() {
  local name="$1"
  local value="$2"

  if ! is_integer "$value"; then
    echo "Error: $name must be an integer from 0 to 4." >&2
    exit 1
  fi

  if (( value < 0 || value > 4 )); then
    echo "Error: $name must be between 0 and 4." >&2
    exit 1
  fi
}

prompt_score() {
  local label="$1"
  local env_name="$2"
  local default_value="${3:-}"
  local value="${!env_name:-}"

  if [[ -z "$value" ]]; then
    if [[ -n "$default_value" ]]; then
      read -r -p "$label [$default_value]: " value
      value="$(trim "$value")"
      if [[ -z "$value" ]]; then
        value="$default_value"
      fi
    else
      read -r -p "$label: " value
      value="$(trim "$value")"
    fi
  fi

  validate_score "$label" "$value"
  printf '%s' "$value"
}

prompt_text() {
  local label="$1"
  local env_name="$2"
  local value="${!env_name:-}"

  if [[ -z "$value" ]]; then
    read -r -p "$label: " value
  fi

  printf '%s' "$(trim "$value")"
}

project="${MCS_PROJECT:-C# Codebase}"
scope="${MCS_SCOPE:-unspecified scope}"
threshold="${MCS_THRESHOLD:-2}"
output="${MCS_OUTPUT:-}"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --project)
      project="${2:-}"
      shift 2
      ;;
    --scope)
      scope="${2:-}"
      shift 2
      ;;
    --output)
      output="${2:-}"
      shift 2
      ;;
    --threshold)
      threshold="${2:-}"
      shift 2
      ;;
    -h|--help)
      show_help
      exit 0
      ;;
    *)
      echo "Error: unknown option '$1'. Use --help for usage." >&2
      exit 1
      ;;
  esac
done

project="$(trim "$project")"
scope="$(trim "$scope")"
validate_score "threshold" "$threshold"

if (( threshold < 0 || threshold > 4 )); then
  echo "Error: threshold must be between 0 and 4." >&2
  exit 1
fi

cat <<EOF
C# Code Maturity Scorecard
Project: $project
Scope:   $scope
Scale:   0-4
EOF

# Core maturity dimensions aligned to practical C# delivery risk.
design_clarity="$(prompt_score "Design clarity" MCS_DESIGN_CLARITY)"
testability="$(prompt_score "Testability" MCS_TESTABILITY)"
dependency_hygiene="$(prompt_score "Dependency hygiene" MCS_DEPENDENCY_HYGIENE)"
error_handling="$(prompt_score "Error handling" MCS_ERROR_HANDLING)"
observability="$(prompt_score "Operational visibility" MCS_OBSERVABILITY)"
security_posture="$(prompt_score "Security posture" MCS_SECURITY_POSTURE)"
delivery_stability="$(prompt_score "Delivery stability" MCS_DELIVERY_STABILITY)"

# Evidence notes are optional, but strongly recommended.
read -r -p "Add evidence notes? [y/N]: " add_notes
add_notes="$(printf '%s' "$add_notes" | tr '[:upper:]' '[:lower:]')"

declare -a dimensions=(
  "Design clarity"
  "Testability"
  "Dependency hygiene"
  "Error handling"
  "Operational visibility"
  "Security posture"
  "Delivery stability"
)

declare -a scores=(
  "$design_clarity"
  "$testability"
  "$dependency_hygiene"
  "$error_handling"
  "$observability"
  "$security_posture"
  "$delivery_stability"
)

declare -a notes=("" "" "" "" "" "" "")

if [[ "$add_notes" == "y" || "$add_notes" == "yes" ]]; then
  for i in "${!dimensions[@]}"; do
    notes[$i]="$(prompt_text "Evidence for ${dimensions[$i]} (optional)" "")"
  done
fi

total=0
priority_count=0
lowest=4
for s in "${scores[@]}"; do
  (( total += s ))
  if (( s <= threshold )); then
    (( priority_count += 1 ))
  fi
  if (( s < lowest )); then
    lowest=$s
  fi
done

count=${#scores[@]}
average=$(awk -v t="$total" -v c="$count" 'BEGIN { printf "%.2f", t / c }')
percent=$(awk -v t="$total" -v c="$count" 'BEGIN { printf "%.0f", (t / (c * 4)) * 100 }')

report=$(mktemp)
{
  echo
  echo "Summary"
  echo "-------"
  echo "Total score:      $total / $((count * 4))"
  echo "Average score:    $average / 4"
  echo "Maturity percent: $percent%"
  echo "Lowest score:     $lowest"
  echo "Priority flags:   $priority_count dimension(s) at or below threshold $threshold"
  echo
  echo "Dimension scores"
  echo "----------------"
  for i in "${!dimensions[@]}"; do
    dim="${dimensions[$i]}"
    score="${scores[$i]}"
    flag=""
    if (( score <= threshold )); then
      flag=" <-- priority"
    fi
    printf '%-22s %s%s\n' "$dim" "$score" "$flag"
    if [[ -n "${notes[$i]}" ]]; then
      printf '  Evidence: %s\n' "${notes[$i]}"
    fi
  done
  echo
  echo "Recommended next actions"
  echo "------------------------"
  if (( lowest <= 1 )); then
    echo "- Treat the weakest dimension as a delivery risk and address it before broad refactoring."
  fi
  if (( testability <= threshold )); then
    echo "- Improve critical-path tests and reduce test setup friction."
  fi
  if (( error_handling <= threshold )); then
    echo "- Review exception boundaries, async failures, and logging consistency."
  fi
  if (( observability <= threshold )); then
    echo "- Add structured logs, correlation context, and useful metrics around key workflows."
  fi
  if (( security_posture <= threshold )); then
    echo "- Validate inputs near boundaries and confirm secrets and resource access are controlled."
  fi
  if (( dependency_hygiene <= threshold )); then
    echo "- Simplify dependencies and enforce clearer project or service boundaries."
  fi
  if (( delivery_stability <= threshold )); then
    echo "- Stabilize builds, CI, and release steps before using the score for release gating."
  fi
  if (( priority_count == 0 )); then
    echo "- No immediate gaps detected by this model; use trend tracking and incident data for validation."
  fi
} > "$report"

cat "$report"

if [[ -n "$output" ]]; then
  cp "$report" "$output"
  echo
  echo "Report written to: $output"
fi

rm -f "$report"
```