#
# chanora_bridge — Rust bridge library as a CocoaPods-vended dynamic framework.
#
# What this file does:
#
#   1. `prepare_command` runs once per `pod install` and once per archive
#      / device build. It:
#        a) Invokes `cargo build --release --target <iOS arch>` for both
#           aarch64-apple-ios (device) and aarch64-apple-ios-sim
#           (simulator on Apple Silicon) so the resulting framework
#           works for both targets.
#        b) Wraps the built dylib in a proper `chanora_bridge.framework`
#           bundle (Versions/A layout with the right Info.plist).
#        c) Rewrites LC_ID_DYLIB to
#           @rpath/chanora_bridge.framework/chanora_bridge so dyld
#           resolves it as a framework when embedded in Runner.app.
#
#   2. `vendored_frameworks` exposes the result to the Pods workspace.
#      CocoaPods then integrates the framework into Runner.xcodeproj
#      with the appropriate embed-and-sign build phase.
#
# Same role Cargokit plays for other Flutter+Rust setups, but written
# by hand against this specific repo's layout to avoid the Cargokit
# vendoring footprint we previously dropped.
#
# Path note: this podspec lives at apps/chanora_flutter/ios/, and
# refers to the Rust workspace at ../../.. (repo root). The
# prepare_command runs with PWD = the directory of this file, so all
# paths are relative to apps/chanora_flutter/ios/.

Pod::Spec.new do |s|
  s.name             = 'chanora_bridge'
  s.version          = '1.0.0'
  s.summary          = 'Chanora Rust bridge (libchanora_bridge) as an iOS framework.'
  s.description      = <<-DESC
    Vendors the Rust-built libchanora_bridge as chanora_bridge.framework so
    flutter_rust_bridge's runtime loader can dlopen it on iOS / iPadOS.
  DESC
  s.homepage         = 'https://github.com/EdisonJwa/chanora'
  s.license          = { :type => 'Apache-2.0 OR MIT', :text => 'See LICENSE-APACHE / LICENSE-MIT at the repo root' }
  s.author           = { 'EdisonJwa' => 'me@edison.network' }
  s.source           = { :path => '.' }
  s.platform         = :ios, '16.0'

  # Build the Rust bridge on `pod install`. The script runs under
  # bash; we use `set -e` so any failure (cargo missing, target not
  # installed, link error) aborts the install loudly. The
  # CMAKE_POLICY_VERSION_MINIMUM + IPHONEOS_DEPLOYMENT_TARGET
  # env vars satisfy audiopus_sys's cmake invocation on modern
  # CMake 4.x and Apple iOS SDK; both are required.
  s.prepare_command  = <<-SCRIPT
    set -e
    REPO_ROOT="$(cd ../../.. && pwd)"
    USER_NAME="$(id -un)"
    USER_HOME="$(dscl . -read "/Users/$USER_NAME" NFSHomeDirectory 2>/dev/null | awk '{print $2}')"
    if [ -z "$USER_HOME" ]; then
      USER_HOME="$(cd ~ && pwd)"
    fi
    BRIDGE="$REPO_ROOT/target/aarch64-apple-ios/release/libchanora_bridge.dylib"
    find_cargo() {
      for candidate in \
        "$USER_HOME/.cargo/bin/cargo" \
        "/opt/homebrew/opt/rustup/bin/cargo" \
        "/usr/local/opt/rustup/bin/cargo"
      do
        if [ -x "$candidate" ]; then
          echo "$candidate"
          return 0
        fi
      done
      command -v cargo
    }
    find_rustc() {
      for candidate in \
        "$USER_HOME/.cargo/bin/rustc" \
        "/opt/homebrew/opt/rustup/bin/rustc" \
        "/usr/local/opt/rustup/bin/rustc"
      do
        if [ -x "$candidate" ]; then
          echo "$candidate"
          return 0
        fi
      done
      command -v rustc
    }
    CARGO_BIN="$(find_cargo)"
    RUSTC_BIN="$(find_rustc)"

    # Prepend Homebrew's bin dir to PATH so `cmake` (used by
    # audiopus_sys's libopus source build) is found. Xcode's
    # script_phase PATH sanitisation strips /opt/homebrew/bin,
    # which on Apple Silicon hosts is where Homebrew tools live.
    export PATH="/opt/homebrew/bin:$PATH"

    echo "[chanora_bridge.podspec] cargo build aarch64-apple-ios"
    cd "$REPO_ROOT"
    HOME="$USER_HOME" \\
      CARGO_HOME="$USER_HOME/.cargo" \\
      RUSTUP_HOME="$USER_HOME/.rustup" \\
      RUSTUP_TOOLCHAIN="stable-aarch64-apple-darwin" \\
      RUSTC="$RUSTC_BIN" \\
      IPHONEOS_DEPLOYMENT_TARGET=16.0 \\
      CMAKE_POLICY_VERSION_MINIMUM=3.5 \\
      CMAKE_OSX_DEPLOYMENT_TARGET=16.0 \\
      CARGO_PROFILE_RELEASE_DEBUG=true \\
      CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO=off \\
      CARGO_PROFILE_RELEASE_STRIP=false \\
      "$CARGO_BIN" build --release --target aarch64-apple-ios -p chanora_bridge

    if [ ! -f "$BRIDGE" ]; then
      echo "ERROR: bridge dylib not found at $BRIDGE" >&2
      exit 1
    fi
    cd "$REPO_ROOT/apps/chanora_flutter/ios"

    # Build the chanora_bridge.framework layout in a known location
    # this podspec will then point vendored_frameworks at.
    FW=Frameworks/chanora_bridge.framework
    rm -rf "$FW"
    mkdir -p "$FW"
    cp "$BRIDGE" "$FW/chanora_bridge"

    cat > "$FW/Info.plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleExecutable</key><string>chanora_bridge</string>
  <key>CFBundleIdentifier</key><string>app.chanora.bridge</string>
  <key>CFBundleName</key><string>chanora_bridge</string>
  <key>CFBundlePackageType</key><string>FMWK</string>
  <key>CFBundleShortVersionString</key><string>1.0.0</string>
  <key>CFBundleVersion</key><string>1</string>
  <key>CFBundleSupportedPlatforms</key><array><string>iPhoneOS</string></array>
  <key>MinimumOSVersion</key><string>16.0</string>
