package com.dronex.rec

import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.BatteryManager
import android.os.Build
import android.os.Environment
import android.os.StatFs
import android.provider.Settings
import com.dronex.rec.recording.RecordingPlatformHandler
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private var platformHandler: RecordingPlatformHandler? = null
    private var platformInfoChannel: MethodChannel? = null

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        platformInfoChannel =
                MethodChannel(
                                flutterEngine.dartExecutor.binaryMessenger,
                                AppConstants.PLATFORM_INFO_CHANNEL,
                        )
                        .also { channel ->
                            channel.setMethodCallHandler { call, result ->
                                when (call.method) {
                                    "packageInfo" -> result.success(packageInfoMap())
                                    "deviceInfo" -> result.success(deviceInfoMap())
                                    "deviceHealth" -> result.success(deviceHealthMap())
                                    else -> result.notImplemented()
                                }
                            }
                        }

        platformHandler =
                RecordingPlatformHandler(
                        this,
                        flutterEngine.dartExecutor.binaryMessenger,
                )
    }

    override fun onDestroy() {
        platformInfoChannel?.setMethodCallHandler(null)
        platformInfoChannel = null
        platformHandler?.dispose()
        platformHandler = null
        super.onDestroy()
    }

    private fun packageInfoMap(): Map<String, String> {
        val packageInfo =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    packageManager.getPackageInfo(
                            packageName,
                            android.content.pm.PackageManager.PackageInfoFlags.of(0),
                    )
                } else {
                    @Suppress("DEPRECATION") packageManager.getPackageInfo(packageName, 0)
                }

        val appName = applicationInfo.loadLabel(packageManager)?.toString().orEmpty()
        val versionCode =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    packageInfo.longVersionCode.toString()
                } else {
                    @Suppress("DEPRECATION") packageInfo.versionCode.toString()
                }

        return mapOf(
                "appName" to appName,
                "packageName" to packageName,
                "version" to packageInfo.versionName.orEmpty(),
                "buildNumber" to versionCode,
        )
    }

    private fun deviceInfoMap(): Map<String, Any> {
        val flags = applicationInfo.flags
        val isEmulator =
                Build.FINGERPRINT.startsWith("generic") ||
                        Build.FINGERPRINT.startsWith("unknown") ||
                        Build.MODEL.contains("google_sdk") ||
                        Build.MODEL.contains("Emulator") ||
                        Build.MODEL.contains("Android SDK built for x86") ||
                        Build.MANUFACTURER.contains("Genymotion") ||
                        Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic") ||
                        Build.PRODUCT == "google_sdk" ||
                        flags and ApplicationInfo.FLAG_DEBUGGABLE != 0 &&
                                Build.HARDWARE.contains("ranchu")

        return mapOf(
                "platform" to "android",
                "deviceCode" to Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID).orEmpty(),
                "brand" to Build.BRAND,
                "model" to Build.MODEL,
                "systemVersion" to Build.VERSION.RELEASE,
                "sdkInt" to Build.VERSION.SDK_INT,
                "isPhysicalDevice" to !isEmulator,
        )
    }

    private fun deviceHealthMap(): Map<String, Any?> {
        val batteryLevelPercent = readBatteryLevelPercent()
        val storageAvailablePercent = readStorageAvailablePercent()
        return mapOf(
                "batteryLevelPercent" to batteryLevelPercent,
                "storageAvailablePercent" to storageAvailablePercent,
        )
    }

    private fun readBatteryLevelPercent(): Int? {
        val batteryManager = getSystemService(Context.BATTERY_SERVICE) as? BatteryManager
                ?: return null
        val level =
                batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
        return if (level in 0..100) level else null
    }

    private fun readStorageAvailablePercent(): Double {
        val stat = StatFs(Environment.getDataDirectory().path)
        val totalBytes = stat.totalBytes
        if (totalBytes <= 0L) return 100.0
        val availableBytes = stat.availableBytes
        return availableBytes.toDouble() / totalBytes.toDouble() * 100.0
    }
}
