#!/bin/sh
set -eu

VERSION="0.2.1"
BASE_URL="${FUNDURPROMPT_BASE_URL:-https://fundurprompt.io}"
INSTALL_HOME="${FUNDURPROMPT_HOME:-$HOME/.fundurprompt}"
BIN_DIR="$INSTALL_HOME/bin"
CONFIG_FILE="$INSTALL_HOME/config.json"
AUTH_FILE="$INSTALL_HOME/auth.json"
MANIFEST_FILE="$INSTALL_HOME/manifest.json"
CODEX_FILE="$BIN_DIR/codex"
FUNDURPROMPT_FILE="$BIN_DIR/fundurprompt"
DRY_RUN=0
UPDATE_SHELL=1

usage() {
  cat <<EOF
FundUrPrompt Codex installer

Usage: sh install.sh [--dry-run] [--base-url URL] [--no-shell]

  --dry-run      Print the install plan without writing files.
  --base-url URL Download assets from URL.
  --no-shell     Do not add the managed PATH block.
EOF
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --dry-run) DRY_RUN=1 ;;
    --base-url) shift; BASE_URL="${1:?--base-url requires a URL}" ;;
    --no-shell) UPDATE_SHELL=0 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown option: $1" >&2; usage >&2; exit 2 ;;
  esac
  shift
done

MANIFEST_URL="$BASE_URL/downloads/fundurprompt-cli-manifest.json"

download() {
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL "$1" -o "$2"
  elif command -v wget >/dev/null 2>&1; then
    wget -qO "$2" "$1"
  else
    echo "Install requires curl or wget." >&2
    exit 1
  fi
}

sha256_file() {
  if command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$1" | awk '{print $1}'
  elif command -v sha256sum >/dev/null 2>&1; then
    sha256sum "$1" | awk '{print $1}'
  else
    echo "Install requires shasum or sha256sum." >&2
    exit 1
  fi
}

resolve_real_codex() {
  python3 - "$BIN_DIR" <<'PY'
import os
import re
import sys

own_bin = os.path.realpath(sys.argv[1])
candidates = []
for directory in os.environ.get("PATH", "").split(os.pathsep):
    if directory and os.path.realpath(directory) != own_bin:
        candidates.append(os.path.join(directory, "codex"))
candidates += [
    os.path.expanduser("~/.local/node_modules/.bin/codex"),
    "/Applications/ChatGPT.app/Contents/Resources/codex",
    "/opt/homebrew/bin/codex",
    "/usr/local/bin/codex",
]
seen = set()
while candidates:
    candidate = candidates.pop(0)
    if not os.path.isfile(candidate) or not os.access(candidate, os.X_OK):
        continue
    resolved = os.path.realpath(candidate)
    if resolved in seen or os.path.dirname(resolved) == own_bin:
        continue
    seen.add(resolved)
    try:
        with open(candidate, "rb") as handle:
            prefix = handle.read(8192)
    except OSError:
        prefix = b""
    if b"VIBE-ADS-CODEX-CLI" in prefix or b"fundurprompt codex shim" in prefix.lower():
        match = re.search(rb"(?m)^\s*exec\s+[\"']?([^\"'\s]+)[\"']?", prefix)
        if match:
            target = os.path.expanduser(match.group(1).decode("utf-8", "ignore"))
            if os.path.isabs(target):
                candidates.insert(0, target)
        continue
    print(candidate)
    break
PY
}

shell_rc_files() {
  case "${SHELL:-}" in
    */zsh) printf '%s\n' "$HOME/.zshrc" ;;
    */bash) printf '%s\n%s\n' "$HOME/.bashrc" "$HOME/.bash_profile" ;;
    */fish) return 1 ;;
    */sh|*/dash|*/ksh) printf '%s\n' "$HOME/.profile" ;;
    *) return 1 ;;
  esac
}

install_shell_path() {
  start="# >>> fundurprompt codex shim >>>"
  end="# <<< fundurprompt codex shim <<<"
  if [ "$UPDATE_SHELL" -eq 0 ]; then
    echo "Skipping shell rc update. Add $BIN_DIR to PATH manually."
    return
  fi
  rc_files="$(shell_rc_files || true)"
  if [ -z "$rc_files" ]; then
    echo "Unsupported shell ${SHELL:-unknown}; add $BIN_DIR to PATH manually."
    return
  fi
  printf '%s\n' "$rc_files" | while IFS= read -r rc_file; do
    if [ "$DRY_RUN" -eq 1 ]; then
      echo "dry-run: append managed PATH block to $rc_file"
      continue
    fi
    mkdir -p "$(dirname "$rc_file")"
    touch "$rc_file"
    if ! grep -F "$start" "$rc_file" >/dev/null 2>&1; then
      printf '\n%s\nexport PATH="%s:$PATH"\n%s\n' "$start" "$BIN_DIR" "$end" >> "$rc_file"
    fi
  done
}

if [ "$DRY_RUN" -eq 1 ]; then
  echo "dry-run: download $MANIFEST_URL"
  echo "dry-run: verify and install $BASE_URL/downloads/fundurprompt-cli.pyz"
  echo "dry-run: create stable install identity at $AUTH_FILE"
  install_shell_path
  echo "dry-run: interactive terminals run $FUNDURPROMPT_FILE login"
  exit 0
