package com.base.appzxhy.ui.clean

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.base.LottieEnum
import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN
import com.base.appzxhy.bean.FileBean
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.ActivityJunkCleanBinding
import com.base.appzxhy.databinding.ItemJunkCleanChildBinding
import com.base.appzxhy.databinding.ItemJunkCleanGroupBinding
import com.base.appzxhy.ui.cleanresult.CleanResultActivity
import com.base.appzxhy.utils.FileUtils
import com.base.appzxhy.utils.MediaUtils
import com.base.appzxhy.utils.MineTypeUtils
import com.base.appzxhy.utils.MyAnimationUtils
import com.base.appzxhy.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pokercc.android.expandablerecyclerview.ExpandableAdapter
import pokercc.android.expandablerecyclerview.ExpandableItemAnimator
import kotlin.random.Random


class JunkCleanActivity : BaseActivity<ActivityJunkCleanBinding>(ActivityJunkCleanBinding::inflate) {

    private var isStartAnimation = true
    private var list = mutableListOf<FileBean>()
    private var total: Long = 0
    private var selectedFiles = listOf<FileBean>()

    private val adapter by lazy {
        class ChildViewHolder(val binding: ItemJunkCleanChildBinding) : ExpandableAdapter.ViewHolder(binding.root)
        class GroupViewHolder(val binding: ItemJunkCleanGroupBinding) : ExpandableAdapter.ViewHolder(binding.root)

        object : ExpandableAdapter<ExpandableAdapter.ViewHolder>() {
            override fun getChildCount(groupPosition: Int): Int = list[groupPosition].items.size

            override fun getGroupCount(): Int = list.size

            override fun onCreateChildViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
                val binding = ItemJunkCleanChildBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
                return ChildViewHolder(binding)
            }

            override fun onCreateGroupViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
                val binding = ItemJunkCleanGroupBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
                return GroupViewHolder(binding)
            }

            override fun onGroupViewHolderExpandChange(
                holder: ViewHolder,
                groupPosition: Int,
                animDuration: Long,
                expand: Boolean
            ) {
            }

            override fun onBindGroupViewHolder(
                holder: ViewHolder,
                groupPosition: Int,
                expand: Boolean,
                payloads: List<Any>
            ) {
                holder as GroupViewHolder
                val group = list[groupPosition]
                holder.binding.tvName.text = group.name
                holder.binding.tvLength.text = Utils.getSizeFormat(group.length)
                holder.binding.ivIcon.setImageResource(group.icon)
                holder.binding.ivIndicator.setImageResource(if (expand) R.drawable.icon_up else R.drawable.icon_down)
                holder.binding.clItem.setBackgroundResource(if (expand && group.items.isNotEmpty()) R.drawable.white_background_top_8 else R.drawable.white_background_8)
                holder.binding.ivSelect.isSelected = group.isSelected
                holder.binding.ivSelect.setOnClickListener {
                    group.isSelected = !group.isSelected
                    group.items.forEach { it.isSelected = group.isSelected }
                    notifyGroupChange(groupPosition)
                    for (childPosition in 0..<group.items.size) {
                        notifyChildChange(groupPosition, childPosition)
                    }
                    updateSelection()
                }

                if (isStartAnimation) {
                    val translationX = holder.itemView.context.resources.displayMetrics.widthPixels.toFloat()
                    holder.itemView.translationX = -translationX
                    MyAnimationUtils.translationX(holder.itemView, -translationX, 0f, 1000, (groupPosition + 1) * 300L)
                }
                if (groupPosition == list.size - 1) isStartAnimation = false
            }

