#!/usr/bin/env bash
# Archive release artifacts (unstripped .so, mapping, HAR) for crash analysis.
# Usage: bash scripts/archive-release.sh <version>
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "$SCRIPT_DIR/_config.sh"

VERSION="${1:-}"
if [ -z "$VERSION" ]; then
  err "Usage: bash scripts/archive-release.sh <version>"
  exit 1
fi

ARCHIVE_DIR="$REPO_ROOT/flexui-engine/release/$VERSION"
ENGINE_DIR="$REPO_ROOT/flexui-engine"
OHOS_DIR="$ENGINE_DIR/framework/ohos"

log "=== Archiving release artifacts v$VERSION ==="

# ---------------------------------------------------------------------------
# 1. Resolve source paths
# ---------------------------------------------------------------------------

UNSTRIPPED_SO="$OHOS_DIR/.cxx/default/default/debug/arm64-v8a/libflexui.so"
HAR_PATH="$ENGINE_DIR/output/flexui_engine.har"
MAPPING_DIR="$OHOS_DIR/build/default/outputs/default/mapping"

# ---------------------------------------------------------------------------
# 2. Validate sources exist (report but don't fail on non-critical items)
# ---------------------------------------------------------------------------
SO_OK=0
HAR_OK=0
MAPPING_OK=0

if [ -f "$UNSTRIPPED_SO" ]; then
  SO_OK=1
  SO_SIZE=$(ls -lh "$UNSTRIPPED_SO" | awk '{print $5}')
else
  warn "Unstripped .so not found at: $UNSTRIPPED_SO"
  warn "  Run a release build first: bash build.sh build-engine --release"
fi

if [ -f "$HAR_PATH" ]; then
  HAR_OK=1
  HAR_SIZE=$(ls -lh "$HAR_PATH" | awk '{print $5}')
else
  warn "HAR not found at: $HAR_PATH"
fi

if [ -d "$MAPPING_DIR" ] && [ -n "$(ls -A "$MAPPING_DIR" 2>/dev/null)" ]; then
  MAPPING_OK=1
else
  warn "Obfuscation mapping not found (only generated in release mode with obfuscation)"
fi

if [ "$SO_OK" -eq 0 ] && [ "$HAR_OK" -eq 0 ]; then
  err "No artifacts found — nothing to archive."
  exit 1
fi

# ---------------------------------------------------------------------------
# 3. Create archive directory
# ---------------------------------------------------------------------------
mkdir -p "$ARCHIVE_DIR"

# Ensure .gitignore exists for the release/ directory (keep dir, ignore contents)
if [ ! -f "$ENGINE_DIR/release/.gitignore" ]; then
  echo "*" > "$ENGINE_DIR/release/.gitignore"
  log "Created flexui-engine/release/.gitignore"
fi

# ---------------------------------------------------------------------------
# 4. Copy artifacts
# ---------------------------------------------------------------------------

if [ "$SO_OK" -eq 1 ]; then
  cp "$UNSTRIPPED_SO" "$ARCHIVE_DIR/libflexui.so"
  log "libflexui.so ($SO_SIZE) → release/$VERSION/"
fi

if [ "$HAR_OK" -eq 1 ]; then
  cp "$HAR_PATH" "$ARCHIVE_DIR/flexui_engine.har"
  log "flexui_engine.har ($HAR_SIZE) → release/$VERSION/"
fi

if [ "$MAPPING_OK" -eq 1 ]; then
  mkdir -p "$ARCHIVE_DIR/mapping"
  cp -r "$MAPPING_DIR"/* "$ARCHIVE_DIR/mapping/"
  log "mapping/ → release/$VERSION/"
fi

# ---------------------------------------------------------------------------
# 5. Generate build-info.json
# ---------------------------------------------------------------------------

GIT_COMMIT=$(git -C "$REPO_ROOT" rev-parse HEAD 2>/dev/null || echo "unknown")
GIT_BRANCH=$(git -C "$REPO_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
BUILD_TIME=$(date -Iseconds 2>/dev/null || date "+%Y-%m-%dT%H:%M:%S%z")
SDK_HOME="${DEVECO_SDK_HOME:-unknown}"

cat > "$ARCHIVE_DIR/build-info.json" <<EOF
{
  "version": "$VERSION",
  "buildTime": "$BUILD_TIME",
  "gitCommit": "$GIT_COMMIT",
  "gitBranch": "$GIT_BRANCH",
  "sdkHome": "$SDK_HOME",
  "libflexuiSize": "$(ls -lh "$UNSTRIPPED_SO" 2>/dev/null | awk '{print $5}' || echo 'N/A')"
}
EOF
log "build-info.json → release/$VERSION/"

# ---------------------------------------------------------------------------
# 6. Generate README.md with crash analysis instructions
# ---------------------------------------------------------------------------

cat > "$ARCHIVE_DIR/README.md" <<'READMEEOF'
# Release vVERSION — Crash Analysis Artifacts

## Contents

| File | Purpose |
|------|---------|
| `libflexui.so` | Unstripped native library with full debug symbols |
| `flexui_engine.har` | Published HAR package (release, obfuscated) |
| `flexui_engine-debug.har` | Debug HAR for development/testing |
| `mapping/` (if present) | ArkTS obfuscation mapping for deobfuscating stack traces |
| `build-info.json` | Build metadata (timestamp, git commit, SDK) |

## How to Symbolize a Native Crash Stack

### Prerequisites

- DevEco Studio SDK (provides `llvm-addr2line` or `llvm-symbolizer`)
- The `libflexui.so` from this directory

### Steps

1. **Locate the crash address** from the crash log (e.g., `#00 pc 0000000000123456 libflexui.so`).

2. **Symbolize with llvm-addr2line:**

   ```bash
   LLVM="$DEVECO_SDK_HOME/default/openharmony/native/llvm/bin"
   "$LLVM/llvm-addr2line" -f -e libflexui.so <crash_address>
   ```

   Example:
   ```bash
   "$LLVM/llvm-addr2line" -f -e libflexui.so 0000000000123456
   ```

3. **Symbolize with ndk-stack (batch):**

   If you have a full crash dump with multiple frames, use `ndk-stack`:
   ```bash
   ndk-stack -sym ./ -dump crash.log
   ```

### Deobfuscate ArkTS Stack Traces

If the crash involves ArkTS code with obfuscated names, use the mapping files in `mapping/`:

```bash
# The mapping file maps obfuscated names back to original source names
# Example: a → MyComponent, b → handleClick
```

### Note

This `.so` file is ~121 MB because it contains full debug symbols (`strip: false`).
The `.so` shipped inside the HAR is identical — stripping happens downstream when
the app HAP is packaged by hvigor's `DoNativeStrip` task.
READMEEOF

# Replace VERSION placeholder in README
sed -i "s/VERSION/$VERSION/g" "$ARCHIVE_DIR/README.md"
log "README.md → release/$VERSION/"

# ---------------------------------------------------------------------------
# Done
# ---------------------------------------------------------------------------
log "=== Archive complete: release/$VERSION/ ==="
echo ""
ls -lh "$ARCHIVE_DIR/"