#!/bin/bash
#
# Eldric AI OS — dnf repo setup
#
# One-liner customer entry point:
#   curl -fsSL https://repo.eldric.ai/install.sh | sudo bash
#
# After this runs, dnf knows where to find Eldric packages:
#   sudo dnf install eldric-aios
#
# The bootstrap that runs install + first-boot config is a separate script:
#   curl -fsSL https://repo.eldric.ai/install-eldric.sh | sudo bash
#
# This script is intentionally narrow: it ONLY adds the dnf repo and the
# signing key. No package installation, no service enablement, no admin
# config. Safe to re-run; second invocation is a no-op.
#
# Supported: Fedora 42+, RHEL 9+, CentOS Stream 9+ on x86_64.
#
# Exit codes:
#   0  repo added (or already present)
#   2  unsupported distro / arch / not root
#   3  network failure
#   4  GPG fingerprint mismatch
#   5  dnf failure

set -euo pipefail

# ─── pinned key fingerprint ──────────────────────────────────────────────
# The public half of the repo signing key. Pinned here so a hostile
# intermediary serving a swapped key fails closed instead of writing a
# bogus pubkey to /etc/pki/rpm-gpg/. Verified against the actual key
# published at https://repo.eldric.ai/signing/RPM-GPG-KEY-eldric on
# 2026-05-15 (RSA 4096, "Eldric Repository Signing <repo@eldric.ai>").
readonly PINNED_FINGERPRINT="23B52B031529BC97A4C3C3D8D8EAD08DBC9B0671"

readonly REPO_BASE="https://repo.eldric.ai/5.0/"
readonly GPG_KEY_URL="https://repo.eldric.ai/signing/RPM-GPG-KEY-eldric"
readonly REPO_FILE="/etc/yum.repos.d/eldric.repo"
readonly KEY_FILE="/etc/pki/rpm-gpg/RPM-GPG-KEY-eldric"

# ─── colorless logging (this runs in pipes / sudo / non-tty often) ──────
info() { printf '==> %s\n' "$*"; }
warn() { printf '==> WARN: %s\n' "$*" >&2; }
die()  { printf '==> ERROR: %s\n' "$*" >&2; exit "${EXIT_CODE:-1}"; }

# ─── root check ──────────────────────────────────────────────────────────
if [[ "$(id -u)" -ne 0 ]]; then
    EXIT_CODE=2 die "must run as root. Try: curl -fsSL https://repo.eldric.ai/install.sh | sudo bash"
fi

# ─── distro + version check ──────────────────────────────────────────────
if [[ ! -r /etc/os-release ]]; then
    EXIT_CODE=2 die "/etc/os-release not readable; cannot detect distro"
fi
# shellcheck disable=SC1091
. /etc/os-release

DISTRO_ID="${ID:-unknown}"
DISTRO_VER="${VERSION_ID:-0}"
DISTRO_LIKE="${ID_LIKE:-}"

# Major version (strip .N off "42" / "9.4" etc.)
DISTRO_MAJOR="${DISTRO_VER%%.*}"

case "$DISTRO_ID" in
    fedora)
        if (( DISTRO_MAJOR < 42 )); then
            EXIT_CODE=2 die "Fedora ${DISTRO_VER} is too old; need 42+"
        fi
        ;;
    rhel|centos)
        if (( DISTRO_MAJOR < 9 )); then
            EXIT_CODE=2 die "${PRETTY_NAME:-$DISTRO_ID $DISTRO_VER} is too old; need RHEL/CentOS 9+"
        fi
        ;;
    *)
        # Some derivatives (Rocky, Alma) identify as themselves but list
        # rhel in ID_LIKE. Accept if the family matches and the major is OK.
        if [[ "$DISTRO_LIKE" == *rhel* ]] && (( DISTRO_MAJOR >= 9 )); then
            info "treating ${PRETTY_NAME:-$DISTRO_ID} as RHEL-family ${DISTRO_MAJOR}"
        else
            EXIT_CODE=2 die "unsupported distro: ${PRETTY_NAME:-$DISTRO_ID $DISTRO_VER}"
        fi
        ;;
esac

# ─── arch check ──────────────────────────────────────────────────────────
ARCH="$(uname -m)"
if [[ "$ARCH" != "x86_64" ]]; then
    EXIT_CODE=2 die "unsupported architecture: ${ARCH}. Eldric ships x86_64 only today."
fi

# ─── dnf check ───────────────────────────────────────────────────────────
if ! command -v dnf >/dev/null 2>&1; then
    EXIT_CODE=2 die "dnf not found; required for repo setup"
fi