            override fun onBindChildViewHolder(
                holder: ViewHolder,
                groupPosition: Int,
                childPosition: Int,
                payloads: List<Any>
            ) {
                holder as ChildViewHolder
                val group = list[groupPosition]
                val child = group.items[childPosition]
                holder.binding.tvName.text = child.name
                holder.binding.tvLength.text = Utils.getSizeFormat(child.length)
                holder.itemView.setBackgroundResource(if (childPosition == group.items.size - 1) R.drawable.white_background_bottom_8 else R.color.white)
                holder.binding.ivSelect.isSelected = child.isSelected
                holder.itemView.setOnClickListener {
                    child.isSelected = !child.isSelected
                    notifyChildChange(groupPosition, childPosition)
                    val isSelected = group.items.stream().allMatch(FileBean::isSelected)
                    if (group.isSelected != isSelected) {
                        group.isSelected = isSelected
                        notifyGroupChange(groupPosition)
                    }
                    updateSelection()
                }
            }
        }
    }

    private fun updateSelection() {
        selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelected } ?: emptyList() }
        total = selectedFiles.sumOf { it.length }
        setClean()
    }


    private fun setClean() {
        binding.tvClean.text =
            if (total > 0) "${getString(R.string.clean)} (${Utils.getSizeFormat(total)})" else getString(R.string.go_it)
        binding.tvClean.isEnabled = total > 0
    }

    override fun useDefaultImmersive() {
        setStatusBarColor()
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, 0, systemBars.right, systemBars.bottom)
            binding.clTop.setPadding(0, systemBars.top, 0, 0)
            insets
        }
    }

    override fun initView() {
        super.initView()
        AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
        binding.expandableFiles.adapter = adapter
        binding.expandableFiles.layoutManager = LinearLayoutManager(this)
        binding.expandableFiles.itemAnimator = ExpandableItemAnimator(binding.expandableFiles)

        initData()
    }

    override fun initListener() {
        super.initListener()

        binding.ivBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
        binding.tvClean.setOnClickListener {
            if (isBackDisable) return@setOnClickListener

            if (total > 0) {
                showAdAnimation(LottieEnum.CLEAN_LOTTIE) {
//                    cleanFiles(selectedFiles)

                    CleanResultActivity.functionKey = JUNK_CLEAN
                    CleanResultActivity.titleName = this@JunkCleanActivity.getString(R.string.junk_clean)
                    CleanResultActivity.total = total
                    goToAc(CleanResultActivity::class.java)
                    finish()
                }
            } else {
//                goToAc(CleanResultActivity)
            }

        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initData() {
        isBackDisable = true
        binding.tvPath.text = ""
        binding.tvClean.visibility = View.GONE
        lifecycleScope.launch(Dispatchers.IO) {
            val emptyFolders = async { FileUtils.findEmptyFolders() }.await()
            val files = async { MediaUtils.findSpecifiedFiles(this@JunkCleanActivity) }.await()
            emptyFolders.forEach { it.isSelected = true }
            files.forEach { it.isSelected = true }

            val apkFiles = files.filter { file ->
                MineTypeUtils.apks.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()
            val tempFiles = files.filter { file ->
                MineTypeUtils.temps.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()
            val logsFiles = files.filter { file ->
                MineTypeUtils.logs.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()

            list = getGroupData()
            list[0].length = emptyFolders.sumOf { it.length }
            list[1].length = apkFiles.sumOf { it.length }
            list[2].length = tempFiles.sumOf { it.length }
            list[3].length = logsFiles.sumOf { it.length }
            list[0].items = emptyFolders
            list[1].items = apkFiles
            list[2].items = tempFiles
            list[3].items = logsFiles
            total = list.sumOf { it.length }
            val childData = mutableListOf<FileBean>().apply {
                addAll(emptyFolders)
                addAll(apkFiles)
                addAll(tempFiles)
                addAll(logsFiles)
            }
            val list = childData.sortedByDescending { it.length }
            val totalSize = list.sumOf { it.length }
            val random = Random.nextLong(2500, 3000)
            launch(Dispatchers.Main) {
                MyAnimationUtils.progress(binding.pbProgress, 0, 100, random)
                ValueAnimator.ofFloat(0f, totalSize.toFloat()).apply {
                    duration = random
                    interpolator = LinearInterpolator()
                    addUpdateListener { animation ->
                        val value = animation.animatedValue as Float
                        setSize(value.toLong())
                    }
                }.start()
            }
            for (data in list) {
                if (binding.pbProgress.progress == 100) break
                withContext(Dispatchers.Main) {
                    binding.tvPath.text = data.path
                }
            }
            delay(random)
            launch(Dispatchers.Main) {
                scanComplete()
                adapter.notifyDataSetChanged()
            }
        }
    }

    private fun getGroupData(): MutableList<FileBean> {
        return mutableListOf(
            FileBean(getString(R.string.empty_folder), icon = R.drawable.icon_empty, isSelected = true),
            FileBean(getString(R.string.apk_files), icon = R.drawable.icon_apk, isSelected = true),
            FileBean(getString(R.string.temp_files), icon = R.drawable.temp, isSelected = true),
            FileBean(getString(R.string.logs_files), icon = R.drawable.icon_log, isSelected = true),
        )
    }

    private fun scanComplete() {
        isBackDisable = false
        binding.expandableFiles.visibility = View.VISIBLE
        binding.tvClean.visibility = View.VISIBLE
        binding.tvPath.text = getString(R.string.clean_tips)
        updateSelection()
    }

    private fun setSize(size: Long) {
        val values = Utils.getSizeArray(size)
        binding.tvLength.text = values[0]
        binding.tvUnit.text = values[1]
    }

}