fi

command -v python3 >/dev/null 2>&1 || { echo "Install requires Python 3." >&2; exit 1; }
real_codex="$(resolve_real_codex || true)"
if [ -z "$real_codex" ]; then
  echo "Warning: could not find a real Codex binary. Set FUNDURPROMPT_REAL_CODEX before running codex."
else
  echo "Real Codex: $real_codex"
fi

mkdir -p "$BIN_DIR"
chmod 700 "$INSTALL_HOME" "$BIN_DIR"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT INT HUP TERM
download "$MANIFEST_URL" "$tmp_dir/manifest.json"

artifact_info="$(python3 - "$tmp_dir/manifest.json" <<'PY'
import json
import sys
with open(sys.argv[1], encoding="utf-8") as handle:
    manifest = json.load(handle)
artifact = manifest.get("artifact") or {}
print(artifact.get("url") or artifact.get("path") or "/downloads/fundurprompt-cli.pyz")
print(artifact.get("path") or "/downloads/fundurprompt-cli.pyz")
print(artifact.get("sha256") or "")
PY
)"
artifact_url="$(printf '%s\n' "$artifact_info" | sed -n '1p')"
artifact_path="$(printf '%s\n' "$artifact_info" | sed -n '2p')"
expected_sha="$(printf '%s\n' "$artifact_info" | sed -n '3p')"
case "$artifact_url" in
  http://*|https://*|file://*) ;;
  *) artifact_url="$BASE_URL$artifact_path" ;;
esac
if [ "$BASE_URL" != "https://fundurprompt.io" ]; then
  artifact_url="$BASE_URL$artifact_path"
fi
[ -n "$expected_sha" ] || { echo "Manifest is missing artifact sha256." >&2; exit 1; }
download "$artifact_url" "$tmp_dir/fundurprompt-cli.pyz"
actual_sha="$(sha256_file "$tmp_dir/fundurprompt-cli.pyz")"
if [ "$actual_sha" != "$expected_sha" ]; then
  echo "Downloaded CLI failed sha256 verification." >&2
  echo "Expected: $expected_sha" >&2
  echo "Actual:   $actual_sha" >&2
  exit 1
fi
chmod 755 "$tmp_dir/fundurprompt-cli.pyz"
mv "$tmp_dir/fundurprompt-cli.pyz" "$CODEX_FILE"
cp "$CODEX_FILE" "$FUNDURPROMPT_FILE"
chmod 755 "$CODEX_FILE" "$FUNDURPROMPT_FILE"
cp "$tmp_dir/manifest.json" "$MANIFEST_FILE"
chmod 600 "$MANIFEST_FILE"

python3 - "$AUTH_FILE" "$CONFIG_FILE" "$BASE_URL" "$real_codex" "$VERSION" <<'PY'
import json
import os
import secrets
import sys
from datetime import datetime, timezone

auth_path, config_path, origin, real_codex, version = sys.argv[1:]
try:
    with open(auth_path, encoding="utf-8") as handle:
        auth = json.load(handle)
except Exception:
    auth = {}
auth.setdefault("installId", "ins_" + secrets.token_hex(12))
auth.setdefault("clientId", "cli_" + secrets.token_hex(12))
auth.setdefault("createdAt", datetime.now(timezone.utc).isoformat())
auth.setdefault("account", None)
config = {
    "version": version,
    "apiBaseUrl": origin,
    "adEndpoint": origin + "/api/cli-placement",
    "impressionEndpoint": origin + "/api/cli-impressions",
    "deviceLoginStartEndpoint": origin + "/api/device-login/start",
    "deviceLoginPollEndpoint": origin + "/api/device-login/poll",
    "cliLogoutEndpoint": origin + "/api/cli-logout",
    "manifestUrl": origin + "/downloads/fundurprompt-cli-manifest.json",
    "realCodexPath": real_codex,
    "placementSurface": "codex_cli_pty_overlay",
    "networkTimeoutSeconds": 1.25,
}
for path, value in ((auth_path, auth), (config_path, config)):
    os.makedirs(os.path.dirname(path), mode=0o700, exist_ok=True)
    temporary = f"{path}.tmp.{os.getpid()}"
    with open(temporary, "w", encoding="utf-8") as handle:
        json.dump(value, handle, indent=2, sort_keys=True)
        handle.write("\n")
    os.chmod(temporary, 0o600)
    os.replace(temporary, path)
PY

install_shell_path
cat <<EOF

FundUrPrompt Codex shim installed.
Open a new terminal or run: export PATH="$BIN_DIR:\$PATH"
Status: $FUNDURPROMPT_FILE status
Uninstall: remove the managed PATH block, then rm -rf "$INSTALL_HOME"
EOF

if [ -t 1 ] && [ -r /dev/tty ] && [ -w /dev/tty ]; then
  "$FUNDURPROMPT_FILE" login </dev/tty || echo "Login was not completed. Retry with: $FUNDURPROMPT_FILE login"
else
  echo "To approve this install and enable earning, run: $FUNDURPROMPT_FILE login"
fi
