#!/usr/bin/env bash

BRT_BASE_URL="${BRT_BASE_URL:-https://brt.sushii.dev}"
BRT_INSTALL_DIR="${BRT_DIR:-${BRT_INSTALL_DIR:-${HOME}/.local/share/brt}}"
BRT_BIN_DIR="${BRT_BIN_DIR:-${HOME}/.local/bin}"
BRT_UPDATE_CHECK_MARKER='# brt auto-update check'
BRT_UPDATE_CHECK_INTERVAL="${BRT_UPDATE_CHECK_INTERVAL:-86400}"

brt_shell_rc_file() {
  case "${SHELL##*/}" in
    zsh) printf '%s' "${HOME}/.zshrc" ;;
    bash)
      if [[ "$(uname -s)" == "Darwin" ]]; then
        printf '%s' "${HOME}/.bash_profile"
      else
        printf '%s' "${HOME}/.bashrc"
      fi
      ;;
    *) printf '%s' "${HOME}/.profile" ;;
  esac
}

brt_ensure_startup_check_hook() {
  brt_remove_startup_check_hook
}

brt_remove_startup_check_hook() {
  local rc tmp
  rc=$(brt_shell_rc_file)
  [[ -f "$rc" ]] || return 0
  grep -qE 'brt -update-check|# brt auto-update check|e\[3J|\033\[3J|\[3J.*\[2J' "$rc" 2>/dev/null || return 0

  tmp=$(mktemp)
  awk -v marker="$BRT_UPDATE_CHECK_MARKER" '
    $0 == marker { skip=1; next }
    /brt -update-check/ { skip=1; next }
    /e\[3J|print -n.*3J|printf.*\\033\[3J/ { skip=1; next }
    skip {
      if (/disown/) { skip=0; next }
      if (/&!/) { skip=0; next }
      if (/nonotify|nomonitor/) next
      if (/set \+m/) next
      if (/setopt localoptions/) next
      if (/\/dev\/tty/) next
      if (/sleep 0\./) next
      if (/print -n|printf/) next
      if (/^[[:space:]]*[\{\(][[:space:]]*$/) next
      if (/^[[:space:]]*\}[[:space:]]*$/) { skip=0; next }
      if (/^[[:space:]]*$/) { skip=0; next }
      skip=0
    }
    { print }
  ' "$rc" > "$tmp" && mv "$tmp" "$rc"
}

brt_update_resolve_install_dir() {
  local brt_bin install_dir
  brt_bin=$(command -v brt 2>/dev/null || true)
  [[ -n "$brt_bin" ]] || return 1
  install_dir=$(brt_realpath "$brt_bin" 2>/dev/null || printf '%s' "$brt_bin")
  dirname "$install_dir"
}

brt_update_check_startup() {
  local cache_dir="${HOME}/.brt"
  local cache_file="${cache_dir}/last-update-check"
  local install_dir local_version remote_version newest now last=0

  [[ "${BRT_AUTO_UPDATE:-1}" == "0" ]] && return 0
  command -v curl &>/dev/null || return 0

  install_dir="${BRT_DIR:-}"
  if [[ -z "$install_dir" || ! -f "${install_dir}/brt" ]]; then
    install_dir=$(brt_update_resolve_install_dir 2>/dev/null || true)
  fi
  [[ -n "$install_dir" && -f "${install_dir}/brt" ]] || return 0

  now=$(date +%s)
  if [[ -f "$cache_file" ]]; then
    last=$(tr -d '[:space:]' < "$cache_file" 2>/dev/null || echo 0)
    [[ "$last" =~ ^[0-9]+$ ]] || last=0
    if (( now - last < BRT_UPDATE_CHECK_INTERVAL )); then
      return 0
    fi
  fi

  remote_version=$(
    curl -fsSL --max-time 4 \
      -H 'Cache-Control: no-cache' \
      -H 'Pragma: no-cache' \
      "${BRT_BASE_URL}/version" 2>/dev/null \
      | tr -d '[:space:]'
  ) || return 0
  [[ -n "$remote_version" ]] || return 0

  mkdir -p "$cache_dir"
  printf '%s\n' "$now" > "$cache_file"

  local_version=$(brt_read_version "$install_dir")
  local_version="${local_version:-unknown}"
  [[ "$local_version" == "unknown" ]] && return 0

  if [[ "$local_version" == "$remote_version" ]]; then
    return 0
  fi

  newest=$(printf '%s\n' "$local_version" "$remote_version" | sort -V | tail -1)
  if [[ "$newest" != "$remote_version" ]]; then
    return 0
  fi

  printf '%s → %s\n' "$local_version" "$remote_version" > "${cache_dir}/update-available"
  return 0
}

brt_update_check_manual() {
  brt_require curl

  local local_version remote_version newest
  local_version=$(brt_read_version "$BRT_DIR")
  local_version="${local_version:-${BRT_VERSION}}"

  brt_info "Checking for updates at ${BRT_BASE_URL}..."

  remote_version=$(
    curl -fsSL --max-time 10 \
      -H 'Cache-Control: no-cache' \
      -H 'Pragma: no-cache' \
      "${BRT_BASE_URL}/version" 2>/dev/null \
      | tr -d '[:space:]'
  ) || {
    brt_error "Could not fetch version from ${BRT_BASE_URL}/version"
    exit 1
  }

  if [[ -z "$remote_version" ]]; then
    brt_error "Remote version file is empty"
    exit 1
  fi

  if [[ "$local_version" == "$remote_version" ]]; then
    brt_ok "brt ${local_version} is up to date"
    return 0
  fi

  newest=$(printf '%s\n' "$local_version" "$remote_version" | sort -V | tail -1)
  if [[ "$newest" != "$remote_version" ]]; then
    brt_ok "brt ${local_version} is up to date (remote: ${remote_version})"
    return 0
  fi

  brt_warn "Update available: ${local_version} → ${remote_version}"
  brt_info "Run: brt -update"
}

brt_update_check() {
  case "${1:-}" in
    --startup)
      brt_update_check_startup
      ;;
    --install-hook)
      brt_remove_startup_check_hook
      ;;
    *)
      brt_update_check_manual "$@"
      ;;
  esac
}

