#!/usr/bin/env sh
set -eu

REPO="${WEBCLI_RELEASE_REPO:-DO-SAY-GO/web-cli}"
RELEASE_TAG="${WEBCLI_RELEASE_TAG:-}"
ARTIFACT_LOCATION="${WEBCLI_ARTIFACT:-}"
CHECKSUMS_LOCATION="${WEBCLI_CHECKSUMS:-}"
PAGES_DOWNLOAD_BASE="${WEBCLI_PAGES_DOWNLOAD_BASE:-https://web-cli-eht.pages.dev/downloads}"
STATE_DIR="${WEBCLI_STATE_DIR:-$HOME/.webcli}"
WRAPPER_PATH="$STATE_DIR/webcli-wrapper.sh"
RUNTIME_DIR="$STATE_DIR/runtime"
CHECK_FILE="$STATE_DIR/.last_update_check"
CADENCE="${WEBCLI_UPDATE_CADENCE:-3600}"

log() { printf '%s\n' "$*"; }
die() { printf '%s\n' "$*" >&2; exit 1; }
ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }

path_contains_dir() {
  case ":$PATH:" in *":$1:"*) return 0 ;; *) return 1 ;; esac
}

dir_is_usable_without_sudo() {
  dir="$1"
  probe="$dir"
  while [ ! -d "$probe" ]; do
    next_probe=$(dirname "$probe")
    [ "$next_probe" != "$probe" ] || break
    probe="$next_probe"
  done
  [ -d "$probe" ] && [ -w "$probe" ]
}

choose_command_dir() {
  if [ -n "$ARTIFACT_LOCATION" ]; then
    old_ifs=$IFS
    IFS=:
    for dir in $PATH; do
      IFS=$old_ifs
      [ -n "$dir" ] || continue
      if dir_is_usable_without_sudo "$dir"; then
        printf '%s\n' "$dir"
        return 0
      fi
      IFS=:
    done
    IFS=$old_ifs
  fi

  existing=$(command -v web 2>/dev/null || true)
  if [ -n "$existing" ]; then
    existing_dir=$(dirname "$existing")
    if path_contains_dir "$existing_dir" && dir_is_usable_without_sudo "$existing_dir"; then
      printf '%s\n' "$existing_dir"
      return 0
    fi
  fi

  for dir in /usr/local/bin /opt/homebrew/bin "$HOME/.local/bin" "$HOME/bin" "$STATE_DIR/bin"; do
    if path_contains_dir "$dir" && dir_is_usable_without_sudo "$dir"; then
      printf '%s\n' "$dir"
      return 0
    fi
  done

  printf '%s\n' "$STATE_DIR/bin"
}

write_runtime_wrapper() {
  ensure_dir "$STATE_DIR"
  ensure_dir "$RUNTIME_DIR"
  cat > "$WRAPPER_PATH" <<'EOF'
#!/usr/bin/env sh
set -eu

REPO="${WEBCLI_RELEASE_REPO:-DO-SAY-GO/web-cli}"
RELEASE_TAG="${WEBCLI_RELEASE_TAG:-}"
ARTIFACT_LOCATION="${WEBCLI_ARTIFACT:-}"
CHECKSUMS_LOCATION="${WEBCLI_CHECKSUMS:-}"
PAGES_DOWNLOAD_BASE="${WEBCLI_PAGES_DOWNLOAD_BASE:-https://web-cli-eht.pages.dev/downloads}"
STATE_DIR="${WEBCLI_STATE_DIR:-$HOME/.webcli}"
RUNTIME_DIR="$STATE_DIR/runtime"
CHECK_FILE="$STATE_DIR/.last_update_check"
CADENCE="${WEBCLI_UPDATE_CADENCE:-3600}"

die() { printf '%s\n' "$*" >&2; exit 1; }
log() { printf '%s\n' "$*"; }

resolve_asset() {
  case "$(uname -s)" in
    Darwin) os="macos"; ext="zip" ;;
    Linux) os="linux"; ext="tar.gz" ;;
    *) die "unsupported OS: $(uname -s)" ;;
  esac
  case "$(uname -m)" in
    x86_64|amd64) arch="x64" ;;
    arm64|aarch64)
      if [ "$os" = "linux" ]; then
        die "linux arm64 release artifacts are not published yet"
      fi
      arch="arm64"
      ;;
    *) die "unsupported architecture: $(uname -m)" ;;
  esac
  printf 'webcli-%s-%s.%s\n' "$os" "$arch" "$ext"
}

should_update() {
  [ -n "$ARTIFACT_LOCATION" ] && return 0
  [ -x "$RUNTIME_DIR/web" ] || return 0
  [ -f "$CHECK_FILE" ] || return 0
  last_check=$(cat "$CHECK_FILE" 2>/dev/null || printf '0')
  case "$last_check" in ''|*[!0-9]*) return 0 ;; esac
  now=$(date +%s)
  [ $((now - last_check)) -ge "$CADENCE" ]
}

fetch_location() {
  location="$1"
  dest="$2"
  case "$location" in
    http://*|https://*) curl -fsSL "$location" -o "$dest" ;;
    *) cp "$location" "$dest" ;;
  esac
}

