package top.yeij.cyrene

import android.Manifest
import android.app.Activity
import android.app.Application
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings
import android.util.Log
import androidx.core.content.ContextCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.GlobalContext
import org.koin.core.context.startKoin
import top.yeij.cyrene.data.local.PreferencesDataStore
import top.yeij.cyrene.data.remote.AuthInterceptor
import top.yeij.cyrene.data.remote.DynamicUrlInterceptor
import top.yeij.cyrene.data.repository.ChatRepositoryImpl
import top.yeij.cyrene.di.appModule
import top.yeij.cyrene.service.KeepAliveReceiver
import top.yeij.cyrene.util.RootKeepAliveHelper
import top.yeij.cyrene.util.RuntimeLog
import java.util.concurrent.atomic.AtomicInteger

class CyreneApplication : Application() {

    private val initScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    private val activityCount = AtomicInteger(0)

    override fun onCreate() {
        super.onCreate()
        RuntimeLog.general("app", "Application onCreate")

        startKoin {
            androidContext(this@CyreneApplication)
            modules(appModule)
        }

        // Track foreground/background state
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityResumed(activity: Activity) {
                if (activityCount.incrementAndGet() == 1) {
                    RuntimeLog.general("app", "App in foreground")
                    getRepo()?.cancelNotifications()
                    getRepo()?.onAppForeground()
                }
            }

            override fun onActivityPaused(activity: Activity) {
                if (activityCount.decrementAndGet() == 0) {
                    RuntimeLog.general("app", "App in background")
                    getRepo()?.onAppBackground()
                }
            }

            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
            override fun onActivityStarted(activity: Activity) {}
            override fun onActivityStopped(activity: Activity) {}
            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
            override fun onActivityDestroyed(activity: Activity) {}
        })

        initScope.launch {
            val koin = GlobalContext.get()
            val prefs: PreferencesDataStore = koin.get()
            val urlInterceptor: DynamicUrlInterceptor = koin.get()
            val authInterceptor: AuthInterceptor = koin.get()

            prefs.baseUrl.firstOrNull()?.let { url ->
                if (url.isNotBlank()) urlInterceptor.baseUrl = url
            }
            prefs.token.firstOrNull()?.let { token ->
                authInterceptor.token = token
            }
        }

        // Schedule periodic keep-alive on first launch
        scheduleInitialKeepAlive()

        // Check battery optimization
        checkBatteryOptimization()

        // Apply root keep-alive if enabled
        initScope.launch {
            val koin = GlobalContext.get()
            val prefs: PreferencesDataStore = koin.get()
            val enabled = prefs.rootKeepAlive.firstOrNull() ?: false
            if (enabled) {
                val ok = RootKeepAliveHelper.applyRootKeepAlive(packageName)
                if (ok) {
                    RuntimeLog.general("app", "Root keep-alive re-applied on boot")
                } else if (RootKeepAliveHelper.isRootAvailable()) {
                    RuntimeLog.general("app", "Root keep-alive re-apply failed despite root being available")
                }
                // Only attempt system wakelock if root keep-alive was enabled
                // We don't persist the wakelock across reboots since it's per-session
            }
        }
    }

    private fun scheduleInitialKeepAlive() {
        try {
            KeepAliveReceiver.schedule(this)
            RuntimeLog.general("app", "Initial keep-alive alarm scheduled")
        } catch (e: Exception) {
            Log.e(TAG, "Failed to schedule initial keep-alive: ${e.message}")
        }
    }

    private fun checkBatteryOptimization() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val pm = getSystemService(PowerManager::class.java)
            if (pm?.isIgnoringBatteryOptimizations(packageName) == false) {
                Log.i(TAG, "App is NOT exempt from battery optimization")
                // Note: we can't request exemption from Application context directly.
                // SettingsScreen should offer a button to open the exemption dialog.
            }
        }
    }

    private fun getRepo(): ChatRepositoryImpl? {
        return try {
            GlobalContext.get().get()
        } catch (_: Throwable) {
            null
        }
    }

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