#!/usr/bin/env bash
set -euo pipefail
export GIT_TERMINAL_PROMPT=0


REPO_URL="${FUGU_REPO_URL:-https://github.com/SakanaAI/fugu.git}"
REPO_DIR="${FUGU_HOME:-${HOME}/.fugu}"
BRANCH="${FUGU_BRANCH:-main}"

have_tty() { [ -e /dev/tty ] && { : < /dev/tty; } 2>/dev/null; }

norm_target() {
  case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')" in
    1|codex)  printf 'codex'  ;;
    2|claude) printf 'claude' ;;
    3|both)   printf 'both'   ;;
    *) return 1 ;;
  esac
}

SELECT=""
ARGS=()
while [ "$#" -gt 0 ]; do
  case "$1" in
    --codex)  SELECT=codex  ;;
    --claude) SELECT=claude ;;
    --both)   SELECT=both   ;;
    *) ARGS+=("$1") ;;
  esac
  shift
done
set -- ${ARGS[@]+"${ARGS[@]}"}

if [ ! -d "$REPO_DIR" ]; then
  git clone "$REPO_URL" "$REPO_DIR"
fi

INSTALL="$REPO_DIR/scripts/install.sh"
INSTALL_CLAUDE="$REPO_DIR/scripts/install-claude.sh"

TARGET=""
if [ -n "$SELECT" ]; then
  TARGET="$SELECT"
elif [ -n "${FUGU_INSTALL_TARGET:-}" ]; then
  TARGET="$(norm_target "$FUGU_INSTALL_TARGET")" \
    || { printf 'bootstrap: invalid FUGU_INSTALL_TARGET=%s (use codex|claude|both)\n' "$FUGU_INSTALL_TARGET" >&2; exit 2; }
fi

reply=""
read_menu() { if have_tty; then IFS= read -r reply < /dev/tty; else IFS= read -r reply; fi; }

if [ -z "$TARGET" ]; then
  if have_tty || [ -t 0 ]; then
    while :; do
      printf '\nInstall Fugu for:\n  1) Codex        (codex-fugu)\n  2) Claude Code  (claude-fugu)\n  3) Both\nSelect [1-3]: ' >&2
      if ! read_menu; then printf '\nbootstrap: no selection received; aborting.\n' >&2; exit 1; fi
      if TARGET="$(norm_target "$reply")"; then break; fi
      printf 'Please enter 1, 2, or 3.\n' >&2
    done
  else
    printf 'bootstrap: no terminal for the menu and FUGU_INSTALL_TARGET is unset; defaulting to Codex.\n' >&2
    TARGET=codex
  fi
fi

refresh_repo() {
  [ -e "$REPO_DIR/.git" ] || return 1
  git -C "$REPO_DIR" rev-parse --git-dir >/dev/null 2>&1 || return 1
  if [ -n "$(git -C "$REPO_DIR" status --porcelain 2>/dev/null)" ]; then
    printf 'bootstrap: local changes in %s will be discarded by the update.\n' "$REPO_DIR" >&2
  fi
  git -C "$REPO_DIR" fetch --quiet origin "$BRANCH" 2>/dev/null || return 1
  git -C "$REPO_DIR" reset --hard "origin/$BRANCH" >/dev/null 2>&1 || return 1
  return 0
}

require() {
  if [ -f "$1" ]; then return 0; fi
  if refresh_repo; then
    if [ -f "$1" ]; then
      printf 'bootstrap: updated the local clone %s to origin/%s.\n' "$REPO_DIR" "$BRANCH" >&2
      return 0
    fi
    printf 'bootstrap: %s not found in %s even after updating to origin/%s.\n' "$1" "$REPO_DIR" "$BRANCH" >&2
    printf 'This install target may not be published to %s (branch %s) yet.\n' "$REPO_URL" "$BRANCH" >&2
  else
    printf 'bootstrap: %s not found in %s and the clone could not be updated (offline, diverged, or not a git checkout).\n' "$1" "$REPO_DIR" >&2
    printf 'If you are online, remove the stale clone and re-run the installer: rm -rf %s\n' "$REPO_DIR" >&2
  fi
  exit 1
}

run_installer() {
  local mode="$1" script="$2"; shift 2
  if [ "$mode" = exec ]; then
    if have_tty; then exec bash "$script" "$@" < /dev/tty; else exec bash "$script" "$@"; fi
  else
    if have_tty; then bash "$script" "$@" < /dev/tty; else bash "$script" "$@"; fi
  fi
}

case "$TARGET" in
  codex)
    require "$INSTALL"
    run_installer exec "$INSTALL" "$@"
    ;;
  claude)
    require "$INSTALL_CLAUDE"
    run_installer exec "$INSTALL_CLAUDE" "$@"
    ;;
  both)
    require "$INSTALL"; require "$INSTALL_CLAUDE"
    if ! have_tty && ! [ -t 0 ] && [ -z "${SAKANA_API_KEY:-}" ]; then
      for a in "$@"; do
        [ "$a" = --dry-run ] && { printf 'bootstrap: "both --dry-run" with no terminal needs SAKANA_API_KEY exported.\n' >&2; exit 2; }
      done
    fi
    run_installer run "$INSTALL" "$@"
    CLAUDE_ARGS=()
    for a in "$@"; do case "$a" in -y|--yes|--dry-run) CLAUDE_ARGS+=("$a") ;; esac; done
    run_installer exec "$INSTALL_CLAUDE" ${CLAUDE_ARGS[@]+"${CLAUDE_ARGS[@]}"}
    ;;
esac
