package com.test.basd.onecleanmaster.activity

import android.annotation.SuppressLint
import android.app.AppOpsManager
import android.app.usage.UsageEvents
import android.app.usage.UsageStats
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.Log
import android.view.View
import androidx.activity.addCallback
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 com.google.android.material.tabs.TabLayoutMediator
import com.test.basd.onecleanmaster.bean.AppBean
import com.test.basd.onecleanmaster.fragment.LaunchesFragment
import com.test.basd.onecleanmaster.fragment.ScreenTimeFragment
import com.test.basd.onecleanmaster.helps.ActivityLauncher
import com.test.basd.onecleanmaster.helps.BaseActivity
import com.test.basd.onecleanmaster.helps.LogEx
import com.test.basd.onecleanmaster.helps.TimeUtils.TODAY_QUERY
import com.test.basd.onecleanmaster.helps.TimeUtils.YESTERDAY_QUERY
import com.test.basd.onecleanmaster.helps.TimeUtils.timePair
import com.test.basd.onecleanmaster.helps.ads.AdmobUtils
import com.test.basd.onecleanmaster.helps.recentapp.LaunchTimeStat
import com.test.basd.onecleanmaster.databinding.ActivityRecentAppBinding
import com.test.basd.onecleanmaster.helps.recentapp.ScreenTimeStat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.json.JSONObject

class RecentAppActivity : BaseActivity<ActivityRecentAppBinding>() {

    override val isLightMode = true
    private val TAG = "RecentAppActivity"
    private val pages = arrayListOf<Fragment>()
    private lateinit var pagerAdapter: ScreenSlidePagerAdapter
    private lateinit var tabs: Array<String>
    private var dataList = ArrayList<AppBean>()
    private lateinit var context: Context
    private lateinit var launcher: ActivityLauncher

    override val binding: ActivityRecentAppBinding by lazy {
        ActivityRecentAppBinding.inflate(layoutInflater)
    }

    override fun initView() {
        launcher = ActivityLauncher(this)
        context = this
        initPage()
        intTab()
        if (checkUsageAccessSettings()) {
            Log.e("MXL", "onCreate: " + checkUsageAccessSettings())
            intData()
            playLottie()
        } else {
            binding.llContent.visibility = View.GONE
            binding.flPermission.visibility = View.VISIBLE
        }
    }

    override fun initListener() {
        binding.flBack.setOnClickListener {
            AdmobUtils.showInterstitialAd(this) {
                finish()
            }
        }
        onBackPressedDispatcher.addCallback {
            LogEx.logDebug(TAG, "onBackPressedDispatcher")
            AdmobUtils.showInterstitialAd(this@RecentAppActivity) {
                finish()
            }
        }
        binding.tvGrand.setOnClickListener {
            val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
            intent.addCategory("android.intent.category.DEFAULT")
            intent.data = Uri.parse("package:${context.packageName}")
            launcher.launch(intent) {
                LogEx.logDebug(TAG, "launcher callback")
                val obj = JSONObject()
                obj.put("activity", javaClass.simpleName)

                if (checkUsageAccessSettings()) {
                    binding.flPermission.visibility = View.GONE
                    binding.llContent.visibility = View.VISIBLE
                    intData()
                } else {
                    finishToMain()
                }
            }
        }
    }

    private fun playLottie(showFinish: (() -> Unit)? = null) {
        binding.llLottie.isVisible = true
        binding.lottie.imageAssetsFolder = "onecle_zui_jing/images/"
        binding.lottie.setAnimation("onecle_zui_jing/data.json")
        binding.lottie.playAnimation()
        binding.root.postDelayed({
            AdmobUtils.showInterstitialAd(this) {
                binding.llLottie.isVisible = false
                showFinish?.invoke()
            }
        }, 6000)
    }


