#!/bin/bash
# freeipa-client.sh — FreeIPA client enrollment
#
# Three modes:
#   --answerfile FILE    Read settings from a JSON file (jq required)
#   --interactive        Prompt for every setting
#   [flags]              Pass any flags directly to freeipa-enroll.sh
#
# All flags accepted by freeipa-enroll.sh work here too and override
# any values loaded from an answerfile or interactive prompts.
#
# JSON answerfile schema:
#   {
#     "domain":      "freeipa.abdelbaki.eu",
#     "realm":       "FREEIPA.ABDELBAKI.EU",
#     "server":      "freeipa.abdelbaki.eu",
#     "hostname":    "",          <- leave blank to use current hostname
#     "principal":   "admin",
#     "password":    "",          <- will prompt if blank
#     "mkhomedir":   true,
#     "sudo":        true,
#     "dns_update":  true,
#     "ntp_server":  "",
#     "fido2":       false,
#     "fido2_users": []
#   }

set -euo pipefail

SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENROLL="$SELF_DIR/freeipa-enroll.sh"

[[ ! -x "$ENROLL" ]] && { echo "Error: freeipa-enroll.sh not found at $ENROLL" >&2; exit 1; }

# Defaults (match freeipa-enroll.sh hardcoded values; freeipa-server.sh will
# sed-replace these when generating customized copies)
IPA_DOMAIN="freeipa.abdelbaki.eu"
IPA_REALM="FREEIPA.ABDELBAKI.EU"
IPA_SERVER="freeipa.abdelbaki.eu"

MODE=""
ANSWERFILE=""
PASSTHROUGH=()

while [[ $# -gt 0 ]]; do
    case $1 in
        --answerfile)  MODE="answerfile"; ANSWERFILE="$2"; shift 2 ;;
        --interactive) MODE="interactive"; shift ;;
        *)             PASSTHROUGH+=("$1"); shift ;;
    esac
done

# ─── Answerfile mode ──────────────────────────────────────────────────────────
if [[ "$MODE" == "answerfile" ]]; then
    [[ ! -f "$ANSWERFILE" ]] && { echo "Error: answerfile not found: $ANSWERFILE" >&2; exit 1; }
    command -v jq &>/dev/null  || { echo "Error: jq is required for answerfile mode" >&2; exit 1; }

    get()      { jq -r "$1 // empty" "$ANSWERFILE"; }
    get_bool() { jq -r "$1 // empty" "$ANSWERFILE"; }

    AF_DOMAIN=$(get '.domain')
    AF_REALM=$(get '.realm')
    AF_SERVER=$(get '.server')
    AF_HOSTNAME=$(get '.hostname')
    AF_PRINCIPAL=$(get '.principal')
    AF_PASSWORD=$(get '.password')
    AF_NTP=$(get '.ntp_server')
    AF_MKHOMEDIR=$(get_bool '.mkhomedir')
    AF_SUDO=$(get_bool '.sudo')
    AF_DNS_UPDATE=$(get_bool '.dns_update')
    AF_FIDO2=$(get_bool '.fido2')
    mapfile -t AF_FIDO2_USERS < <(jq -r '.fido2_users // [] | .[]' "$ANSWERFILE")

    ARGS=()
    [[ -n "$AF_DOMAIN"    ]] && ARGS+=(--domain    "$AF_DOMAIN")
    [[ -n "$AF_REALM"     ]] && ARGS+=(--realm     "$AF_REALM")
    [[ -n "$AF_SERVER"    ]] && ARGS+=(--server    "$AF_SERVER")
    [[ -n "$AF_HOSTNAME"  ]] && ARGS+=(--hostname  "$AF_HOSTNAME")
    [[ -n "$AF_PRINCIPAL" ]] && ARGS+=(--principal "$AF_PRINCIPAL")
    [[ -n "$AF_NTP"       ]] && ARGS+=(--ntp-server "$AF_NTP")

    if [[ -z "$AF_PASSWORD" ]]; then
        if [[ "${MARCHY_UNATTENDED:-0}" == "1" || ! -t 0 ]]; then
            echo "Error: answerfile has no password and no terminal is attached to prompt for one — skipping enrollment." >&2
            exit 1
        fi
        printf '[?] Password for %s@%s: ' "${AF_PRINCIPAL:-admin}" "${AF_REALM:-REALM}"
        read -rs AF_PASSWORD; echo
    fi
    ARGS+=(--password "$AF_PASSWORD")

    [[ "$AF_MKHOMEDIR"  == "false" ]] && ARGS+=(--no-mkhomedir)
    [[ "$AF_SUDO"       == "false" ]] && ARGS+=(--no-sudo)
    [[ "$AF_DNS_UPDATE" == "false" ]] && ARGS+=(--no-dns-update)
    [[ "$AF_FIDO2"      == "true"  ]] && ARGS+=(--fido2)
    for U in "${AF_FIDO2_USERS[@]}"; do
        [[ -n "$U" ]] && ARGS+=(--fido2-user "$U")
    done

    exec "$ENROLL" "${ARGS[@]}" "${PASSTHROUGH[@]}"
