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

usage() {
    cat <<'EOF'
Usage: ./scripts/create_admin_user.sh --username <name> --password <pass> [options]

Erstellt per HTTP-API entweder den initialen Admin (wenn noch keiner existiert)
oder legt – nach Login mit bestehenden Admin-Zugangsdaten – zusätzliche Admins an.

Benötigte Tools: curl, jq

Optionen:
  --server <url>               Backend-Basis-URL (Standard: http://localhost:5000)
  --username <name>            Neuer Admin-Benutzername (Pflicht)
  --password <pass>            Neues Admin-Passwort (Pflicht, min. 10 Zeichen)
  --role <role>                Rolle für den Benutzer (Standard: admin)
  --require-password-change    Markiert den Benutzer für Passwort-Änderung beim Login
  --admin-user <name>          Bestehender Admin (für zusätzliche Benutzer erforderlich)
  --admin-password <pass>      Passwort des bestehenden Admins
  --insecure                   TLS-Zertifikatsprüfung deaktivieren (z. B. bei Self-Signed)
  -h, --help                   Diese Hilfe anzeigen

Hinweis: Wenn bereits ein Admin existiert, müssen --admin-user und --admin-password
angegeben werden, damit sich das Skript anmelden und den neuen Benutzer anlegen kann.
EOF
}

require_cmd() {
    if ! command -v "$1" >/dev/null 2>&1; then
        echo "ERROR: Benötigtes Tool '$1' wurde nicht gefunden." >&2
        exit 1
    fi
}

# Standardwerte
SERVER_URL="${SERVER_URL:-${SERVER:-http://localhost:5000}}"
TARGET_USERNAME=""
TARGET_PASSWORD=""
TARGET_ROLE="admin"
REQUIRE_PASSWORD_CHANGE=false
ADMIN_USERNAME="${ADMIN_USERNAME:-}"
ADMIN_PASSWORD="${ADMIN_PASSWORD:-}"
CURL_INSECURE=0

while [[ $# -gt 0 ]]; do
    case "$1" in
        --server)
            SERVER_URL="$2"
            shift 2
            ;;
        --username)
            TARGET_USERNAME="$2"
            shift 2
            ;;
        --password)
            TARGET_PASSWORD="$2"
            shift 2
            ;;
        --role)
            TARGET_ROLE="$2"
            shift 2
            ;;
        --require-password-change)
            REQUIRE_PASSWORD_CHANGE=true
            shift
            ;;
        --admin-user)
            ADMIN_USERNAME="$2"
            shift 2
            ;;
        --admin-password)
            ADMIN_PASSWORD="$2"
            shift 2
            ;;
        --insecure)
            CURL_INSECURE=1
            shift
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            echo "Unbekannte Option: $1" >&2
            usage
            exit 1
            ;;
    esac
done

if [[ -z "$TARGET_USERNAME" || -z "$TARGET_PASSWORD" ]]; then
    echo "ERROR: --username und --password sind erforderlich." >&2
    usage
    exit 1
fi

require_cmd curl
require_cmd jq

BASE_URL="${SERVER_URL%/}"
COOKIE_JAR="$(mktemp)"
trap 'rm -f "$COOKIE_JAR"' EXIT

CURL_EXTRA=()
if [[ "$CURL_INSECURE" -eq 1 ]]; then
    CURL_EXTRA+=(-k)
fi

HTTP_STATUS=0
HTTP_BODY=""

