# Installing OpenAI's ChatGPT Desktop without trusting the download. Sourced,
# not run.
#
# OpenAI signs both its packages and its repository metadata, with one key, and
# publishes neither that key nor its fingerprint anywhere a first install could
# fetch them. The documented instructions are "download this RPM and install
# it" -- and the RPM's own root scriptlet is what writes the repository file and
# drops the key into /etc/pki/rpm-gpg. Following them means handing an
# unverified download to root and letting it decide afterwards what to trust,
# which is the one thing this repository will not do with a network response.
#
# So the key is pinned here instead. setup/keys/ carries a copy and records
# where it came from; this verifies that copy's fingerprint, installs it, and
# writes the repository itself with gpgcheck on. dnf then checks the metadata
# signature and the package signature against that key before anything runs as
# root, and every later upgrade goes through the same repository and the same
# key.
#
# Two callers, which is why this is a library: install-packages, for a machine
# being built, and the migration that replaces the community codex-desktop
# build on machines that predate the official package.

# The key that signs the packages and the repository metadata. Pinned, so a
# substituted key is a failure here rather than a silent change of publisher.
CHATGPT_KEY_FINGERPRINT="3BFA0E4AE8B8CC16A2D9BA684A3B4A566C4660E4"

# `$basearch` stays literal: dnf expands it, and this is the same base URL the
# package's own scriptlet configures.
CHATGPT_REPO_BASEURL="https://persistent.oaistatic.com/codex-app-prod/linux/rpm/\$basearch"
CHATGPT_REPO_FILE="/etc/yum.repos.d/chatgpt.repo"
CHATGPT_KEY_FILE="/etc/pki/rpm-gpg/RPM-GPG-KEY-chatgpt"

chatgpt_pinned_key() {
    printf '%s/setup/keys/RPM-GPG-KEY-chatgpt' "${PANAMA_PATH:-$HOME/.local/share/Panama}"
}

# The fingerprint of the pinned copy. Nonzero when it cannot be read at all,
# which the caller reports differently from a key that reads but is the wrong
# one.
chatgpt_pinned_fingerprint() {
    local key
    key="$(chatgpt_pinned_key)"
    [[ -r "$key" ]] || return 1
    gpg --show-keys --with-colons "$key" 2>/dev/null \
        | awk -F: '$1 == "fpr" { print $10; exit }'
}

# Fails without touching anything when the pinned key is missing, unreadable,
# or not the key this repository says it is. Everything below assumes it passed.
chatgpt_verify_pinned_key() {
    local found
    if ! command -v gpg >/dev/null 2>&1; then
        printf 'gpg is missing, so the pinned ChatGPT signing key cannot be verified.\n' >&2
        return 1
    fi
    if ! found="$(chatgpt_pinned_fingerprint)"; then
        printf 'The pinned ChatGPT signing key is missing: %s\n' "$(chatgpt_pinned_key)" >&2
        return 1
    fi
    if [[ "$found" != "$CHATGPT_KEY_FINGERPRINT" ]]; then
        printf 'The pinned ChatGPT signing key is %s, not the expected %s.\n' \
            "${found:-unreadable}" "$CHATGPT_KEY_FINGERPRINT" >&2
        return 1
    fi
}

# Installs the verified key and the repository that names it, so the install
# after this one is a signature check rather than an act of faith.
#
# Takes the command that gets root, because the two callers ask for it
# differently: plain `sudo` from the installer, which authenticated once at the
# top of the run, and `panama-sudo --reason ...` from a migration, whose prompt
# has to say which repair it is for.
chatgpt_install_repository() {
    local -a sudo_cmd=("$@")
    (( ${#sudo_cmd[@]} > 0 )) || sudo_cmd=(sudo)

    chatgpt_verify_pinned_key || return 1

    "${sudo_cmd[@]}" install -D -m 0644 "$(chatgpt_pinned_key)" "$CHATGPT_KEY_FILE" || return 1
    "${sudo_cmd[@]}" rpmkeys --import "$CHATGPT_KEY_FILE" || return 1

    # Written here rather than left to the package's scriptlet, because the
    # point of it is to exist -- with gpgcheck on and this key named -- before
    # the first install rather than after it. Same base URL and same key the
    # scriptlet writes, so it finds nothing to change later.
    printf '%s\n' \
        '[openai-chatgpt]' \
        'name=ChatGPT' \
        "baseurl=$CHATGPT_REPO_BASEURL" \
        'enabled=1' \
        'type=rpm-md' \
        'gpgcheck=1' \
        'repo_gpgcheck=1' \
        "gpgkey=file://$CHATGPT_KEY_FILE" \
        | "${sudo_cmd[@]}" tee "$CHATGPT_REPO_FILE" >/dev/null || return 1
}