BRT_LIB_MODULES="common progress deps ip dns portscan ping whois trace curl post headers ssl reverse edit json encode hash url grep uuid pass run serve watch listen killport du extract sysinfo publickey timestamp timer calc env which speed weather qr image video doom browse config access update uninstall"

UPDATE_FILES=()
UPDATE_DOWNLOAD=()
UPDATE_SKIPPED=0

brt_update_download_files() {
  UPDATE_FILES=(brt)
  local f
  for f in ${BRT_LIB_MODULES}; do
    UPDATE_FILES+=("lib/${f}.sh")
  done
  UPDATE_FILES+=(lib/access.py lib/media.py lib/browse.py version)
}

brt_update_sha256_file() {
  local file="$1"
  [[ -f "$file" ]] || return 0
  if command -v sha256sum &>/dev/null; then
    sha256sum "$file" | awk '{print $1}'
  else
    shasum -a 256 "$file" | awk '{print $1}'
  fi
}

brt_update_manifest_hash() {
  local manifest="$1"
  local path="$2"
  awk -v p="$path" '$0 !~ /^#/ && $2 == p { print $1; exit }' "$manifest"
}

brt_update_fetch_checksums() {
  local dest="$1"
  curl -fsSL \
    -H 'Cache-Control: no-cache' \
    -H 'Pragma: no-cache' \
    "${BRT_BASE_URL}/checksums" \
    -o "$dest" 2>/dev/null
}

brt_update_remove_stale_files() {
  local f rel keep entry
  for f in "${BRT_INSTALL_DIR}/lib/"*.sh "${BRT_INSTALL_DIR}/lib/"*.py; do
    [[ -e "$f" ]] || continue
    rel="lib/$(basename "$f")"
    keep=0
    for entry in "${UPDATE_FILES[@]}"; do
      [[ "$entry" == "$rel" ]] && keep=1 && break
    done
    [[ "$keep" -eq 1 ]] || rm -f "$f"
  done
}

brt_update_plan_downloads() {
  local manifest="$1"
  local path remote_hash local_hash
  UPDATE_DOWNLOAD=()
  UPDATE_SKIPPED=0

  for path in "${UPDATE_FILES[@]}"; do
    remote_hash=$(brt_update_manifest_hash "$manifest" "$path")
    if [[ -n "$remote_hash" && -f "${BRT_INSTALL_DIR}/${path}" ]]; then
      local_hash=$(brt_update_sha256_file "${BRT_INSTALL_DIR}/${path}")
      if [[ "$remote_hash" == "$local_hash" ]]; then
        ((UPDATE_SKIPPED++)) || true
        continue
      fi
    fi
    UPDATE_DOWNLOAD+=("$path")
  done
}

brt_update_fetch() {
  local path="$1"
  local dest="${BRT_INSTALL_DIR}/${path}"
  mkdir -p "$(dirname "$dest")"
  curl -fsSL \
    -H 'Cache-Control: no-cache' \
    -H 'Pragma: no-cache' \
    "${BRT_BASE_URL}/${path}" \
    -o "$dest" || {
    brt_error "Failed to download ${BRT_BASE_URL}/${path}"
    exit 1
  }
}