api_request() {
    local method="$1"
    local url="$2"
    local data="$3"
    shift 3
    local tmp
    tmp="$(mktemp)"
    local args=(-sS -o "$tmp" -w '%{http_code}' -X "$method" -H 'Accept: application/json' -b "$COOKIE_JAR" -c "$COOKIE_JAR")
    if [[ -n "$data" ]]; then
        args+=(-H 'Content-Type: application/json' -d "$data")
    fi
    if [[ ${#CURL_EXTRA[@]} -gt 0 ]]; then
        args+=("${CURL_EXTRA[@]}")
    fi
    if [[ $# -gt 0 ]]; then
        args+=("$@")
    fi
    local status
    if ! status=$(curl "${args[@]}" "$url"); then
        rm -f "$tmp"
        echo "ERROR: HTTP-Anfrage fehlgeschlagen (${method} ${url})" >&2
        exit 1
    fi
    HTTP_STATUS="$status"
    HTTP_BODY="$(cat "$tmp")"
    rm -f "$tmp"
}

assert_status() {
    local expected="$1"
    shift || true
    local matched=0
    IFS=',' read -ra codes <<< "$expected"
    for code in "${codes[@]}"; do
        if [[ "$HTTP_STATUS" == "$code" ]]; then
            matched=1
            break
        fi
    done
    if [[ $matched -eq 0 ]]; then
        local msg
        msg=$(echo "$HTTP_BODY" | jq -r '.error // .message // empty' 2>/dev/null || true)
        if [[ -z "$msg" ]]; then
            msg="$HTTP_BODY"
        fi
        echo "ERROR: Anfrage fehlgeschlagen (${HTTP_STATUS}): $msg" >&2
        exit 1
    fi
}

json_bool() {
    if [[ "$1" == "true" ]]; then
        echo "true"
    else
        echo "false"
    fi
}

jq_payload() {
    jq -n "$@"
}

echo "INFO: Prüfe Setup-Status am ${BASE_URL}..."
api_request "GET" "${BASE_URL}/auth/setup/status" ""
assert_status "200"
needs_setup=$(echo "$HTTP_BODY" | jq -r '.needsSetup // false')

if [[ "$needs_setup" == "true" ]]; then
    echo "INFO: Kein Admin vorhanden – erstelle initialen Benutzer..."
    payload=$(jq_payload --arg username "$TARGET_USERNAME" --arg password "$TARGET_PASSWORD" '{username:$username,password:$password}')
    api_request "POST" "${BASE_URL}/auth/setup/initial-admin" "$payload"
    assert_status "201"
    user=$(echo "$HTTP_BODY" | jq -r '.user.username')
    echo "SUCCESS: Initialer Admin '$user' erstellt."
    exit 0
fi

if [[ -z "$ADMIN_USERNAME" || -z "$ADMIN_PASSWORD" ]]; then
    echo "ERROR: Bestehender Admin benötigt: bitte --admin-user und --admin-password angeben." >&2
    exit 1
fi

echo "INFO: Melde bestehenden Admin an..."
login_payload=$(jq_payload --arg username "$ADMIN_USERNAME" --arg password "$ADMIN_PASSWORD" '{username:$username,password:$password}')
api_request "POST" "${BASE_URL}/auth/login" "$login_payload"
assert_status "200"

api_request "GET" "${BASE_URL}/auth/csrf-token" ""
assert_status "200"
csrf_token=$(echo "$HTTP_BODY" | jq -r '.csrfToken // empty')
if [[ -z "$csrf_token" ]]; then
    echo "ERROR: Konnte keinen CSRF-Token abrufen." >&2
    exit 1
fi

require_flag=$(json_bool "$REQUIRE_PASSWORD_CHANGE")
create_payload=$(jq_payload --arg username "$TARGET_USERNAME" --arg password "$TARGET_PASSWORD" --arg role "$TARGET_ROLE" --argjson requirePasswordChange "$require_flag" '{username:$username,password:$password,role:($role // "admin"),requirePasswordChange:$requirePasswordChange}')

echo "INFO: Lege zusätzlichen Admin an..."
api_request "POST" "${BASE_URL}/api/admin/users" "$create_payload" -H "X-CSRF-Token: $csrf_token"
assert_status "201"
created_user=$(echo "$HTTP_BODY" | jq -r '.user.username')
created_role=$(echo "$HTTP_BODY" | jq -r '.user.role')

echo "SUCCESS: Neuer Admin '${created_user}' (Rolle: ${created_role}) wurde erstellt."
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
BACKEND_DIR="${REPO_ROOT}/backend"
NODE_SCRIPT="${BACKEND_DIR}/src/scripts/createAdminUser.js"
STAMP_FILE="${BACKEND_DIR}/.create_admin_user_deps.stamp"

usage() {
    cat <<EOF
Usage: ./scripts/create_admin_user.sh --username <name> --password <pass> [--role <role>] [--require-password-change]

Beispiele:
  ./scripts/create_admin_user.sh --username admin2 --password 'SehrSicher123!'
  ./scripts/create_admin_user.sh --username audit --password 'NochSicherer123!' --role auditor --require-password-change
EOF
}

if [[ $# -eq 0 ]]; then
    usage
    exit 1
fi

case "${1:-}" in
    -h|--help)
        usage
        exit 0
        ;;
esac

if [[ ! -f "${NODE_SCRIPT}" ]]; then
    echo "createAdminUser.js nicht gefunden (erwartet unter ${NODE_SCRIPT})." >&2
    exit 1
fi

if ! command -v node >/dev/null 2>&1; then
    echo "Node.js wird benötigt, bitte installieren." >&2
    exit 1
fi

ensure_node_modules() {
    if [[ ! -d "${BACKEND_DIR}/node_modules" ]]; then
        echo "📦 Installiere Backend-Abhängigkeiten (npm install)..."
        (cd "${BACKEND_DIR}" && npm install)
        touch "${STAMP_FILE}"
        return
    fi

    if [[ -f "${BACKEND_DIR}/package-lock.json" ]] && [[ ! -f "${STAMP_FILE}" || "${BACKEND_DIR}/package-lock.json" -nt "${STAMP_FILE}" ]]; then
        echo "📦 Aktualisiere Backend-Abhängigkeiten (npm install)..."
        (cd "${BACKEND_DIR}" && npm install)
        touch "${STAMP_FILE}"
    fi
}

ensure_node_modules

pushd "${BACKEND_DIR}" >/dev/null
# Standardmäßig teueres Preview-Rendering überspringen
export SKIP_PREVIEW_GENERATION="${SKIP_PREVIEW_GENERATION:-1}"
node "${NODE_SCRIPT}" "$@"
popd >/dev/null
