package app.chanora.chanora_flutter

import android.app.Application
import android.util.Log

/**
 * Application subclass that owns the earliest-possible load of the
 * `chanora_bridge` native cdylib.
 *
 * Trace: SDD-105 (AndroidJniBootstrap), DEC-004 (single JavaVM* capture point).
 *
 * Rationale (SDD-105):
 *   `JNI_OnLoad` in `crates/chanora_bridge/src/android_init.rs` captures the
 *   process-wide `JavaVM*` the first time the library is loaded. By performing
 *   the `System.loadLibrary("chanora_bridge")` call here in `Application.onCreate`
 *   we guarantee that the VM pointer is available *before* any Flutter plugin,
 *   background isolate, or FRB-generated stub attempts to call into Rust. This
 *   also ensures the load happens on the main thread, satisfying the threading
 *   guarantee documented in SDD-105.
 *
 * Manifest contract (Wave 2B-1):
 *   AndroidManifest.xml must reference this class via
 *     android:name="app.chanora.chanora_flutter.ChanoraApplication"
 *   in the <application> tag. Wave 2B-1 owns that edit; do not duplicate it
 *   here.
 */
class ChanoraApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        // SDD-105: load the native bridge as early as possible so JNI_OnLoad
        // runs before any FRB call site is reached.
        try {
            // SDD-105 implementation detail: the Android NDK C++ runtime
            // (libc++_shared.so) must be loaded BEFORE chanora_bridge so that
            // chanora_bridge's undefined C++ symbols (notably
            // __cxa_pure_virtual, __cxa_atexit) resolve via the global
            // symbol namespace. libchanora_bridge.so does not carry a
            // DT_NEEDED libc++_shared.so entry today (the Rust cdylib build
            // does not emit one), so the loader will not auto-pull it just
            // because it is co-located in jniLibs/<abi>/. This explicit
            // ordered loadLibrary pair is the canonical NDK pattern.
            // Follow-up: a cleaner build-side fix is to inject
            // `-lc++_shared` into the Rust cdylib link args via
            // cargo:rustc-link-lib in a build.rs, producing a DT_NEEDED
            // entry that makes this manual ordering unnecessary.
            System.loadLibrary("c++_shared")
            System.loadLibrary("chanora_bridge")
        } catch (t: UnsatisfiedLinkError) {
            // SDD-105: panic-safe FFI boundary — log loudly, then rethrow so
            // the process fails fast rather than silently running without the
            // Rust core. A swallowed link error would manifest much later as
            // a confusing UnsatisfiedLinkError on the first FRB call.
            Log.e(TAG, "Failed to load native library", t)
            throw t
        }
    }

    companion object {
        private const val TAG = "ChanoraApp"
    }
}