</dict>
</plist>
PLIST

    install_name_tool -id "@rpath/chanora_bridge.framework/chanora_bridge" \\
                      "$FW/chanora_bridge"

    # Generate the framework's dSYM bundle. Apple's archive validator
    # rejects uploads when an embedded framework has no matching dSYM
    # (UUID lookup miss in the archive's dSYMs/ folder), which is the
    # failure mode that produced this prepare_command in the first
    # place. dsymutil reads the DWARF that cargo emitted (enabled by
    # [profile.release] debug = true at the workspace root) and writes
    # chanora_bridge.framework.dSYM next to the framework. We then
    # strip the in-framework binary so the shipped app stays slim —
    # the symbols live exclusively in the dSYM bundle, which is the
    # layout xcodebuild -exportArchive and App Store Connect expect.
    rm -rf "$FW.dSYM"
    xcrun dsymutil "$FW/chanora_bridge" -o "$FW.dSYM"
    xcrun strip -S -x "$FW/chanora_bridge"
    echo "[chanora_bridge.podspec] framework + dSYM ready at $FW"
  SCRIPT

  # Pod CocoaPods picks this up; the framework gets embedded into
  # Runner.app/Frameworks/ with Embed & Sign automatically.
  s.vendored_frameworks = 'Frameworks/chanora_bridge.framework'

  # Re-run the cargo build + framework wrap on every Xcode build,
  # not only on `pod install`. The `prepare_command` above runs
  # once per `pod install` which is too sticky — Rust source
  # changes were getting silently ignored because Xcode happily
  # re-bundled the stale framework. This script_phase shells out to
  # cargo on every Xcode "Build" so the framework is always in sync
  # with the current Rust workspace.
  #
  # `:execution_position => :before_compile` runs the script before
  # Xcode's CompileSources phase, so by the time the linker / embed
  # step sees `Frameworks/chanora_bridge.framework`, it is fresh.
  s.script_phase = {
    :name => 'Rebuild chanora_bridge.framework from Rust',
    :script => <<-SCRIPT,
      set -e
      REPO_ROOT="$(cd "${PODS_TARGET_SRCROOT}/../../.." && pwd)"
      USER_NAME="$(id -un)"
      USER_HOME="$(dscl . -read "/Users/$USER_NAME" NFSHomeDirectory 2>/dev/null | awk '{print $2}')"
      if [ -z "$USER_HOME" ]; then
        USER_HOME="$(cd ~ && pwd)"
      fi
      find_cargo() {
        for candidate in \
          "$USER_HOME/.cargo/bin/cargo" \
          "/opt/homebrew/opt/rustup/bin/cargo" \
          "/usr/local/opt/rustup/bin/cargo"
        do
          if [ -x "$candidate" ]; then
            echo "$candidate"
            return 0
          fi
        done
        command -v cargo
      }
      find_rustc() {
        for candidate in \
          "$USER_HOME/.cargo/bin/rustc" \
          "/opt/homebrew/opt/rustup/bin/rustc" \
          "/usr/local/opt/rustup/bin/rustc"
        do
          if [ -x "$candidate" ]; then
            echo "$candidate"
            return 0
          fi
        done
        command -v rustc
      }
      CARGO_BIN="$(find_cargo)"
      RUSTC_BIN="$(find_rustc)"

      # Prepend Homebrew's bin dir to PATH so `cmake` (used by
      # audiopus_sys's libopus source build) is found. Xcode's
      # script_phase PATH sanitisation strips /opt/homebrew/bin,
      # which on Apple Silicon hosts is where Homebrew tools live.
      export PATH="/opt/homebrew/bin:$PATH"

      if [ "${PLATFORM_NAME:-iphoneos}" = "iphonesimulator" ]; then
        RUST_TARGET="aarch64-apple-ios-sim"
        SUPPORTED_PLATFORM="iPhoneSimulator"
      else
        RUST_TARGET="aarch64-apple-ios"
        SUPPORTED_PLATFORM="iPhoneOS"
      fi
      BRIDGE="$REPO_ROOT/target/$RUST_TARGET/release/libchanora_bridge.dylib"
      echo "[chanora_bridge script_phase] cargo build $RUST_TARGET"
      cd "$REPO_ROOT"
      HOME="$USER_HOME" \\
        CARGO_HOME="$USER_HOME/.cargo" \\
        RUSTUP_HOME="$USER_HOME/.rustup" \\
        RUSTUP_TOOLCHAIN="stable-aarch64-apple-darwin" \\
        RUSTC="$RUSTC_BIN" \\
        IPHONEOS_DEPLOYMENT_TARGET=16.0 \\
        CMAKE_POLICY_VERSION_MINIMUM=3.5 \\
        CMAKE_OSX_DEPLOYMENT_TARGET=16.0 \\
        CARGO_PROFILE_RELEASE_DEBUG=true \\
        CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO=off \\
        CARGO_PROFILE_RELEASE_STRIP=false \\
        "$CARGO_BIN" build --release --target "$RUST_TARGET" -p chanora_bridge

      cd "$REPO_ROOT/apps/chanora_flutter/ios"
      FW=Frameworks/chanora_bridge.framework

      # Skip the wrap step if the framework's binary is already
      # up-to-date with the cargo output (fast no-op on incremental
      # builds where Rust didn't change). We still publish the dSYM
      # into DWARF_DSYM_FOLDER_PATH below so archive builds always
      # have the symbols, even when the framework itself is cached.
      FW_UP_TO_DATE=0
      if [ -f "$FW/chanora_bridge" ] && [ "$FW/chanora_bridge" -nt "$BRIDGE" ]; then
        echo "[chanora_bridge script_phase] framework already up-to-date"
        FW_UP_TO_DATE=1
      fi

      if [ "$FW_UP_TO_DATE" = 0 ]; then
        mkdir -p "$FW"
        cp "$BRIDGE" "$FW/chanora_bridge"
        cat > "$FW/Info.plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleExecutable</key><string>chanora_bridge</string>
  <key>CFBundleIdentifier</key><string>app.chanora.bridge</string>
  <key>CFBundleName</key><string>chanora_bridge</string>
  <key>CFBundlePackageType</key><string>FMWK</string>
  <key>CFBundleShortVersionString</key><string>1.0.0</string>
  <key>CFBundleVersion</key><string>1</string>
  <key>CFBundleSupportedPlatforms</key><array><string>$SUPPORTED_PLATFORM</string></array>
  <key>MinimumOSVersion</key><string>16.0</string>
</dict>
</plist>
PLIST
        install_name_tool -id "@rpath/chanora_bridge.framework/chanora_bridge" \\
                          "$FW/chanora_bridge"
        rm -rf "$FW.dSYM"
        xcrun dsymutil "$FW/chanora_bridge" -o "$FW.dSYM"
        xcrun strip -S -x "$FW/chanora_bridge"
        echo "[chanora_bridge script_phase] framework refreshed (with dSYM)"
      fi

      # Publish the dSYM into Xcode's archive dSYM folder on every
      # build (cached or not). Without this the archive validator
      # fails with "archive did not include a dSYM for the
      # chanora_bridge.framework with the UUIDs [<uuid>]" and the
      # IPA cannot be uploaded to App Store Connect / TestFlight.
      # ${DWARF_DSYM_FOLDER_PATH} resolves to <ARCHIVE>/dSYMs for
      # archive builds and <BUILT_PRODUCTS_DIR> otherwise; both paths
      # are the ones xcodebuild scans when collecting symbols.
      if [ -n "${DWARF_DSYM_FOLDER_PATH:-}" ] && [ -d "$FW.dSYM" ]; then
        mkdir -p "$DWARF_DSYM_FOLDER_PATH"
        rm -rf "$DWARF_DSYM_FOLDER_PATH/chanora_bridge.framework.dSYM"
        cp -R "$FW.dSYM" "$DWARF_DSYM_FOLDER_PATH/chanora_bridge.framework.dSYM"
        echo "[chanora_bridge script_phase] dSYM published to $DWARF_DSYM_FOLDER_PATH"
      fi
    SCRIPT
    :execution_position => :before_compile,
  }

  # The pod has no Objective-C sources; it's purely a framework
  # carrier. Suppress CocoaPods's source-file warning.
  s.source_files = 'Frameworks/chanora_bridge.framework/Headers/*.h'

  # No public Swift / ObjC API to expose — the Flutter app talks to
  # the framework via FRB's FFI symbol lookup at runtime, not via
  # imports.
end
