package com.zxhyis.toolss.ui.page.appmanager

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.View
import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.zxhyis.toolss.R
import com.zxhyis.toolss.ad.AdmobUtils
import com.zxhyis.toolss.ad.EventHelper
import com.zxhyis.toolss.databinding.ActivityAppManager2Binding
import com.zxhyis.toolss.logic.ActivityLauncher
import com.zxhyis.toolss.logic.AppBean
import com.zxhyis.toolss.logic.InstallEx.isInstalled
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.logic.ReportInterface
import com.zxhyis.toolss.logic.setOnClick
import com.zxhyis.toolss.ui.page.appmanager.AppListFragment.Companion.APP_LIST_TYPE_INSTALL
import com.zxhyis.toolss.ui.page.appmanager.AppListFragment.Companion.APP_LIST_TYPE_LAST_USE
import com.zxhyis.toolss.ui.page.appmanager.AppListFragment.Companion.APP_LIST_TYPE_NAME
import com.zxhyis.toolss.ui.page.appmanager.AppListFragment.Companion.APP_LIST_TYPE_SIZE
import com.zxhyis.toolss.ui.page.appmanager.UsageAccessSettings.checkUsageAccessSettings
import com.zxhyis.toolss.ui.page.viewmodel.AppViewModel
import com.zxhyis.toolss.ui.page.viewmodel.AppViewModel.Companion.THIRTY_DAYS_QUERY
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.internal.wait
import java.util.concurrent.LinkedBlockingDeque


/**
 */
class AppManager2Activity : AppCompatActivity(), ReportInterface {

    private lateinit var launcher: ActivityLauncher
    private lateinit var binding: ActivityAppManager2Binding
    private val dataList = ArrayList<AppBean>()
    private val pages = arrayListOf<Fragment>()
    private lateinit var pagerAdapter: ScreenSlidePagerAdapter
    private val TAG: String = "AppManager2Activity"
    private var currentPosition: Int = 0
    private lateinit var context: Context
    private val viewModel: AppViewModel by viewModels()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        context = this
        launcher = ActivityLauncher(this)
        binding = ActivityAppManager2Binding.inflate(layoutInflater)
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        initViewPager()
        playlottie()
        CoroutineScope(Dispatchers.Main).launch {

            initAppData()

            if (checkUsageAccessSettings()) {
                async(Dispatchers.IO) {
                    setAppBeanSize()
                    setAppLastUseTime()
                }.await()
            }

            pages.forEachIndexed { index, fragment ->
                val appListFragment = (fragment as AppListFragment)
                appListFragment.refreshFragmentData(dataList, index == currentPosition, index)
            }
        }

        binding.llName.setOnClick(javaClass.simpleName) {
            if (currentPosition == 0) {
                val fragment = (pages[0] as AppListFragment)
                fragment.reverseOrder()
                val isAsc = fragment.isAsc
                changeAsc(0, isAsc)
            }
            binding.viewpager2.setCurrentItem(0, false)
        }
        binding.llInstall.setOnClick(javaClass.simpleName) {
            if (currentPosition == 1) {
                val fragment = (pages[1] as AppListFragment)
                fragment.reverseOrder()
                val isAsc = fragment.isAsc
                changeAsc(1, isAsc)
            }
            binding.viewpager2.setCurrentItem(1, false)
        }
        binding.llSize.setOnClick(javaClass.simpleName) {
            if (currentPosition == 2) {
                val fragment = (pages[2] as AppListFragment)
                fragment.reverseOrder()
                val isAsc = fragment.isAsc
                changeAsc(2, isAsc)
            }
            binding.viewpager2.setCurrentItem(2, false)
        }
        binding.llLastUse.setOnClick(javaClass.simpleName) {
            if (currentPosition == 3) {
                val fragment = (pages[3] as AppListFragment)
                fragment.reverseOrder()
                val isAsc = fragment.isAsc
                changeAsc(3, isAsc)
            }
            binding.viewpager2.setCurrentItem(3, false)
        }
        binding.flBack.setOnClick(javaClass.simpleName) {
            AdmobUtils.showInterstitialAd(this) {
                finish()
            }
        }
        onBackPressedDispatcher.addCallback {
            AdmobUtils.showInterstitialAd(this@AppManager2Activity) {
                finish()
            }
        }
//        binding.tvTitle.setOnClickListener {
//            val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
//            intent.addCategory("android.intent.category.DEFAULT")
//            intent.data = Uri.parse("package:${this.packageName}")
//            launcher.launch(intent) {
//                LogEx.logDebug(TAG, "launcher callback")
//            }
//        }

