package ir.mnpc.rasadyar

import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.core.content.FileProvider
import java.io.File
import androidx.core.net.toUri


class ApkInstaller(private val context: Context) {

    var pendingApkFile: File? = null

    companion object {
        const val INSTALL_REQUEST_CODE = 1001
        const val INSTALL_PERMISSION_REQUEST_CODE =2001

    }

    /**
     * Install APK with compatibility for Android 5-15
     */
    fun installApk(apkFile: File) {
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                // Android 8+ (API 26+) - Use PackageInstaller API
                installWithFileProvider(apkFile)
            }

            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> {
                // Android 7+ (API 24+) - Use FileProvider with Intent
                installWithFileProvider(apkFile)
            }

            else -> {
                // Android 5-6 (API 21-23) - Use file URI with Intent
                installWithFileUri(apkFile)
            }
        }
    }

    /**
     * Android 8+ (API 26+) - PackageInstaller API
     */
    private fun installWithPackageInstaller(apkFile: File) {
        try {
            val packageInstaller = context.packageManager.packageInstaller
            val params = PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL
            )

            // Set installer package name for better tracking
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                params.setInstallReason(PackageManager.INSTALL_REASON_USER)
            }

            val sessionId = packageInstaller.createSession(params)
            val session = packageInstaller.openSession(sessionId)

            session.use { activeSession ->
                apkFile.inputStream().use { inputStream ->
                    activeSession.openWrite("package", 0, apkFile.length()).use { outputStream ->
                        inputStream.copyTo(outputStream)
                        activeSession.fsync(outputStream)
                    }
                }

                val intent = Intent(context, InstallResultReceiver::class.java).apply {
                    action = "${context.packageName}.INSTALL_RESULT"
                }

                val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
                } else {
                    PendingIntent.FLAG_UPDATE_CURRENT
                }

                val pendingIntent = PendingIntent.getBroadcast(
                    context, 0, intent, flags
                )

                activeSession.commit(pendingIntent.intentSender)
            }
        } catch (e: Exception) {
            // Fallback to intent method
            installWithFileProvider(apkFile)
        }
    }

    /**
     * Android 7+ (API 24+) - FileProvider with Intent
     */
    private fun installWithFileProvider(apkFile: File) {
        try {
            val apkUri = FileProvider.getUriForFile(
                context,
                "${context.packageName}.fileprovider",
                apkFile
            )

            val intent = createInstallIntent(apkUri).apply {
                flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK

                // Additional flags for better compatibility
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
                    putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, context.packageName)
                }
            }

            if (context is Activity) {
                context.startActivityForResult(intent, INSTALL_REQUEST_CODE)
            } else {
                context.startActivity(intent)
            }
        } catch (e: Exception) {

            // Final fallback for Android 7+
            installWithFileUri(apkFile)
        }
    }

    /**
     * Android 5-6 (API 21-23) - File URI with Intent
     */
    private fun installWithFileUri(apkFile: File) {
        try {
            val apkUri = Uri.fromFile(apkFile)
            val intent = createInstallIntent(apkUri).apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK
            }

            if (context is Activity) {
                context.startActivityForResult(intent, INSTALL_REQUEST_CODE)
            } else {
                context.startActivity(intent)
            }
        } catch (e: Exception) {

        }
    }

    /**
     * Create appropriate install intent based on Android version
     */
    private fun createInstallIntent(uri: Uri): Intent {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
                data = uri
            }
        } else {
            Intent(Intent.ACTION_VIEW).apply {
                setDataAndType(uri, "application/vnd.android.package-archive")
            }
        }
    }

    /**
     * Check if installation from unknown sources is allowed
     */
    fun canInstallPackages(): Boolean {
        return when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                context.packageManager.canRequestPackageInstalls()
            }

            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
                try {
                    Settings.Secure.getInt(
                        context.contentResolver,
                        Settings.Secure.INSTALL_NON_MARKET_APPS
                    ) == 1
                } catch (e: Settings.SettingNotFoundException) {
                    false
                }
            }

            else -> {
                // For older versions, assume it's allowed
                true
            }
        }
    }

    /**
     * Request permission to install packages
     */
    fun requestInstallPermission(activity: Activity) {
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                if (!activity.packageManager.canRequestPackageInstalls()) {
                    val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
                        data = "package:${activity.packageName}".toUri()
                    }
                    activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE)
                }
            }

            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
                val intent = Intent(Settings.ACTION_SECURITY_SETTINGS)
                activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE)
            }
        }
    }



}

class InstallResultReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) {
            PackageInstaller.STATUS_SUCCESS -> {
                Log.d("InstallResult", "Installation successful")
                // Handle successful installation
                Toast.makeText(context, "Installation successful", Toast.LENGTH_SHORT).show()
            }

            PackageInstaller.STATUS_FAILURE -> {
                val message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
                Log.e("InstallResult", "Installation failed: $message")
                Toast.makeText(context, "Installation failed: $message", Toast.LENGTH_LONG).show()
            }

            PackageInstaller.STATUS_FAILURE_BLOCKED -> {
                Log.e("InstallResult", "Installation blocked")
                Toast.makeText(context, "Installation blocked by system", Toast.LENGTH_LONG).show()
            }

            PackageInstaller.STATUS_FAILURE_ABORTED -> {
                Log.e("InstallResult", "Installation aborted")
                Toast.makeText(context, "Installation was cancelled", Toast.LENGTH_SHORT).show()
            }

            PackageInstaller.STATUS_FAILURE_INVALID -> {
                Log.e("InstallResult", "Invalid APK")
                Toast.makeText(context, "Invalid APK file", Toast.LENGTH_LONG).show()
            }

            PackageInstaller.STATUS_FAILURE_CONFLICT -> {
                Log.e("InstallResult", "Installation conflict")
                Toast.makeText(
                    context,
                    "Installation conflict with existing app",
                    Toast.LENGTH_LONG
                ).show()
            }

            PackageInstaller.STATUS_FAILURE_STORAGE -> {
                Log.e("InstallResult", "Insufficient storage")
                Toast.makeText(context, "Insufficient storage space", Toast.LENGTH_LONG).show()
            }

            PackageInstaller.STATUS_FAILURE_INCOMPATIBLE -> {
                Log.e("InstallResult", "Incompatible app")
                Toast.makeText(context, "App is incompatible with device", Toast.LENGTH_LONG).show()
            }

            else -> {
                Log.w("InstallResult", "Unknown status: $status")
            }
        }
    }
}