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

VERSION="0.5.0-beta.7"
BASE_URL="${COMPACT_CONTEXT_BASE_URL:-https://compact-context.met.chatgpt.site}"
ARCHIVE="compact-context-v${VERSION}.zip"
INSTALL_ROOT="${HOME}/.codex/marketplaces"
INSTALL_DIR="${INSTALL_ROOT}/compact-context-v${VERSION}"
MARKETPLACE_NAME="compact-context"
PLUGIN_ID="compact-codebase@compact-context"
HOOK_LAUNCHER="open-codex-hooks.py"
HOOK_LAUNCHER_SHA256="f4ddda4c5a6c6d658dd0b470b73955f58184606348960419725a01ba19cbd9dd"
TEMP_DIR="$(mktemp -d)"

cleanup() {
  rm -rf "${TEMP_DIR}"
}
trap cleanup EXIT

command -v curl >/dev/null || { echo "Compact Context needs curl." >&2; exit 1; }
command -v unzip >/dev/null || { echo "Compact Context needs unzip." >&2; exit 1; }
command -v shasum >/dev/null || { echo "Compact Context needs shasum." >&2; exit 1; }
command -v python3 >/dev/null || { echo "Compact Context needs Python 3." >&2; exit 1; }
command -v codex >/dev/null || { echo "Codex CLI was not found in PATH." >&2; exit 1; }
codex plugin add --help >/dev/null 2>&1 || {
  echo "This installer needs a Codex CLI version with 'codex plugin add'. Update Codex Desktop and try again." >&2
  exit 1
}

echo "Downloading Compact Context v${VERSION}..."
curl -fsSL "${BASE_URL}/${ARCHIVE}" -o "${TEMP_DIR}/${ARCHIVE}"
curl -fsSL "${BASE_URL}/${ARCHIVE}.sha256" -o "${TEMP_DIR}/${ARCHIVE}.sha256"
(
  cd "${TEMP_DIR}"
  shasum -a 256 -c "${ARCHIVE}.sha256" >/dev/null
  unzip -q "${ARCHIVE}"
)

test -f "${TEMP_DIR}/compact-context/.agents/plugins/marketplace.json" || {
  echo "The downloaded marketplace is incomplete." >&2
  exit 1
}

mkdir -p "${INSTALL_ROOT}"
if [[ ! -e "${INSTALL_DIR}" ]]; then
  mv "${TEMP_DIR}/compact-context" "${INSTALL_DIR}"
elif [[ ! -f "${INSTALL_DIR}/.agents/plugins/marketplace.json" ]]; then
  echo "${INSTALL_DIR} already exists but is incomplete. Move it aside and run this installer again." >&2
  exit 1
fi

MARKETPLACES="$(codex plugin marketplace list --json 2>/dev/null || true)"
MARKETPLACES_COMPACT="$(printf '%s' "${MARKETPLACES}" | tr -d '[:space:]')"
if [[ "${MARKETPLACES_COMPACT}" == *'"name":"compact-context"'* || "${MARKETPLACES_COMPACT}" == *'"marketplaceName":"compact-context"'* ]]; then
  if [[ "${MARKETPLACES_COMPACT}" != *"${INSTALL_DIR}"* ]]; then
    echo "Replacing an earlier Compact Context marketplace source..."
    codex plugin marketplace remove "${MARKETPLACE_NAME}" >/dev/null
    codex plugin marketplace add "${INSTALL_DIR}" >/dev/null
  fi
else
  codex plugin marketplace add "${INSTALL_DIR}" >/dev/null
fi

echo "Installing the Compact Context plugin..."
PLUGINS="$(codex plugin list --json 2>/dev/null || true)"
PLUGINS_COMPACT="$(printf '%s' "${PLUGINS}" | tr -d '[:space:]')"
if [[ ( "${PLUGINS_COMPACT}" == *'"pluginId":"compact-codebase"'* || "${PLUGINS_COMPACT}" == *'"pluginId":"compact-codebase@compact-context"'* ) && "${PLUGINS_COMPACT}" == *'"marketplaceName":"compact-context"'* ]]; then
  echo "Compact Context is already installed; continuing to hook approval."
else
  codex plugin add "${PLUGIN_ID}" >/dev/null
fi

echo
echo "Compact Context v${VERSION} is installed."
echo "Opening Codex hook approval..."
echo "Approve the Compact Context UserPromptSubmit and Stop hooks, then quit Codex CLI."
echo

if exec 2>/dev/null 3<>/dev/tty; then
  if curl -fsSL "${BASE_URL}/${HOOK_LAUNCHER}?v=4" -o "${TEMP_DIR}/${HOOK_LAUNCHER}"; then
    ACTUAL_HOOK_LAUNCHER_SHA256="$(shasum -a 256 "${TEMP_DIR}/${HOOK_LAUNCHER}" | awk '{print $1}')"
    if [[ "${ACTUAL_HOOK_LAUNCHER_SHA256}" == "${HOOK_LAUNCHER_SHA256}" ]]; then
      python3 "${TEMP_DIR}/${HOOK_LAUNCHER}" "$(command -v codex)" <&3 >&3 2>&3
    else
      echo "Hook launcher verification failed. Type /hooks after Codex opens."
      codex <&3 >&3 2>&3
    fi
  else
    echo "Automatic /hooks opening is unavailable. Type /hooks after Codex opens."
    codex <&3 >&3 2>&3
  fi
  exec 3>&-
else
  echo "No interactive terminal was detected. Run 'codex', then type '/hooks' to approve the two hooks."
fi

echo
echo "Setup is complete. Fully quit and reopen Codex Desktop, then start a new chat."
