#!/usr/bin/env bash
set -euo pipefail

# ============================================================================
APP_PKG="uk.simlink.lpa"
APKTOOL_TREE="eazyeuicc"
ORIG_APK="eazyeuicc.apk"
DEP_JAR="eazyeuicc.jar"
JAVA_PKG="im.angry.openeuicc.bridge"
SRC_DIR="src"
OUT_DIR="out"
DEPS_DIR="deps"
BAKSMALI_JAR="tools/baksmali.jar"
# ============================================================================

pick_smali_bucket() {
  local base="$APKTOOL_TREE"
  local n=2
  [[ -d "$base/smali" ]] && echo "$base/smali" && return 0
  while [[ -d "$base/smali_classes$n" ]]; do n=$((n+1)); done
  echo "$base/smali_classes$n"
}

# Derived paths/names
SMALI_PKG_DIR="${JAVA_PKG//.//}"
SRC_PKG_DIR="${SRC_DIR}/${SMALI_PKG_DIR}"
TARGET_SMALI_ROOT="$(pick_smali_bucket)"
TARGET_SMALI_DIR="${TARGET_SMALI_ROOT}/${SMALI_PKG_DIR}"

# SDK paths
ANDROID_SDK="$HOME/Library/Android/sdk"
ANDROID_JAR="$ANDROID_SDK/platforms/android-33/android.jar"
BT="$ANDROID_SDK/build-tools/$(ls "$ANDROID_SDK/build-tools" | sort -V | tail -1)"

# Sanity: tools present
command -v apktool >/dev/null || { echo "ERROR: apktool not found"; exit 1; }
command -v adb     >/dev/null || { echo "ERROR: adb not found"; exit 1; }
command -v java    >/dev/null || { echo "ERROR: java not found"; exit 1; }
command -v javac   >/dev/null || { echo "ERROR: javac not found"; exit 1; }
# command -v keytool >/dev/null || { echo "ERROR: keytool not found"; exit 1; }

# Sanity: files/dirs
[[ -f "$ANDROID_JAR" ]]  || { echo "ERROR: android.jar not found: $ANDROID_JAR"; exit 1; }
[[ -x "$BT/d8" ]]        || { echo "ERROR: d8 not found: $BT/d8"; exit 1; }
[[ -x "$BT/zipalign" ]]  || { echo "ERROR: zipalign not found: $BT/zipalign"; exit 1; }
[[ -x "$BT/apksigner" ]] || { echo "ERROR: apksigner not found: $BT/apksigner"; exit 1; }
[[ -f "$BAKSMALI_JAR" ]] || { echo "ERROR: baksmali jar missing: $BAKSMALI_JAR"; exit 1; }
[[ -d "$APKTOOL_TREE" ]] || { echo "ERROR: apktool tree missing: $APKTOOL_TREE"; exit 1; }
[[ -d "$SRC_PKG_DIR" ]]  || { echo "ERROR: source package dir missing: $SRC_PKG_DIR"; exit 1; }
mkdir -p "$DEPS_DIR"

# Ensure we have a complete classpath jar containing ALL dexes (kotlin, coroutines, lpac_jni, etc.)
rebuild_cp_jar() {
  local apk="$1"
  local dexdir="$DEPS_DIR/_dex"
  local mergedir="$DEPS_DIR/_merge"
  local jar_out="$DEPS_DIR/$DEP_JAR"
  rm -rf "$dexdir" "$mergedir"
  mkdir -p "$dexdir" "$mergedir"

  echo "[dex] extracting classes*.dex from $apk"
  unzip -q -j "$apk" 'classes*.dex' -d "$dexdir"

  local any=0
  for d in "$dexdir"/classes*.dex; do
    [[ -f "$d" ]] || continue
    any=1
    local j="${d%.dex}.jar"
    echo "[dex2jar] $d -> $j"
    d2j-dex2jar "$d" -o "$j" >/dev/null
    unzip -q -o "$j" -d "$mergedir"
  done
  [[ $any -eq 1 ]] || { echo "ERROR: no classes*.dex found in $apk"; exit 1; }

  (cd "$mergedir" && jar cf "../$DEP_JAR" .)
  rm -rf "$dexdir" "$mergedir"
}

# (Re)build deps jar if missing or incomplete
APP_JAR="$DEPS_DIR/$DEP_JAR"
need_rebuild=0
if [[ ! -f "$APP_JAR" ]]; then
  need_rebuild=1
else
  jar tf "$APP_JAR" | grep -q '^kotlin/'                  || need_rebuild=1
  jar tf "$APP_JAR" | grep -q '^kotlinx/coroutines/'      || need_rebuild=1
  jar tf "$APP_JAR" | grep -q '^net/typeblog/lpac_jni/'   || need_rebuild=1