brt_update_remote_brt_version() {
  curl -fsSL "${BRT_BASE_URL}/brt" 2>/dev/null \
    | grep '^_BRT_EMBEDDED_VERSION=' \
    | head -1 \
    | cut -d'"' -f2
}

brt_update_install() {
  local path total i=0
  local manifest use_manifest=0

  brt_update_download_files
  mkdir -p "${BRT_INSTALL_DIR}/lib" "${BRT_BIN_DIR}"

  manifest=$(mktemp)
  if brt_update_fetch_checksums "$manifest"; then
    use_manifest=1
    brt_update_plan_downloads "$manifest"
  else
    UPDATE_DOWNLOAD=("${UPDATE_FILES[@]}")
    UPDATE_SKIPPED=0
    brt_warn "Remote checksums unavailable — downloading all files"
  fi
  rm -f "$manifest"

  total=${#UPDATE_DOWNLOAD[@]}
  if [[ "$total" -eq 0 ]]; then
    brt_ok "All ${#UPDATE_FILES[@]} files already up to date"
  else
    if [[ "$use_manifest" -eq 1 && "$UPDATE_SKIPPED" -gt 0 ]]; then
      brt_info "Downloading ${total} changed file(s), skipped ${UPDATE_SKIPPED} unchanged"
    else
      brt_info "Downloading brt from ${BRT_BASE_URL}..."
    fi

    for path in "${UPDATE_DOWNLOAD[@]}"; do
      ((i++)) || true
      brt_progress_bar "$i" "$total" "$path"
      brt_update_fetch "$path"
    done
  fi

  brt_update_remove_stale_files

  chmod +x "${BRT_INSTALL_DIR}/brt" "${BRT_INSTALL_DIR}/lib/"*.sh "${BRT_INSTALL_DIR}/lib/access.py" "${BRT_INSTALL_DIR}/lib/media.py" "${BRT_INSTALL_DIR}/lib/browse.py" 2>/dev/null || true
  ln -sf "${BRT_INSTALL_DIR}/brt" "${BRT_BIN_DIR}/brt"
}

brt_update_confirm() {
  printf "Install update? [Y/n] "
  read -r ans
  [[ -z "$ans" || "$ans" =~ ^[Yy]$ ]]
}

brt_update() {
  brt_require curl

  local local_version remote_version remote_brt_version installed_version
  local_version=$(brt_read_version "$BRT_DIR")
  local_version="${local_version:-${BRT_VERSION}}"

  brt_info "Checking for updates at ${BRT_BASE_URL}..."

  remote_version=$(curl -fsSL "${BRT_BASE_URL}/version" 2>/dev/null | tr -d '[:space:]') || {
    brt_error "Could not fetch version from ${BRT_BASE_URL}/version"
    exit 1
  }

  if [[ -z "$remote_version" ]]; then
    brt_error "Remote version file is empty"
    exit 1
  fi

  remote_brt_version=$(brt_update_remote_brt_version)
  if [[ -z "$remote_brt_version" ]]; then
    brt_error "Could not read version from ${BRT_BASE_URL}/brt"
    exit 1
  fi

  if [[ "$remote_version" != "$remote_brt_version" ]]; then
    brt_error "Site files are out of sync (version=${remote_version}, brt=${remote_brt_version})"
    brt_info "Try again after the site redeploys, or reinstall:"
    brt_info "$(brt_install_hint_primary)"
    exit 1
  fi

  if [[ "$local_version" == "$remote_version" ]]; then
    brt_ok "brt ${local_version} is up to date"
    exec "${BRT_DIR}/brt" -version
  fi

  local newest
  newest=$(printf '%s\n' "$local_version" "$remote_version" | sort -V | tail -1)

  if [[ "$newest" != "$remote_version" ]]; then
    brt_ok "brt ${local_version} is up to date (remote: ${remote_version})"
    exec "${BRT_DIR}/brt" -version
  fi

  brt_info "Update available: ${local_version} → ${remote_version}"
  if ! brt_update_confirm; then
    brt_info "Update cancelled"
    return 0
  fi

  brt_update_install

  installed_version=$(brt_read_version "$BRT_INSTALL_DIR")
  if [[ "$installed_version" != "$remote_version" ]]; then
    brt_error "Update failed: expected ${remote_version}, got ${installed_version:-unknown}"
    exit 1
  fi

  hash -r 2>/dev/null || rehash 2>/dev/null || true

  # shellcheck source=/dev/null
  source "${BRT_INSTALL_DIR}/lib/deps.sh"
  brt_install_media_dependencies || true

  brt_ok "Updated to brt ${installed_version}"
  brt_info "Installed at: ${BRT_INSTALL_DIR}"
  brt_ensure_startup_check_hook || true
  exec "${BRT_INSTALL_DIR}/brt" -version
}
