#!/bin/bash
# Vendored from https://github.com/bbugyi200/dotfiles via pyvendor on 2026-02-21

source "$(dirname "${BASH_SOURCE[0]}")/../lib/bugyi-260221.sh"

export USAGE_GRAMMAR=(
  "[-v] <directory> <line_limit> <warning_limit> <info_limit>"
  "-h"
)

read -r -d '' DOC <<EOM
$(usage)

Check that all Python files in a directory are below a specified line count limit.

Positional Arguments
--------------------
directory
    The directory to search for Python files (searches recursively).

line_limit
    The maximum number of lines allowed per file (hard limit, causes error).

warning_limit
    The warning threshold for line count (must be less than line_limit).
    Files exceeding this limit but below line_limit will trigger a warning.

info_limit
    The info threshold for line count (must be less than warning_limit).
    Files exceeding this limit but below warning_limit will trigger an info
    message as an FYI that a warning will be triggered soon.

Optional Arguments
------------------
-h | --help
    View this help message.

-v | --verbose
    Enable verbose output. This option can be specified multiple times (e.g. -v, -vv, ...).

Examples
--------
$(basename "${BASH_SOURCE[0]}") home/lib/gai 500 400 300
$(basename "${BASH_SOURCE[0]}") -v src 1000 750 500

EOM

function run() {
  log::debug "Command-Line Arguments: ($*)"

  eval set -- "$(getopt -o "h,v" -l "help,verbose" -- "$@")"

  VERBOSE=0
  while [[ -n "$1" ]]; do
    case $1 in
    -h | --help)
      echo "${DOC}"
      exit 0
      ;;
    -v | --verbose)
      VERBOSE=$((VERBOSE + 1))
      ;;
    --)
      shift
      break
      ;;
    esac
    shift
  done

  if [[ "${VERBOSE}" -gt 1 ]]; then
    PS4='$LINENO: '
    set -x
  fi

  readonly DOC
  readonly VERBOSE

  local directory="$1"
  local line_limit="$2"
  local warning_limit="$3"
  local info_limit="$4"

  if [[ -z "${directory}" ]]; then
    die -x2 "Error: directory argument is required"
  fi

  if [[ -z "${line_limit}" ]]; then
    die -x2 "Error: line_limit argument is required"
  fi

  if [[ -z "${warning_limit}" ]]; then
    die -x2 "Error: warning_limit argument is required"
  fi

  if [[ -z "${info_limit}" ]]; then
    die -x2 "Error: info_limit argument is required"
  fi

  if [[ ! -d "${directory}" ]]; then
    die "Error: directory '${directory}' does not exist"
  fi

  if ! [[ "${line_limit}" =~ ^[0-9]+$ ]]; then
    die "Error: line_limit must be a positive integer, got: ${line_limit}"
  fi

  if ! [[ "${warning_limit}" =~ ^[0-9]+$ ]]; then
    die "Error: warning_limit must be a positive integer, got: ${warning_limit}"
  fi

  if ! [[ "${info_limit}" =~ ^[0-9]+$ ]]; then
    die "Error: info_limit must be a positive integer, got: ${info_limit}"
  fi

  if [[ "${warning_limit}" -ge "${line_limit}" ]]; then
    die "Error: warning_limit (${warning_limit}) must be less than line_limit (${line_limit})"
  fi

  if [[ "${info_limit}" -ge "${warning_limit}" ]]; then
    die "Error: info_limit (${info_limit}) must be less than warning_limit (${warning_limit})"
  fi

  check_python_files "${directory}" "${line_limit}" "${warning_limit}" "${info_limit}"
}

function check_python_files() {
  local directory="$1"
  local line_limit="$2"
  local warning_limit="$3"
  local info_limit="$4"
  local violations=0
  local warnings=0
  local infos=0

  log::info "Checking Python files in '${directory}' for line limit of ${line_limit} (warning at ${warning_limit}, info at ${info_limit})..."

  # Find all .py files recursively and check line counts
  while IFS= read -r -d '' file; do
    local line_count
    line_count=$(wc -l < "${file}")

    if [[ "${line_count}" -gt "${line_limit}" ]]; then
      log::error "VIOLATION: ${file} has ${line_count} lines (limit: ${line_limit})"
      violations=$((violations + 1))
    elif [[ "${line_count}" -gt "${warning_limit}" ]]; then
      log::warn "WARNING: ${file} has ${line_count} lines (warning: ${warning_limit}, limit: ${line_limit})"
      warnings=$((warnings + 1))
    elif [[ "${line_count}" -gt "${info_limit}" ]]; then
      log::info "FYI: ${file} has ${line_count} lines (info: ${info_limit}, warning: ${warning_limit}) - will trigger warning soon"
      infos=$((infos + 1))
    else
      log::debug "OK: ${file} has ${line_count} lines"
    fi
  done < <(find "${directory}" -type f -name "*.py" -print0)

  if [[ "${violations}" -gt 0 ]]; then
    die "Found ${violations} file(s) exceeding line limit of ${line_limit}"
  elif [[ "${warnings}" -gt 0 ]]; then
    log::warn "Found ${warnings} file(s) exceeding warning limit of ${warning_limit}"
  elif [[ "${infos}" -gt 0 ]]; then
    log::info "Found ${infos} file(s) exceeding info limit of ${info_limit}"
  else
    log::info "All Python files are within the info limit of ${info_limit}"
  fi
}

if [[ "${SCRIPTNAME}" == "$(basename "${BASH_SOURCE[0]}")" ]]; then
  run "$@"
fi