info "distro: ${PRETTY_NAME:-$DISTRO_ID $DISTRO_VER} (${ARCH})"

# ─── GPG key fetch + fingerprint verify ──────────────────────────────────
if [[ -r "$KEY_FILE" ]]; then
    # Idempotency: if file is already there AND its fingerprint matches,
    # skip the re-download. If it doesn't match, refuse — something is off
    # and the operator should manually investigate.
    EXISTING_FP="$(gpg --show-keys --with-colons "$KEY_FILE" 2>/dev/null | awk -F: '/^fpr/ {print $10; exit}')"
    if [[ "$EXISTING_FP" == "$PINNED_FINGERPRINT" ]]; then
        info "GPG key already present at $KEY_FILE (fingerprint match)"
    else
        EXIT_CODE=4 die "existing $KEY_FILE has fingerprint $EXISTING_FP; expected $PINNED_FINGERPRINT — refusing to overwrite. Remove the file by hand if you trust the new key."
    fi
else
    info "fetching GPG key from $GPG_KEY_URL"
    TMP_KEY="$(mktemp -t eldric-gpg-XXXXXX)"
    trap 'rm -f "$TMP_KEY"' EXIT

    if ! curl -fsSL --max-time 30 "$GPG_KEY_URL" -o "$TMP_KEY"; then
        EXIT_CODE=3 die "failed to fetch GPG key from $GPG_KEY_URL"
    fi

    FETCHED_FP="$(gpg --show-keys --with-colons "$TMP_KEY" 2>/dev/null | awk -F: '/^fpr/ {print $10; exit}')"
    if [[ "$FETCHED_FP" != "$PINNED_FINGERPRINT" ]]; then
        EXIT_CODE=4 die "GPG fingerprint mismatch: fetched=$FETCHED_FP pinned=$PINNED_FINGERPRINT"
    fi

    install -o root -g root -m 0644 "$TMP_KEY" "$KEY_FILE"
    info "GPG key installed at $KEY_FILE (fingerprint $PINNED_FINGERPRINT)"
fi

# ─── write /etc/yum.repos.d/eldric.repo ──────────────────────────────────
NEW_REPO_CONTENTS="$(cat <<EOF
# Eldric AI OS — 5.0 stream
# Generated by https://repo.eldric.ai/install.sh
# Re-run that script to refresh.
[eldric-5.0]
name=Eldric AI OS 5.0
baseurl=${REPO_BASE}
enabled=1
gpgcheck=1
gpgkey=file://${KEY_FILE}
repo_gpgcheck=0
metadata_expire=300
EOF
)"

if [[ -r "$REPO_FILE" ]]; then
    if [[ "$(cat "$REPO_FILE")" == "$NEW_REPO_CONTENTS" ]]; then
        info "$REPO_FILE already up to date"
    else
        info "$REPO_FILE differs from generator output; replacing (backup at ${REPO_FILE}.bak)"
        cp -a "$REPO_FILE" "${REPO_FILE}.bak"
        printf '%s\n' "$NEW_REPO_CONTENTS" > "$REPO_FILE"
        chmod 0644 "$REPO_FILE"
    fi
else
    info "writing $REPO_FILE"
    printf '%s\n' "$NEW_REPO_CONTENTS" > "$REPO_FILE"
    chmod 0644 "$REPO_FILE"
fi

# ─── refresh dnf cache + smoke test ──────────────────────────────────────
info "refreshing dnf metadata for eldric-5.0"
if ! dnf -q --disablerepo='*' --enablerepo=eldric-5.0 clean expire-cache >/dev/null 2>&1; then
    EXIT_CODE=5 die "dnf clean expire-cache failed for eldric-5.0 repo"
fi

if ! dnf -q --disablerepo='*' --enablerepo=eldric-5.0 makecache >/dev/null 2>&1; then
    EXIT_CODE=5 die "dnf makecache failed; verify network reaches $REPO_BASE"
fi

info "smoke-checking eldric-aios package visibility"
if ! dnf -q --disablerepo='*' --enablerepo=eldric-5.0 list available 'eldric-aios' >/dev/null 2>&1; then
    EXIT_CODE=5 die "dnf reports eldric-aios not available; repo is wired but package listing failed"
fi

# ─── done ────────────────────────────────────────────────────────────────
echo
info "Eldric repo added."
echo
echo "Next steps:"
echo "  Install just the package:"
echo "      sudo dnf install eldric-aios"
echo
echo "  Or full bootstrap (recommended for first-time install):"
echo "      curl -fsSL https://repo.eldric.ai/install-eldric.sh | sudo bash"
echo
