package com.ledgrab.android

import android.app.Application
import android.util.Log
import com.chaquo.python.Python
import com.chaquo.python.android.AndroidPlatform
import java.io.File
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * Application class — initializes the Chaquopy Python runtime and
 * installs a global uncaught exception handler that persists crash
 * logs to app-private storage.
 *
 * `Python.start()` must be called once before any Python code runs.
 * It loads libpython, extracts stdlib + pip packages from APK assets
 * (first launch only), and sets up `sys.path`.
 */
class LedGrabApp : Application() {

    /** Set if [Python.start] threw — surfaced by MainActivity. */
    @Volatile
    var initError: Throwable? = null
        private set

    override fun onCreate() {
        super.onCreate()
        installCrashLogger()
        try {
            if (!Python.isStarted()) {
                Python.start(AndroidPlatform(this))
            }
        } catch (t: Throwable) {
            // Don't crash here — MainActivity will render a failure
            // screen with a Copy log button so the user can report it.
            Log.e(TAG, "Python.start() failed", t)
            initError = t
            return
        }
        // Bind application context for the USB-serial bridge so Python
        // can enumerate and open USB-to-TTL adapters without needing
        // an Activity reference.
        UsbSerialBridge.init(this)
        // Bind application context for the BLE bridge so Python can
        // scan and connect to BLE LED controllers.
        BleBridge.init(this)
    }

    /**
     * Install a global uncaught exception handler that writes the
     * stack trace to `files/crash-<timestamp>.log` before letting
     * the default handler terminate the process.  Logs survive app
     * restarts and can be pulled via `adb pull` for diagnostics.
     */
    private fun installCrashLogger() {
        val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            try {
                val ts = SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US).format(Date())
                val logFile = File(filesDir, "crash-$ts.log")
                PrintWriter(logFile).use { pw ->
                    pw.println("LedGrab crash at $ts")
                    pw.println("Thread: ${thread.name}")
                    pw.println()
                    throwable.printStackTrace(pw)
                }
                Log.e(TAG, "Crash log written to ${logFile.absolutePath}")
            } catch (_: Exception) {
                // Best effort — don't crash inside the crash handler.
            }
            // Chain to the default handler so Android shows the crash dialog
            // and terminates the process.
            defaultHandler?.uncaughtException(thread, throwable)
        }
    }

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