        pageReport()
    }

    private fun playlottie() {
        LogEx.logDebug(TAG, "playlottie")
        binding.llLottie.isVisible = true
        binding.lottie.imageAssetsFolder = "appmanager/images/"
        binding.lottie.setAnimation("appmanager/data.json")
        binding.lottie.playAnimation()
        binding.root.postDelayed({
            AdmobUtils.showInterstitialAd(this) {
                binding.llLottie.isVisible = false
            }
        }, 6000)
    }

    fun refreshUsageAccessData() {
        if (checkUsageAccessSettings()) {

            pages.forEachIndexed { index, fragment ->
                val appListFragment = (fragment as AppListFragment)
                appListFragment.showContent(index == currentPosition)
            }

            lifecycleScope.launch(Dispatchers.IO) {

                setAppBeanSize()
                setAppLastUseTime()

                launch(Dispatchers.Main) {
                    pages.forEachIndexed { index, fragment ->
                        val appListFragment = (fragment as AppListFragment)
                        appListFragment.refreshFragmentData(dataList, index == currentPosition)
                    }
                }
            }
        }
    }

    private fun changeAsc(position: Int, isAsc: Boolean) {
        when (position) {
            0 -> {
                binding.arrowInstall.setAscOrder(false)
                binding.arrowSize.setAscOrder(false)
                binding.arrowLastUse.setAscOrder(false)

                binding.arrowName.setAscOrder(true, isAsc)
            }

            1 -> {
                binding.arrowName.setAscOrder(false)
                binding.arrowSize.setAscOrder(false)
                binding.arrowLastUse.setAscOrder(false)

                binding.arrowInstall.setAscOrder(true, isAsc)
            }

            2 -> {
                binding.arrowName.setAscOrder(false)
                binding.arrowInstall.setAscOrder(false)
                binding.arrowLastUse.setAscOrder(false)

                binding.arrowSize.setAscOrder(true, isAsc)
            }

            3 -> {
                binding.arrowName.setAscOrder(false)
                binding.arrowInstall.setAscOrder(false)
                binding.arrowSize.setAscOrder(false)

                binding.arrowLastUse.setAscOrder(true, isAsc)
            }
        }
    }


    private fun changeIndicator(position: Int) {
        when (position) {
            0 -> {
                binding.vName.visibility = View.VISIBLE
                binding.vInstall.visibility = View.INVISIBLE
                binding.vSize.visibility = View.INVISIBLE
                binding.vLastUse.visibility = View.INVISIBLE
            }

            1 -> {
                binding.vName.visibility = View.INVISIBLE
                binding.vInstall.visibility = View.VISIBLE
                binding.vSize.visibility = View.INVISIBLE
                binding.vLastUse.visibility = View.INVISIBLE
            }

            2 -> {
                binding.vName.visibility = View.INVISIBLE
                binding.vInstall.visibility = View.INVISIBLE
                binding.vSize.visibility = View.VISIBLE
                binding.vLastUse.visibility = View.INVISIBLE
            }

            3 -> {
                binding.vName.visibility = View.INVISIBLE
                binding.vInstall.visibility = View.INVISIBLE
                binding.vSize.visibility = View.INVISIBLE
                binding.vLastUse.visibility = View.VISIBLE
            }
        }
    }

    private fun initViewPager() {
        pages.add(AppListFragment().apply { setInitData(launcher, APP_LIST_TYPE_NAME, true) })
        pages.add(AppListFragment().apply { setInitData(launcher, APP_LIST_TYPE_INSTALL, false) })
        pages.add(AppListFragment().apply { setInitData(launcher, APP_LIST_TYPE_SIZE, false, needPermission = true) })
        pages.add(AppListFragment().apply { setInitData(launcher, APP_LIST_TYPE_LAST_USE, false, needPermission = true) })


        pagerAdapter = ScreenSlidePagerAdapter(this@AppManager2Activity)

        binding.viewpager2.adapter = pagerAdapter

        binding.viewpager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                currentPosition = position
                changeIndicator(position)
                val fragment = (pages[position] as AppListFragment)
                fragment.setDataRefresh(dataList)
                changeAsc(position, fragment.isAsc)
            }
        })
    }


    private fun initAppData() {
        dataList.clear()

        val pm = packageManager
        val packages = pm.getInstalledPackages(0)

        packages.forEach { app ->
            if (viewModel.isLaunchApp(context, app)) {

                val appBean = AppBean(
                    app.applicationInfo.loadIcon(pm),
                    app.applicationInfo.loadLabel(pm).toString(),
                    app.applicationInfo.packageName,
                    false
                )

                //安装时间
                viewModel.setAppInstallTime(appBean, context)
                dataList.add(appBean)
            }
        }
        LogEx.logDebug(TAG, "dataList.size=${dataList.size}")
    }

    fun setAppBeanSize() {
        viewModel.setAppBeanSize(this, dataList)
    }


    fun setAppLastUseTime() {
        viewModel.setAppLastUseTime(this, dataList, queryTime = THIRTY_DAYS_QUERY)
    }

    @SuppressLint("NotifyDataSetChanged")
    fun otherPageRemove(appBean: AppBean, fragment: AppListFragment) {
        dataList.remove(appBean)
        pages.forEach {
            if (it != fragment) {
                (it as AppListFragment).setData(dataList)
            }
        }
    }


    fun allPageRemove(unInstalled: List<AppBean>) {
        Log.e(TAG, "unInstalled=$unInstalled")
        dataList.removeAll(unInstalled.toSet())

        pages.forEachIndexed { index, fragment ->
            val fg = fragment as AppListFragment
            if (index == currentPosition) {
                Log.e(TAG, "dataList=$dataList currentPosition=$currentPosition")
                lifecycleScope.launch(Dispatchers.Main) {
                    delay(1500)
                    fg.setDataRefresh(dataList)
                }
            } else {
                Log.e(TAG, "dataList=$dataList index=$index")
                fg.setData(dataList)
            }
        }
    }

    @SuppressLint("StringFormatMatches")
    fun showUnInstall(selectList: List<AppBean>) {

        if (selectList.isNotEmpty()) {
            binding.tvUninstall.isVisible = true
            binding.tvUninstall.text = resources.getString(R.string.uninstall_number, selectList.size)
            binding.tvUninstall.setOnClick(javaClass.simpleName) {
                binding.tvUninstall.isVisible = false
                binding.tvUninstall.setOnClickListener { }
                unInstallApps(selectList) { unInstalled ->
                    allPageRemove(unInstalled)
                }
            }
        } else {
            binding.tvUninstall.isVisible = false
            binding.tvUninstall.setOnClickListener { }
        }


    }

    private fun unInstallApps(selectList: List<AppBean>, finishUnInstall: (unInstalled: List<AppBean>) -> Unit) =
        lifecycleScope.launch(Dispatchers.IO) {

            val unInstall = arrayListOf<AppBean>()//待卸载列表
            unInstall.addAll(selectList)

            val unInstalled = arrayListOf<AppBean>()//已卸载列表

            val queue = LinkedBlockingDeque<AppBean>()

            val first = unInstall[0]
            queue.put(first)

            while (isActive) {
                val appBean = withContext(Dispatchers.IO) {
                    queue.take()
                }
                val intent = Intent(Intent.ACTION_DELETE, Uri.parse("package:${appBean.pkg}"))

                launcher.launch(intent) {

                    val flag = isInstalled(
                        this@AppManager2Activity,
                        appBean.pkg,
                        error = {
                            unInstall.remove(appBean)
                            unInstalled.add(appBean)
                        })

                    if (!flag) {
                        unInstall.remove(appBean)
                        unInstalled.add(appBean)
                    }

                    if (unInstall.isNotEmpty()) {
                        val next = unInstalled[0]
                        LogEx.logDebug(TAG, "卸载回调 next=$next")
                        queue.put(next)
                    } else {
                        LogEx.logDebug(TAG, "卸载完成回调 finishUnInstall unInstalled=$unInstalled")
                        finishUnInstall.invoke(unInstalled)
                        cancel()
                    }
                }
            }

        }

    inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
        override fun getItemCount(): Int = pages.size
        override fun createFragment(position: Int): Fragment = pages[position]
    }

    override fun pageReport() {
        EventHelper.event("page_${javaClass.simpleName}")
    }
}


