#!/bin/bash
#
# Install a signed HAP onto connected HarmonyOS devices via hdc.
#
# Usage:
#   ./installOhosHap-Mac.sh
#   ./installOhosHap-Mac.sh -f /path/to/app.hap
#   ./installOhosHap-Mac.sh -f app.hap -t 127.0.0.1:5555 -u
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_HAP="/Users/dongsq/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/wxid_r4h5wm6tbw9q22_8d0b/msg/file/2026-07/entry-default-signed(1).hap"
DEFAULT_ABILITY="EntryAbility"
REMOTE_DIR="/data/local/tmp/hap_install"

HAP_FILE="$DEFAULT_HAP"
TARGET_ID=""
BUNDLE_NAME=""
ABILITY_NAME="$DEFAULT_ABILITY"
FORCE_UNINSTALL=0
NO_START=0

usage() {
  cat <<EOF
Usage: $0 [options]

Install a signed HAP to connected HarmonyOS device(s).

Options:
  -f PATH   HAP file path (default: WeChat shared entry-default-signed(1).hap)
  -t ID     Device id from 'hdc list targets' (default: all connected devices)
  -b NAME   Bundle name (default: read from HAP pack.info, else app.json5)
  -a NAME   Ability name for aa start (default: $DEFAULT_ABILITY)
  -u        Uninstall existing app before install
  -n        Install only, do not launch app
  -h        Help

Examples:
  $0
  $0 -f ./harmonyApp/entry/build/default/outputs/default/entry-default-signed.hap
  $0 -f ~/Downloads/app.hap -t 127.0.0.1:5555 -u
EOF
  exit 0
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -f) HAP_FILE="$2"; shift 2 ;;
    -t) TARGET_ID="$2"; shift 2 ;;
    -b) BUNDLE_NAME="$2"; shift 2 ;;
    -a) ABILITY_NAME="$2"; shift 2 ;;
    -u) FORCE_UNINSTALL=1; shift ;;
    -n) NO_START=1; shift ;;
    -h) usage ;;
    *) echo "Unknown option: $1"; usage ;;
  esac
done

DEVECO_PATH="${DEVECO_PATH:-/Applications/DevEco-Studio.app}"
DEVECO_HOME="${DEVECO_HOME:-$DEVECO_PATH/Contents}"
HDC_BIN="$DEVECO_HOME/sdk/default/openharmony/toolchains/hdc"

if [[ ! -x "$HDC_BIN" ]]; then
  echo "Error: hdc not found at $HDC_BIN"
  exit 1
fi

if [[ ! -f "$HAP_FILE" ]]; then
  echo "Error: HAP not found: $HAP_FILE"
  exit 1
fi

HAP_FILE="$(cd "$(dirname "$HAP_FILE")" && pwd)/$(basename "$HAP_FILE")"
HAP_BASENAME="$(basename "$HAP_FILE")"

read_bundle_from_hap() {
  local pack
  pack="$(unzip -p "$HAP_FILE" pack.info 2>/dev/null || true)"
  if [[ -n "$pack" ]]; then
    echo "$pack" | sed -n 's/.*"bundleName"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1
  fi
}

if [[ -z "$BUNDLE_NAME" ]]; then
  BUNDLE_NAME="$(read_bundle_from_hap || true)"
fi

if [[ -z "$BUNDLE_NAME" && -f "$SCRIPT_DIR/harmonyApp/AppScope/app.json5" ]]; then
  BUNDLE_NAME="$(grep '"bundleName"' "$SCRIPT_DIR/harmonyApp/AppScope/app.json5" \
    | sed 's/.*"bundleName"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | head -1 | tr -d '\r')"
fi

if [[ -z "$BUNDLE_NAME" ]]; then
  echo "Error: could not determine bundle name; pass -b com.example.app"
  exit 1
fi

mapfile -t DEVICE_IDS < <("$HDC_BIN" list targets 2>/dev/null \
  | awk 'NF>=1 && $1 !~ /^\[Empty\]$/{print $1}' \
  | tr -d '\r')

if [[ -n "$TARGET_ID" ]]; then
  DEVICE_IDS=("$TARGET_ID")
fi

if [[ ${#DEVICE_IDS[@]} -eq 0 ]]; then
  echo "Error: no device connected. Connect phone and run: $HDC_BIN list targets"
  exit 1
fi

install_on_device() {
  local tid="$1"
  echo "============================================================"
  echo "Device: $tid"
  echo "HAP:    $HAP_FILE"
  echo "Bundle: $BUNDLE_NAME"

  if [[ "$FORCE_UNINSTALL" -eq 1 ]]; then
    echo "Uninstalling $BUNDLE_NAME ..."
    "$HDC_BIN" -t "$tid" shell bm uninstall -n "$BUNDLE_NAME" >/dev/null 2>&1 || true
  fi

  echo "Pushing HAP ..."
  "$HDC_BIN" -t "$tid" shell mkdir -p "$REMOTE_DIR"
  "$HDC_BIN" -t "$tid" file send "$HAP_FILE" "$REMOTE_DIR/$HAP_BASENAME"

  echo "Installing ..."
  local output
  output="$("$HDC_BIN" -t "$tid" shell bm install -p "$REMOTE_DIR/$HAP_BASENAME" 2>&1 || true)"
  echo "$output"

  if echo "$output" | grep -qiE 'fail|error'; then
    echo "Install failed, retrying after uninstall ..."
    "$HDC_BIN" -t "$tid" shell bm uninstall -n "$BUNDLE_NAME" >/dev/null 2>&1 || true
    sleep 2
    output="$("$HDC_BIN" -t "$tid" shell bm install -p "$REMOTE_DIR/$HAP_BASENAME" 2>&1 || true)"
    echo "$output"
    if echo "$output" | grep -qiE 'fail|error'; then
      echo "Error: install failed on $tid"
      return 1
    fi
  fi

  if [[ "$NO_START" -eq 0 ]]; then
    echo "Launching $ABILITY_NAME ..."
    "$HDC_BIN" -t "$tid" shell aa start -a "$ABILITY_NAME" -b "$BUNDLE_NAME"
  fi

  echo "Done on $tid"
}

FAIL=0
for tid in "${DEVICE_IDS[@]}"; do
  if ! install_on_device "$tid"; then
    FAIL=1
  fi
done

exit "$FAIL"
