package com.example.offlinestore1

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.Gravity
import android.view.View
import android.widget.EditText
import android.widget.HorizontalScrollView
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File
import java.util.concurrent.ConcurrentHashMap
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {

    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: AppAdapter
    private lateinit var edtSearch: EditText
    private lateinit var prefs: PreferencesHelper
    private lateinit var chipsContainer: LinearLayout
    private lateinit var swipeRefresh: SwipeRefreshLayout
    private lateinit var btnToggleView: ImageButton
    private lateinit var horizontalScrollView: HorizontalScrollView

    private var allApps: MutableList<AppModel> = mutableListOf()
    private var visibleApps: MutableList<AppModel> = mutableListOf()
    private var selectedCategory: String = "הכל"
    private var isGrid = false

    private val gson = Gson()
    private val CACHE_KEY = "apps_cache"

    private val sessionToPackageMap = ConcurrentHashMap<Int, String>()

    private val installerCallback = object : PackageInstaller.SessionCallback() {
        override fun onCreated(sessionId: Int) {}
        override fun onBadgingChanged(sessionId: Int) {}
        override fun onActiveChanged(sessionId: Int, active: Boolean) {}
        override fun onProgressChanged(sessionId: Int, progress: Float) {}
        override fun onFinished(sessionId: Int, success: Boolean) {
            sessionToPackageMap.remove(sessionId)
        }
    }

    private val installResultReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action != InstallReceiver.ACTION_INSTALL_RESULT) return

            val packageName = intent.getStringExtra(InstallReceiver.EXTRA_PACKAGE_NAME).orEmpty()
            val operation = intent.getStringExtra(InstallReceiver.EXTRA_OPERATION).orEmpty()
            val success = intent.getBooleanExtra("success", false)

            if (packageName.isBlank()) return

            if (operation == "install") {
                updateAppState(packageName, success, "idle", 0, "")
            } else if (operation == "uninstall") {
                updateAppState(packageName, !success, "idle", 0, "")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        prefs = PreferencesHelper(this)
        isGrid = prefs.isGridMode()

        recyclerView = findViewById(R.id.recyclerViewApps)
        edtSearch = findViewById(R.id.edtSearch)
        chipsContainer = findViewById(R.id.chipsContainer)
        swipeRefresh = findViewById(R.id.swipeRefresh)
        
        val container = findViewById<LinearLayout>(R.id.chipsContainer)
        horizontalScrollView = container.parent as HorizontalScrollView

        val btnSettings = findViewById<ImageButton>(R.id.btnSettings)
        btnToggleView = findViewById<ImageButton>(R.id.btnToggleView)

        updateToggleIcon()

        btnSettings.setOnClickListener {
            it.startClickAnimation()
            val intent = Intent(this, SettingsActivity::class.java)
            startActivity(intent)
        }

        btnToggleView.setOnClickListener {
            it.startClickAnimation()
            isGrid = !isGrid
            prefs.saveViewMode(isGrid)
            applyLayoutManager()
            rebuildAdapter()
            updateToggleIcon()
            recyclerView.scheduleLayoutAnimation()
        }

        swipeRefresh.setOnRefreshListener {
            loadApps()
        }

        swipeRefresh.setColorSchemeColors(resources.getColor(R.color.primary, theme))

        edtSearch.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                applyFilters()
            }
            override fun afterTextChanged(s: Editable?) {}
        })

        applyLayoutManager()
        
        // טעינה מהירה מה-Cache בשרשור נפרד כדי לא לתקוע את ה-UI
        thread {
            loadFromCache()
        }
        loadApps()
        
        packageManager.packageInstaller.registerSessionCallback(installerCallback)
    }

    private fun updateToggleIcon() {
        if (isGrid) {
            btnToggleView.setImageResource(R.drawable.ic_list)
        } else {
            btnToggleView.setImageResource(R.drawable.ic_grid)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        try {
            packageManager.packageInstaller.unregisterSessionCallback(installerCallback)
        } catch (_: Exception) {}
    }

    override fun onResume() {
        super.onResume()
        if (prefs.hasPassword() && !LoginActivity.isAuthenticated) {
            val intent = Intent(this, LoginActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
            startActivity(intent)
            finish()
            return
        }
        refreshInstalledStates()
    }

    override fun onStart() {
        super.onStart()
        LoginActivity.runningActivities++

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(
                installResultReceiver,
                IntentFilter(InstallReceiver.ACTION_INSTALL_RESULT),
                Context.RECEIVER_NOT_EXPORTED
            )
        } else {
            @Suppress("DEPRECATION")
            registerReceiver(
                installResultReceiver,
                IntentFilter(InstallReceiver.ACTION_INSTALL_RESULT)
            )
        }
    }

    override fun onStop() {
        super.onStop()
        LoginActivity.runningActivities--
        if (LoginActivity.runningActivities <= 0) {
            LoginActivity.isAuthenticated = false
        }
        try {
            unregisterReceiver(installResultReceiver)
        } catch (_: Exception) {
        }
    }

    private fun applyLayoutManager() {
        recyclerView.layoutManager = if (isGrid) {
            GridLayoutManager(this, 2)
        } else {
            LinearLayoutManager(this)
        }
    }

    private fun rebuildAdapter() {
        adapter = AppAdapter(
            appList = visibleApps,
            isGridMode = isGrid,
            onPrimaryClick = { app ->
                if (app.isInstalled) {
                    openApp(app.packageName)
                } else {
                    updateAppState(
                        packageName = app.packageName,
                        isInstalled = false,
                        installState = "copying",
                        progress = 0,
                        statusText = "מכין אפליקציה להתקנה..."
                    )
                    silentInstall(app)
                }
            },
            onUninstallClick = { app ->
                confirmUninstall(app)
            }
        )
        recyclerView.adapter = adapter
    }

    private fun loadApps() {
        swipeRefresh.isRefreshing = true
        thread {
            val apps = scanAllApks("/system/app-data/")
            saveToCache(apps)
            runOnUiThread {
                allApps.clear()
                allApps.addAll(apps)
                buildCategoryChips()
                applyFilters()
                rebuildAdapter()
                recyclerView.scheduleLayoutAnimation()
                swipeRefresh.isRefreshing = false
                
                horizontalScrollView.post {
                    horizontalScrollView.fullScroll(View.FOCUS_RIGHT)
                }
            }
        }
    }

    private fun scanAllApks(rootPath: String): List<AppModel> {
        val list = mutableListOf<AppModel>()
        val rootDir = File(rootPath)
        val pm = packageManager

        if (!rootDir.exists() || !rootDir.isDirectory) return emptyList()

        rootDir.listFiles()
            ?.filter { it.isDirectory }
            ?.forEach { categoryDir ->
                categoryDir.listFiles { _, name -> name.endsWith(".apk", ignoreCase = true) }
                    ?.forEach { file ->
                        try {
                            val info = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                                pm.getPackageArchiveInfo(
                                    file.absolutePath,
                                    PackageManager.PackageInfoFlags.of(0)
                                )
                            } else {
                                @Suppress("DEPRECATION")
                                pm.getPackageArchiveInfo(file.absolutePath, 0)
                            }

                            info?.applicationInfo?.let { appInfo ->
                                val pkgName = info.packageName
                                val verCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                                    info.longVersionCode.toInt()
                                } else {
                                    @Suppress("DEPRECATION")
                                    info.versionCode
                                }

                                appInfo.sourceDir = file.absolutePath
                                appInfo.publicSourceDir = file.absolutePath
                                
                                val installedVer = getInstalledVersionCode(pm, pkgName)

                                list.add(
                                    AppModel(
                                        name = appInfo.loadLabel(pm).toString(),
                                        icon = appInfo.loadIcon(pm),
                                        packageName = pkgName,
                                        apkFile = file,
                                        isInstalled = installedVer != -1,
                                        category = categoryDir.name,
                                        sizeText = AppModel.formatSize(file.length()),
                                        installState = "idle",
                                        progress = 0,
                                        statusText = "",
                                        versionCode = verCode,
                                        installedVersionCode = installedVer
                                    )
                                )
                            }
                        } catch (_: Exception) {
                        }
                    }
            }

        return list
            .groupBy { it.packageName.lowercase() }
            .map { entry -> entry.value.maxBy { it.versionCode } }
            .sortedBy { it.name.lowercase() }
    }

    private fun saveToCache(apps: List<AppModel>) {
        val json = gson.toJson(apps)
        getSharedPreferences("offline_store_cache", MODE_PRIVATE)
            .edit()
            .putString(CACHE_KEY, json)
            .apply()
    }

    private fun loadFromCache() {
        val json = getSharedPreferences("offline_store_cache", MODE_PRIVATE)
            .getString(CACHE_KEY, null) ?: return

        try {
            val type = object : TypeToken<List<AppModel>>() {}.type
            val cachedApps: List<AppModel> = gson.fromJson(json, type)
            
            val pm = packageManager
            cachedApps.forEach { app ->
                app.installedVersionCode = getInstalledVersionCode(pm, app.packageName)
                app.isInstalled = app.installedVersionCode != -1
            }

            runOnUiThread {
                allApps.clear()
                allApps.addAll(cachedApps)
                buildCategoryChips()
                applyFilters()
                rebuildAdapter()
            }
        } catch (_: Exception) {}
    }

    private fun getInstalledVersionCode(pm: PackageManager, packageName: String): Int {
        return try {
            val info = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                pm.getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))
            } else {
                @Suppress("DEPRECATION")
                pm.getPackageInfo(packageName, 0)
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) info.longVersionCode.toInt() else @Suppress("DEPRECATION") info.versionCode
        } catch (_: Exception) { -1 }
    }

    private fun buildCategoryChips() {
        chipsContainer.removeAllViews()

        val categories = mutableListOf("הכל")
        categories.addAll(allApps.map { it.category }.distinct().sorted())

        categories.forEach { category ->
            val isSelected = category == selectedCategory
            val chip = TextView(this).apply {
                text = category
                textSize = 14f
                gravity = Gravity.CENTER
                
                background = getDrawable(if (isSelected) R.drawable.bg_chip_selected else R.drawable.bg_chip)
                setTextColor(if (isSelected) Color.parseColor("#4F46E5") else Color.parseColor("#475569"))
                
                val horizontalPx = 16.toPx()
                val verticalPx = 6.toPx()
                setPadding(horizontalPx, verticalPx, horizontalPx, verticalPx)

                setOnClickListener {
                    it.startClickAnimation()
                    selectedCategory = category
                    buildCategoryChips()
                    applyFilters()
                    recyclerView.scheduleLayoutAnimation()
                }
            }

            val params = LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
            )
            params.marginStart = 6.toPx()
            params.topMargin = 2.toPx()
            params.bottomMargin = 2.toPx()
            chip.layoutParams = params

            chipsContainer.addView(chip)
        }
    }

    private fun Int.toPx(): Int = (this * resources.displayMetrics.density).toInt()

    private fun applyFilters() {
        val q = edtSearch.text.toString().trim().lowercase()

        visibleApps.clear()
        visibleApps.addAll(
            allApps.filter { app ->
                val categoryOk = selectedCategory == "הכל" || app.category == selectedCategory
                val textOk =
                    q.isEmpty() ||
                            app.name.lowercase().contains(q) ||
                            app.packageName.lowercase().contains(q) ||
                            app.category.lowercase().contains(q)

                categoryOk && textOk
            }
        )

        if (::adapter.isInitialized) {
            adapter.notifyDataSetChanged()
        }
    }

    private fun refreshInstalledStates() {
        val pm = packageManager
        allApps.forEach { app ->
            app.installedVersionCode = getInstalledVersionCode(pm, app.packageName)
            app.isInstalled = app.installedVersionCode != -1
            if (app.installState != "idle") {
                app.installState = "idle"
                app.progress = 0
                app.statusText = ""
            }
        }
        applyFilters()
    }

    private fun updateAppState(
        packageName: String,
        isInstalled: Boolean,
        installState: String,
        progress: Int,
        statusText: String
    ) {
        runOnUiThread {
            allApps.find { it.packageName == packageName }?.let { app ->
                app.isInstalled = isInstalled
                app.installState = installState
                app.progress = progress
                app.statusText = statusText
                if (isInstalled) {
                    app.installedVersionCode = getInstalledVersionCode(packageManager, packageName)
                } else if (installState == "idle") {
                    app.installedVersionCode = -1
                }

                visibleApps.find { it.packageName == packageName }?.let { vApp ->
                    vApp.isInstalled = isInstalled
                    vApp.installState = installState
                    vApp.progress = progress
                    vApp.statusText = statusText
                    if (::adapter.isInitialized) {
                        adapter.notifyItemChanged(visibleApps.indexOf(vApp))
                    }
                }
            }
        }
    }

    private fun openApp(packageName: String) {
        val intent = packageManager.getLaunchIntentForPackage(packageName)
        if (intent != null) {
            startActivity(intent)
        } else {
            Toast.makeText(this, "לא ניתן לפתוח את האפליקציה", Toast.LENGTH_SHORT).show()
        }
    }

    private fun silentInstall(app: AppModel) {
        thread {
            val apkFile = app.apkFile
            val installer = packageManager.packageInstaller
            val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                params.setRequireUserAction(PackageInstaller.SessionParams.USER_ACTION_NOT_REQUIRED)
            }

            try {
                val sessionId = installer.createSession(params)
                val session = installer.openSession(sessionId)
                sessionToPackageMap[sessionId] = app.packageName

                updateAppState(
                    packageName = app.packageName,
                    isInstalled = false,
                    installState = "copying",
                    progress = 0,
                    statusText = "מכין התקנה..."
                )

                apkFile.inputStream().use { input ->
                    session.openWrite("package_install", 0, apkFile.length()).use { output ->
                        val buffer = ByteArray(65536)
                        var total = 0L
                        var read: Int

                        while (input.read(buffer).also { read = it } != -1) {
                            output.write(buffer, 0, read)
                            total += read
                        }
                        session.fsync(output)
                    }
                }

                updateAppState(
                    packageName = app.packageName,
                    isInstalled = false,
                    installState = "installing",
                    progress = 0,
                    statusText = "מתקין..."
                )

                val intent = Intent(this, InstallReceiver::class.java).apply {
                    putExtra(InstallReceiver.EXTRA_PACKAGE_NAME, app.packageName)
                    putExtra(InstallReceiver.EXTRA_OPERATION, "install")
                }

                val pendingIntent = PendingIntent.getBroadcast(
                    this,
                    sessionId,
                    intent,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
                )

                session.commit(pendingIntent.intentSender)
                session.close()

            } catch (e: Exception) {
                updateAppState(
                    packageName = app.packageName,
                    isInstalled = false,
                    installState = "idle",
                    progress = 0,
                    statusText = ""
                )
                runOnUiThread {
                    Toast.makeText(this, "שגיאה בהתקנה: ${e.message}", Toast.LENGTH_LONG).show()
                }
            }
        }
    }

    private fun confirmUninstall(app: AppModel) {
        AlertDialog.Builder(this)
            .setTitle("הסרת אפליקציה")
            .setMessage("האם אתה בטוח שברצונך להסיר את ${app.name}?")
            .setPositiveButton("הסר") { _, _ ->
                uninstallPackage(app)
            }
            .setNegativeButton("ביטול", null)
            .show()
    }

    private fun uninstallPackage(app: AppModel) {
        try {
            val installer = packageManager.packageInstaller
            val intent = Intent(this, InstallReceiver::class.java).apply {
                putExtra(InstallReceiver.EXTRA_PACKAGE_NAME, app.packageName)
                putExtra(InstallReceiver.EXTRA_OPERATION, "uninstall")
            }

            val pendingIntent = PendingIntent.getBroadcast(
                this,
                app.packageName.hashCode(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
            )

            installer.uninstall(app.packageName, pendingIntent.intentSender)

            updateAppState(
                packageName = app.packageName,
                isInstalled = true,
                installState = "installing",
                progress = 0,
                statusText = "מסיר..."
            )

        } catch (e: Exception) {
            Toast.makeText(this, "שגיאה בהסרה: ${e.message}", Toast.LENGTH_LONG).show()
        }
    }
}
