#!/usr/bin/env bash
# list_users.sh — показать текущих пользователей (имена + comment, без хешей)
# Usage: ./scripts/auth/list_users.sh
set -euo pipefail

# 3× dirname от $0 (.../scripts/auth/list_users.sh) → repo root. Bug fix 2026-05-26.
SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
SNIPPET="$REPO_ROOT/caddy/users.caddy.snippet"

if [[ ! -f "$SNIPPET" ]]; then
    echo "ERROR: snippet not found at $SNIPPET" >&2
    exit 1
fi

echo "Users in $SNIPPET:"
echo ""
printf "%-12s %s\n" "USERNAME" "COMMENT"
printf "%-12s %s\n" "--------" "-------"

# Parse only the real user lines INSIDE the `basic_auth ... { ... }` block (#429).
# The previous grep `^\s+[a-z][a-z0-9-]+\s+[A-Za-z0-9+/]+=*` also matched indented
# base64-ish comment text and miscounted. Here we:
#   - enter the block on a line whose first token is `basic_auth` ending in `{`;
#   - leave it on the closing `}`;
#   - inside, skip blank and comment-only lines, require a username-shaped first
#     field (^[a-z][a-z0-9_.-]+$, matches add/remove_user.sh) AND a 2nd field
#     (the hash). Comment is whatever follows the first `#`.
# A single pass prints rows and the total, so the count can't drift from the list.
awk '
    $1 == "basic_auth" && /\{[[:space:]]*$/ { in_block = 1; next }
    in_block && /^[[:space:]]*\}/           { in_block = 0; next }
    !in_block                               { next }

    {
        line = $0
        sub(/^[[:space:]]+/, "", line)          # strip leading indent
        if (line == "" || line ~ /^#/) next     # blank / comment-only

        user = line
        sub(/[[:space:]].*$/, "", user)         # first whitespace-delimited token
        if (user !~ /^[a-z][a-z0-9_.-]+$/) next # must look like a username

        rest = line
        sub(/^[^[:space:]]+[[:space:]]+/, "", rest)  # drop username
        if (rest == "") next                    # no 2nd field -> not a user line

        hash = rest
        sub(/[[:space:]].*$/, "", hash)         # 2nd token = the hash
        # Real entry: 2nd token is a base64-encoded bcrypt hash (base64 charset,
        # long). This is what excludes indented prose like "note this ..." whose
        # 2nd word ("this") is short non-base64 text — the #429 false positive.
        if (hash !~ /^[A-Za-z0-9+\/=]{20,}$/) next

        comment = ""
        h = index(rest, "#")
        if (h > 0) {
            comment = substr(rest, h + 1)
            sub(/^[[:space:]]+/, "", comment)
        }
        printf "%-12s %s\n", user, comment
        count++
    }
    END { print ""; printf "Total: %d user(s)\n", count }
' "$SNIPPET"
