#!/usr/bin/env bash
#===============================================================================
# Script Name  : minimal-template.sh
# Description  : Minimal production-grade Bash script template
# Author       : <author>
# Version      : 1.0.0
# License      : MIT
# Last Updated : <date>
# Bash Version : >= 5.0
#
# Assumptions:
# - Running on Linux/macOS with GNU coreutils
# - UTF-8 locale available
#===============================================================================

#===============================================================================
# ASCII CALL GRAPH
#===============================================================================
# main()
#   ├── parse_args()
#   ├── check_dependencies()
#   ├── setup_temp()
#   ├── do_work()
#   │     └── helper_function()
#   └── cleanup() [via trap]
#===============================================================================

#===============================================================================
# GLOBAL CONSTANTS
#===============================================================================
readonly VERSION="1.0.0"
readonly SCRIPT_NAME="${0##*/}"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Exit codes
readonly E_SUCCESS=0
readonly E_GENERAL=1
readonly E_ARGS=2
readonly E_DEPS=3
readonly E_PERM=4
readonly E_NOTFOUND=5

#===============================================================================
# STRICT MODE
#===============================================================================
set -Eeuo pipefail
IFS=$' \t\n'

#===============================================================================
# CONFIGURABLE DEFAULTS
#===============================================================================
LOG_LEVEL="${LOG_LEVEL:-INFO}"
DRY_RUN=false
VERBOSE=false
FORCE=false
TEMP_DIR=""

#===============================================================================
# LOGGING & ERROR HANDLING
#===============================================================================

### Log message at DEBUG level
### @param message string Message to log
### @return 0 Always
log_debug() {
    [[ "${LOG_LEVEL}" == "DEBUG" ]] || return 0
    printf '[%s] [DEBUG] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >&2
}

### Log message at INFO level
### @param message string Message to log
### @return 0 Always
log_info() {
    [[ "${LOG_LEVEL}" =~ ^(DEBUG|INFO)$ ]] || return 0
    printf '[%s] [INFO] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >&2
}

### Log message at WARN level
### @param message string Message to log
### @return 0 Always
log_warn() {
    [[ "${LOG_LEVEL}" =~ ^(DEBUG|INFO|WARN)$ ]] || return 0
    printf '[%s] [WARN] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >&2
}

### Log message at ERROR level
### @param message string Message to log
### @return 0 Always
log_error() {
    printf '[%s] [ERROR] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >&2
}

### Exit with error message, location info, and exit code
### @param message string Error message
### @param exit_code int Exit code (default: 1)
### @return never Exits script
### @side_effect Terminates script
die() {
    local message="$1"
    local exit_code="${2:-$E_GENERAL}"
    local caller_info=""

    # > Build caller info for debugging
    if [[ "${BASH_LINENO[0]:-0}" -gt 0 ]]; then
        caller_info=" (${FUNCNAME[1]:-main}:${BASH_LINENO[0]:-?})"
    fi

    log_error "${message}${caller_info}"
    exit "$exit_code"
}

### Execute command with dry-run support
### @param cmd array Command and arguments
### @return 0 Success
### @return 1 Command failed
### @side_effect Executes external command
run_cmd() {
    local -a cmd=("$@")

    if [[ "${DRY_RUN}" == "true" ]]; then
        log_info "[DRY-RUN] Would execute: ${cmd[*]}"
        return 0
    fi

    [[ "${VERBOSE}" == "true" ]] && log_debug "Executing: ${cmd[*]}"

    if ! "${cmd[@]}"; then
        log_error "Command failed: ${cmd[*]}"
        return 1
    fi
}

### Cleanup temporary resources
### @return 0 Always
### @side_effect Removes temp directory
cleanup() {
    local exit_code=$?

    if [[ -n "${TEMP_DIR:-}" && -d "${TEMP_DIR}" ]]; then
        rm -rf "${TEMP_DIR}"
        log_debug "Cleaned up temp dir: ${TEMP_DIR}"
    fi

    exit "$exit_code"
}

# > Set traps for cleanup on exit/error/interrupt
trap cleanup EXIT ERR INT TERM

#===============================================================================
# DEPENDENCY & ENVIRONMENT CHECKS
#===============================================================================

### Check Bash version meets minimum requirement
### @return 0 Version OK
### @return 1 Version too old
### @require Bash >= 5.0
check_bash_version() {
    local required_major=5
    local required_minor=0
    local current_major="${BASH_VERSINFO[0]}"
    local current_minor="${BASH_VERSINFO[1]}"

    if (( current_major < required_major )) || \
       (( current_major == required_major && current_minor < required_minor )); then
        die "Bash >= ${required_major}.${required_minor} required (current: ${current_major}.${current_minor})" "$E_DEPS"
    fi
}