fetch_with_fallback() {
  primary="$1"
  fallback="$2"
  dest="$3"
  if fetch_location "$primary" "$dest"; then return 0; fi
  [ -n "$fallback" ] || return 1
  fetch_location "$fallback" "$dest"
}

sha256_hex() {
  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
    die "Need shasum or sha256sum to verify downloads"
  fi
}

download_and_install() {
  asset=$(resolve_asset)
  release_path="latest/download"
  if [ -n "$RELEASE_TAG" ]; then release_path="download/${RELEASE_TAG}"; fi

  if [ -n "$ARTIFACT_LOCATION" ]; then
    artifact_primary="$ARTIFACT_LOCATION"; artifact_fallback=""
  elif [ -z "$RELEASE_TAG" ]; then
    artifact_primary="$PAGES_DOWNLOAD_BASE/$asset"
    artifact_fallback="https://github.com/$REPO/releases/latest/download/$asset"
  else
    artifact_primary="https://github.com/$REPO/releases/$release_path/$asset"
    artifact_fallback=""
  fi

  if [ -n "$CHECKSUMS_LOCATION" ]; then
    checksums_primary="$CHECKSUMS_LOCATION"; checksums_fallback=""
  elif [ -z "$RELEASE_TAG" ]; then
    checksums_primary="$PAGES_DOWNLOAD_BASE/SHA256SUMS.txt"
    checksums_fallback="https://github.com/$REPO/releases/latest/download/SHA256SUMS.txt"
  else
    checksums_primary="https://github.com/$REPO/releases/$release_path/SHA256SUMS.txt"
    checksums_fallback=""
  fi

  tmp=$(mktemp -d)
  trap 'rm -rf "$tmp"' EXIT INT HUP TERM
  log "Checking for WebCLI updates..."
  fetch_with_fallback "$artifact_primary" "$artifact_fallback" "$tmp/$asset" || die "Could not fetch $asset"
  fetch_with_fallback "$checksums_primary" "$checksums_fallback" "$tmp/SHA256SUMS.txt" || die "Could not fetch SHA256SUMS.txt"

  expected=$(grep "  ${asset}$" "$tmp/SHA256SUMS.txt" | awk '{print $1}' || true)
  [ -n "$expected" ] || die "Missing checksum entry for $asset"
  actual=$(sha256_hex "$tmp/$asset")
  [ "$expected" = "$actual" ] || die "Checksum verification failed for $asset"

  case "$asset" in
    *.tar.gz) tar -xzf "$tmp/$asset" -C "$tmp" ;;
    *.zip)
      command -v unzip >/dev/null 2>&1 || die "unzip is required to extract $asset"
      unzip -q "$tmp/$asset" -d "$tmp"
      ;;
  esac

  web_bin=$(find "$tmp" -type f -name web -print | head -n 1)
  [ -n "$web_bin" ] || die "Could not locate web in $asset"
  mkdir -p "$RUNTIME_DIR"
  install -m 755 "$web_bin" "$RUNTIME_DIR/web"

  bbx_bin=$(find "$tmp" -type f -name bbx -print | head -n 1)
  if [ -n "$bbx_bin" ]; then install -m 755 "$bbx_bin" "$RUNTIME_DIR/bbx"; fi
  date +%s > "$CHECK_FILE"
}

if should_update; then download_and_install; fi

if [ "${WEBCLI_INSTALL_ONLY:-0}" = "1" ]; then
  log "WebCLI payload is ready in $RUNTIME_DIR"
  exit 0
fi

case "${1:-}" in
  web|bbx) command_name="$1"; shift ;;
  *) command_name=$(basename "$0") ;;
esac
payload="$RUNTIME_DIR/$command_name"
[ -x "$payload" ] || die "$command_name is not installed. Re-run the installer."
exec "$payload" "$@"
EOF
  chmod 755 "$WRAPPER_PATH"
}

write_command_shim() {
  shim_path="$1"
  command_name="$2"
  cat > "$shim_path" <<EOF
#!/usr/bin/env sh
set -eu
STATE_DIR="\${WEBCLI_STATE_DIR:-\$HOME/.webcli}"
exec "\$STATE_DIR/webcli-wrapper.sh" "$command_name" "\$@"
EOF
  chmod 755 "$shim_path"
}

main() {
  command -v curl >/dev/null 2>&1 || die "curl is required"
  command -v tar >/dev/null 2>&1 || die "tar is required"
  ensure_dir "$STATE_DIR"
  write_runtime_wrapper

  target_dir=$(choose_command_dir)
  ensure_dir "$target_dir"
  tmp=$(mktemp -d)
  trap 'rm -rf "$tmp"' EXIT INT HUP TERM

  for command_name in web bbx; do
    shim_path="$tmp/$command_name"
    write_command_shim "$shim_path" "$command_name"
    install -m 755 "$shim_path" "$target_dir/$command_name"
  done

  WEBCLI_INSTALL_ONLY=1 "$WRAPPER_PATH"
  log "Installed WebCLI commands to $target_dir"
  log "WebCLI wrapper: $WRAPPER_PATH"
  log "WebCLI runtime: $RUNTIME_DIR"
}

main "$@"