fi
if [[ $need_rebuild -eq 1 ]]; then
  [[ -f "$ORIG_APK" ]] || { echo "ERROR: ORIG_APK not found: $ORIG_APK"; exit 1; }
  rebuild_cp_jar "$ORIG_APK"
fi

# Verify again (fail fast with helpful messages)
jar tf "$APP_JAR" | grep -q '^kotlin/'                || { echo "ERROR: Kotlin stdlib missing in $APP_JAR"; exit 1; }
jar tf "$APP_JAR" | grep -q '^kotlinx/coroutines/'    || { echo "ERROR: kotlinx coroutines missing in $APP_JAR"; exit 1; }
jar tf "$APP_JAR" | grep -q '^net/typeblog/lpac_jni/' || { echo "ERROR: net.typeblog.lpac_jni missing in $APP_JAR"; exit 1; }

# Gather sources
JAVA_SOURCES=()
while IFS= read -r -d '' f; do
  JAVA_SOURCES+=("$f")
done < <(find "$SRC_PKG_DIR" -type f -name '*.java' -print0)
[[ ${#JAVA_SOURCES[@]} -gt 0 ]] || { echo "ERROR: no .java files found under $SRC_PKG_DIR"; exit 1; }

# Clean + mkdirs
rm -rf "$APKTOOL_TREE/build"
rm -rf "$OUT_DIR"
mkdir -p "$OUT_DIR"/{classes,dex,smali}

# Build classpath from all jars in deps
CP="$ANDROID_JAR:$(find "$DEPS_DIR" -maxdepth 1 -type f -name '*.jar' | paste -sd: -)"

# Compile
javac \
  -source 23 -target 23 \
  -classpath "$CP" \
  -Xlint:-options \
  -encoding UTF-8 \
  -d "$OUT_DIR/classes" \
  "${JAVA_SOURCES[@]}"

# DEX
D8_CLASSPATH_ARGS=()
IFS=':' read -ra CP_ENTRIES <<< "$CP"
for entry in "${CP_ENTRIES[@]}"; do
  D8_CLASSPATH_ARGS+=(--classpath "$entry")
done
"$BT/d8" \
  --lib "$ANDROID_JAR" \
  "${D8_CLASSPATH_ARGS[@]}" \
  --output "$OUT_DIR/dex" \
  $(find "$OUT_DIR/classes" -type f -name '*.class')


# Smali
found_dex=0
for dex in "$OUT_DIR"/dex/*.dex; do
  [[ -f "$dex" ]] || continue
  found_dex=1
  java -jar "$BAKSMALI_JAR" d "$dex" -o "$OUT_DIR/smali"
done
[[ $found_dex -eq 1 ]] || { echo "ERROR: no dex files produced"; exit 1; }
mkdir -p "$TARGET_SMALI_DIR"
if [[ -d "$OUT_DIR/smali/$SMALI_PKG_DIR" ]]; then
  rm -rf "$TARGET_SMALI_DIR"
  mkdir -p "$TARGET_SMALI_DIR"
  cp -R "$OUT_DIR/smali/$SMALI_PKG_DIR/." "$TARGET_SMALI_DIR/"
else
  echo "ERROR: expected smali package dir not found: $OUT_DIR/smali/$SMALI_PKG_DIR"
  exit 1
fi

# Rebuild
apktool b "$APKTOOL_TREE" -o "$OUT_DIR/build-unsigned.apk"

# Align
"$BT/zipalign" -p -f 4 "$OUT_DIR/build-unsigned.apk" "$OUT_DIR/build-aligned.apk"

# Ensure keystore
# if [ ! -f "$HOME/.android/debug.keystore" ]; then
#   mkdir -p "$HOME/.android"
#   keytool -genkeypair \
#     -keystore "$HOME/.android/debug.keystore" \
#     -storepass android -keypass android \
#     -alias androiddebugkey \
#     -keyalg RSA -keysize 2048 -validity 10000 \
#     -dname "CN=Android Debug,O=Android,C=US"
# fi

# https://github.com/9esim/9eSIMCommunityKey
COMMUNITY_KEY_JKS="./9eSIMCommunityKey.jks"
COMMUNITY_KEY_PASS="147258369"

# Sign APK using 9eSIM Community Key
java --enable-native-access=ALL-UNNAMED \
  -jar "$BT/lib/apksigner.jar" sign \
  --ks "$COMMUNITY_KEY_JKS" \
  --ks-pass pass:"$COMMUNITY_KEY_PASS" \
  --out "$OUT_DIR/build-signed.apk" \
  "$OUT_DIR/build-aligned.apk"

# Install
adb install -r "$OUT_DIR/build-signed.apk"