### Check required external commands exist
### @return 0 All dependencies present
### @return 3 Missing dependency
check_dependencies() {
    local -a required_cmds=("date" "mktemp" "rm")  # > Add your dependencies here
    local cmd

    for cmd in "${required_cmds[@]}"; do
        if ! command -v "$cmd" &>/dev/null; then
            die "Required command not found: $cmd" "$E_DEPS"
        fi
    done

    log_debug "All dependencies satisfied"
}

#===============================================================================
# HELPER FUNCTIONS
#===============================================================================

### Create temporary directory
### @return 0 Success
### @side_effect Sets TEMP_DIR global
setup_temp() {
    TEMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/${SCRIPT_NAME}.XXXXXX")"
    readonly TEMP_DIR
    log_debug "Created temp dir: ${TEMP_DIR}"
}

### Display usage information
### @return 0 Always
usage() {
    cat <<EOF
Usage: ${SCRIPT_NAME} [OPTIONS] <argument>

Description:
    Brief description of what this script does.

Options:
    -h, --help      Show this help message
    -v, --verbose   Enable verbose output
    -q, --quiet     Suppress non-error output
    -n, --dry-run   Show what would be done without executing
    -f, --force     Force operation (skip confirmations)
    --version       Show version information

Arguments:
    <argument>      Description of required argument

Examples:
    ${SCRIPT_NAME} --help
    ${SCRIPT_NAME} --dry-run input.txt
    ${SCRIPT_NAME} --verbose --force input.txt

Exit Codes:
    0   Success
    1   General error
    2   Invalid arguments
    3   Missing dependency
    4   Permission denied
    5   Resource not found

EOF
}

#===============================================================================
# BUSINESS FUNCTIONS
#===============================================================================

### Main business logic (replace with actual implementation)
### @param input string Input to process
### @return 0 Success
### @return 1 Processing failed
do_work() {
    local input="$1"

    log_info "Processing: ${input}"

    # > Replace with actual business logic
    run_cmd echo "Working on: ${input}"

    log_info "Done"
}

#===============================================================================
# ARGUMENT PARSING
#===============================================================================

### Parse command line arguments
### @param args array Command line arguments
### @return 0 Success
### @return 2 Invalid argument
parse_args() {
    local positional=()

    while [[ $# -gt 0 ]]; do
        case "$1" in
            -h|--help)
                usage
                exit "$E_SUCCESS"
                ;;
            --version)
                echo "${SCRIPT_NAME} version ${VERSION}"
                exit "$E_SUCCESS"
                ;;
            -v|--verbose)
                VERBOSE=true
                LOG_LEVEL="DEBUG"
                shift
                ;;
            -q|--quiet)
                LOG_LEVEL="ERROR"
                shift
                ;;
            -n|--dry-run)
                DRY_RUN=true
                shift
                ;;
            -f|--force)
                FORCE=true
                shift
                ;;
            --)
                shift
                positional+=("$@")
                break
                ;;
            -*)
                die "Unknown option: $1" "$E_ARGS"
                ;;
            *)
                positional+=("$1")
                shift
                ;;
        esac
    done

    # > Restore positional parameters
    set -- "${positional[@]}"

    # > Validate required arguments
    if [[ $# -lt 1 ]]; then
        die "Missing required argument. Use --help for usage." "$E_ARGS"
    fi

    # > Export parsed values for main()
    INPUT_ARG="$1"
}

#===============================================================================
# MAIN
#===============================================================================

### Main entry point - orchestrates script execution
### @param args array Command line arguments
### @return 0 Success
main() {
    check_bash_version
    parse_args "$@"
    check_dependencies
    setup_temp

    log_info "Starting ${SCRIPT_NAME} v${VERSION}"
    [[ "${DRY_RUN}" == "true" ]] && log_warn "Running in dry-run mode"

    do_work "${INPUT_ARG}"

    log_info "Completed successfully"
}

# > Entry point
main "$@"

#===============================================================================
# SELF-TEST EXAMPLES
#===============================================================================
# Run these commands to verify script behavior:
#
# 1. Show help:
#    ./minimal-template.sh --help
#
# 2. Dry-run mode:
#    ./minimal-template.sh --dry-run test-input
#
# 3. Invalid argument (expect exit 2):
#    ./minimal-template.sh --invalid-option
#
# 4. Missing argument (expect exit 2):
#    ./minimal-template.sh
#
# 5. Verbose mode:
#    ./minimal-template.sh --verbose test-input
#===============================================================================