fi

# ─── Interactive mode ─────────────────────────────────────────────────────────
if [[ "$MODE" == "interactive" ]]; then
    p() { printf '\033[0;35m[?]\033[0m %s ' "$*"; }

    p "IPA Domain [$IPA_DOMAIN]:"; read -r I; IPA_DOMAIN="${I:-$IPA_DOMAIN}"
    IPA_REALM="${IPA_DOMAIN^^}"
    p "Kerberos Realm [$IPA_REALM]:"; read -r I; IPA_REALM="${I:-$IPA_REALM}"
    p "IPA Server [$IPA_SERVER]:"; read -r I; IPA_SERVER="${I:-$IPA_SERVER}"

    CURRENT_HOST=$(hostname -f 2>/dev/null || hostname)
    p "This host's FQDN [$CURRENT_HOST]:"; read -r I; CLIENT_HOSTNAME="${I:-$CURRENT_HOST}"

    p "Admin principal [admin]:"; read -r PRINCIPAL; PRINCIPAL="${PRINCIPAL:-admin}"
    p "Admin password (no echo):"; read -rs PASSWORD; echo
    [[ -z "$PASSWORD" ]] && { echo "Error: password is required" >&2; exit 1; }

    p "Enable home directory creation? [Y/n]:"; read -r I
    MKHOMEDIR=true; [[ "${I,,}" == "n"* ]] && MKHOMEDIR=false

    p "Configure sudo via SSSD? [Y/n]:"; read -r I
    SUDO=true; [[ "${I,,}" == "n"* ]] && SUDO=false

    p "Update DNS record? [Y/n]:"; read -r I
    DNS_UPDATE=true; [[ "${I,,}" == "n"* ]] && DNS_UPDATE=false

    p "NTP server (blank to skip):"; read -r NTP_SERVER

    p "Enable FIDO2 authentication? [y/N]:"; read -r I
    FIDO2=false; [[ "${I,,}" == "y"* ]] && FIDO2=true

    FIDO2_USER_LIST=()
    if [[ "$FIDO2" == true ]]; then
        p "FIDO2 users (comma-separated, blank to skip):"; read -r I
        if [[ -n "$I" ]]; then
            IFS=',' read -ra FIDO2_USER_LIST <<< "$I"
        fi
    fi

    ARGS=(
        --domain    "$IPA_DOMAIN"
        --realm     "$IPA_REALM"
        --server    "$IPA_SERVER"
        --hostname  "$CLIENT_HOSTNAME"
        --principal "$PRINCIPAL"
        --password  "$PASSWORD"
    )
    [[ "$MKHOMEDIR"  == false ]] && ARGS+=(--no-mkhomedir)
    [[ "$SUDO"       == false ]] && ARGS+=(--no-sudo)
    [[ "$DNS_UPDATE" == false ]] && ARGS+=(--no-dns-update)
    [[ "$FIDO2"      == true  ]] && ARGS+=(--fido2)
    [[ -n "$NTP_SERVER"       ]] && ARGS+=(--ntp-server "$NTP_SERVER")
    for U in "${FIDO2_USER_LIST[@]}"; do
        [[ -n "${U// /}" ]] && ARGS+=(--fido2-user "${U// /}")
    done

    exec "$ENROLL" "${ARGS[@]}" "${PASSTHROUGH[@]}"
fi

# ─── Direct passthrough ───────────────────────────────────────────────────────
# No --answerfile or --interactive: forward all args directly to freeipa-enroll.sh
exec "$ENROLL" "${PASSTHROUGH[@]}"