    private fun intData() {


        CoroutineScope(Dispatchers.IO).launch {

            //测试打印数据
//            printEventList(context, lifecycleScope).await()

            //构建AppData列表
            initAppData()

            //设置启动数据
            setLaunchesData()

            //屏幕时间数据
            setScreenTimeData()

            //更新UI数据
            launch(Dispatchers.Main) {
                updateFragmentData(0, 1)
            }
        }
    }

    private fun initAppData() {
        dataList.clear()

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

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

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

                //安装时间
                setAppInstallTime(appBean, context)
                dataList.add(appBean)
            }
        }

    }

    private fun updateFragmentData(vararg position: Int) {
        if (position.contains(0)) {
            val launchesFragment = pages[0] as LaunchesFragment
            launchesFragment.setAppUseData(dataList)
        }

        if (position.contains(1)) {
            val screenTimeFragment = pages[1] as ScreenTimeFragment
            screenTimeFragment.setScreenData(dataList)
        }

    }

    private fun setScreenTimeData(queryTime: Int = TODAY_QUERY) {
        val pair = timePair(queryTime)

        val screenTimeMap = ScreenTimeStat(pair.first, pair.second).run(context)
        //key=com.vivo.appfilter pkg=com.vivo.appfilter f30766a=防拉起服务 f30767b=com.vivo.appfilter c=1132
        dataList.forEach { app ->
            if (screenTimeMap.keys.contains(app.pkg)) {
                val value = screenTimeMap[app.pkg]
                value?.let { b ->
                    app.screenTime = b.c
                }
            }
        }
    }

    private fun setLaunchesData(queryTime: Int = TODAY_QUERY) {
        val tempList = arrayListOf<AppBean>()
        tempList.addAll(dataList)

        //后台启动数据
        dataList = getAppUseAnalyze(context, queryTime, tempList)

        //前台启动数据
        val pair = timePair(queryTime)
        val ast = LaunchTimeStat(pair.first, pair.second)
        val hashMap = ast.run(context)
        dataList.forEach { app ->
            if (hashMap.keys.contains(app.pkg)) {
                val value = hashMap[app.pkg]
                if (value != null) {
                    val tempList2 = arrayListOf<UsageEvents.Event>()
                    tempList2.addAll(value)
                    app.usageEvents?.also { evens -> tempList2.addAll(evens) }
                    app.usageEvents = tempList2
                }
            }
        }
    }

    fun changeTimeRefresh(queryTime: Int, fragmentPosition: Int) {
        lifecycleScope.launch(Dispatchers.IO) {
            initAppData()

            //设置启动数据
            setLaunchesData(queryTime)

            //屏幕时间数据
            setScreenTimeData(queryTime)

            //更新UI数据
            launch(Dispatchers.Main) { updateFragmentData(fragmentPosition) }
        }
    }


    private fun intTab() {
        //有个问题结合ViewPager2就无法用静态xml中的TabItem
        tabs = arrayOf("LAUNCHES", "SCREEN TIME")
        TabLayoutMediator(binding.tabLayout, binding.viewpager2) { tab, position ->
            tab.text = tabs[position]
            binding.viewpager2.currentItem = position
        }.attach()

        binding.viewpager2.currentItem = 0
    }

    private fun initPage() {
        pages.add(LaunchesFragment())
        pages.add(ScreenTimeFragment())
        pagerAdapter = ScreenSlidePagerAdapter(this)
        binding.viewpager2.adapter = pagerAdapter
    }

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


    private fun checkUsageAccessSettings(): Boolean {

        val appOpsManager = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager

        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            appOpsManager.unsafeCheckOpNoThrow(
                AppOpsManager.OPSTR_GET_USAGE_STATS,
                android.os.Process.myUid(),
                this.packageName
            ) == AppOpsManager.MODE_ALLOWED
        } else {
            appOpsManager.checkOpNoThrow(
                AppOpsManager.OPSTR_GET_USAGE_STATS,
                android.os.Process.myUid(),
                this.packageName
            ) == AppOpsManager.MODE_ALLOWED
        }
    }

    private fun isLaunchApp(context: Context, app: PackageInfo, filterSystem: Boolean = true): Boolean {

        val flagSystem = (app.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) < 1
        val flag = if (filterSystem) flagSystem else true

        return flag && app.applicationInfo.packageName != context.packageName
    }

    private fun setAppInstallTime(appBean: AppBean, context: Context) {
        //安装时间
        var firstInstallTime = 0L
        try {
            val packageManager = context.packageManager
            val packageInfo: PackageInfo = packageManager.getPackageInfo(appBean.pkg, 0)
            //应用装时间
            firstInstallTime = packageInfo.firstInstallTime
            //应用最后一次更新时间
            val lastUpdateTime = packageInfo.lastUpdateTime
//                        LogEx.logDebug(TAG, "lastUpdateTime=$lastUpdateTime")
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }

        appBean.installTime = firstInstallTime
    }

    /**
     * 设置最近使用分析数据
     */
    private fun getAppUseAnalyze(
        context: Context,
        queryTime: Int = YESTERDAY_QUERY,
        dataList: List<AppBean>,
    ): ArrayList<AppBean> {
        val launchList = arrayListOf<AppBean>()
        val pair = timePair(queryTime)
        val startTime: Long = pair.first
        val endTime: Long = pair.second

        val stateList = getUsageList(context, startTime, endTime)
        val evenMap = getEventList2(context, startTime, endTime)

//        evenList.forEach { event -> printEvent(event) }
//        stateList.forEach { state -> printState(state) }

        dataList.forEach { app ->
            //这里只使用后台启动数据
            //FOREGROUND_SERVICE_START 19
            app.usageEvents = evenMap[app.pkg]?.filter { it.eventType == 19 }
            app.usageStats = stateList.filter { it.packageName == app.pkg }
        }

        launchList.addAll(dataList)

        return launchList
    }

    /**
     * 前台运行App+后台运行App=总的启动App
     */
    fun getUsageList(context: Context, startTime: Long, endTime: Long): ArrayList<UsageStats> {
        val list = arrayListOf<UsageStats>()
        val mUsmManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
        val map = mUsmManager.queryAndAggregateUsageStats(startTime, endTime)
        map.values.forEach { stats ->
            if (stats.totalTimeInForeground > 0) {
                list.add(stats)
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    if (stats.totalTimeForegroundServiceUsed > 0) {
                        list.add(stats)
                    }
                }
            }

        }
        return list
    }

    @SuppressLint("InlinedApi")
    fun getEventList2(
        context: Context,
        startTime: Long,
        endTime: Long,
    ): HashMap<String, ArrayList<UsageEvents.Event>> {

        val mUsmManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
        //链表记录所有的Event.快速查找
        val allList = ArrayList<UsageEvents.Event>()

        try {
            val events = mUsmManager.queryEvents(startTime, endTime)
            while (events.hasNextEvent()) {
                val event = UsageEvents.Event()
                events.getNextEvent(event)

                val flag2 =
                    (event.eventType != UsageEvents.Event.ACTIVITY_STOPPED) && (event.eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED)
                if (flag2) {
                    allList.add(event)
                }
            }
        } catch (e: Exception) {
            LogEx.logDebug(TAG, "Exception ${e.printStackTrace()}")
            e.printStackTrace()
        }

        //记录数据结构
        val hashMap = HashMap<String, ArrayList<UsageEvents.Event>>()

        allList.forEachIndexed { index, event ->

            //例子：CCAAVCSAABBBCDEFGABCDEFAABB
            //过滤的结果
            //CAASAAGAFAA

            val list = hashMap[event.packageName]
            if (list == null) {
                hashMap[event.packageName] = arrayListOf()
            }

            //上个Event是否存在
            var lastEvent: UsageEvents.Event? = null
            val lastIndex = index - 1
            if (index > 0) {
                lastEvent = allList[lastIndex]
            }

            //上一个Event是否相同包
            if (lastEvent != null && lastEvent.packageName != event.packageName) {
                list?.add(lastEvent)
            }

            list?.add(event)

        }

        return hashMap
    }

}