package com.ritoq.quickphone.ui.clean

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContextCompat
import androidx.core.graphics.toColorInt
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.ritoq.quickphone.R
import com.ritoq.quickphone.base.BaseActivity
import com.ritoq.quickphone.base.LottieEnum
import com.ritoq.quickphone.base.cleanFileBeans
import com.ritoq.quickphone.bean.FeatureBean.Companion.JUNK_CLEAN
import com.ritoq.quickphone.bean.FeatureBean.Companion.setFunctionTodayUsed
import com.ritoq.quickphone.bean.FileBean
import com.ritoq.quickphone.bean.config.AdConfigBean
import com.ritoq.quickphone.databinding.ActivityJunkClean2Binding
import com.ritoq.quickphone.databinding.ItemJunkCleanChildBinding
import com.ritoq.quickphone.databinding.ItemJunkCleanGroupBinding
import com.ritoq.quickphone.ui.cleanresult.CleanResultActivity
import com.ritoq.quickphone.utils.FileUtils
import com.ritoq.quickphone.utils.KotlinExt.toFormatSize
import com.ritoq.quickphone.utils.MediaUtils
import com.ritoq.quickphone.utils.MineTypeUtils
import com.ritoq.quickphone.utils.MyAnimationUtils
import com.ritoq.quickphone.utils.Utils
import com.zhpan.indicator.enums.IndicatorSlideMode
import com.zhpan.indicator.enums.IndicatorStyle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
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<ActivityJunkClean2Binding>(ActivityJunkClean2Binding::inflate) {

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

    private val page1 by lazy { CleanPageFragment() }
    private val page2 by lazy { CleanNativeFragment() }
    private val fragments by lazy {
        arrayListOf<Fragment>().apply {
            add(page1)
            if (AdConfigBean.adsConfigBean.isAdShow) {
                binding.indicator.visibility = View.VISIBLE
                add(page2)
            }
        }
    }
    private val viewPagerAdapter by lazy {
        object : FragmentStateAdapter(this) {
            override fun getItemCount(): Int = fragments.size

            override fun createFragment(position: Int): Fragment = fragments[position]
        }
    }
    private var currentPosition = 0


    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_zhankai_clean else R.drawable.icon_shouqi_clean)
                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) {
                    holder.binding.ivRotate.visibility = View.VISIBLE
                    holder.binding.ivSelect.visibility = View.INVISIBLE
                    MyAnimationUtils.rotation(holder.binding.ivRotate)
//                    val translationX = holder.itemView.context.resources.displayMetrics.widthPixels.toFloat()
//                    holder.itemView.translationX = -translationX
//                    MyAnimationUtils.translationX(holder.itemView, -translationX, 0f, 1000, (groupPosition + 1) * 300L)
                } else {
                    holder.binding.ivRotate.visibility = View.GONE
                    holder.binding.ivSelect.visibility = View.VISIBLE
                }
//                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
        if (binding.tvClean.isEnabled) {
            binding.tvClean.setTextColor(ContextCompat.getColor(this, R.color.white))
        } else {
            binding.tvClean.setTextColor(ContextCompat.getColor(this, R.color.colorPrimary))
        }
    }

    override fun useDefaultImmersive() {
        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
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun initView() {
        super.initView()
        binding.expandableFiles.adapter = adapter
        binding.expandableFiles.layoutManager = LinearLayoutManager(this)
        binding.expandableFiles.itemAnimator = ExpandableItemAnimator(binding.expandableFiles)

        initPage()
        initData()

        setFunctionTodayUsed(JUNK_CLEAN)
    }

    private fun initPage() {
        binding.indicator.apply {
            setSliderColor("#ffffff".toColorInt(), "#06D16C".toColorInt())
            setSliderWidth(resources.getDimension(R.dimen.dp_6))
            setSliderHeight(resources.getDimension(R.dimen.dp_6))
            setSlideMode(IndicatorSlideMode.COLOR)
            setIndicatorStyle(IndicatorStyle.CIRCLE)
            setPageSize(2)
            notifyDataChanged()
        }

        binding.viewPager2.adapter = viewPagerAdapter
        binding.viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                binding.indicator.onPageScrolled(position, positionOffset, positionOffsetPixels)
            }

            override fun onPageSelected(position: Int) {
                binding.indicator.onPageSelected(position)
                currentPosition = position
            }
        })

        if (AdConfigBean.adsConfigBean.isAdShow) {
            lifecycleScope.launch(Dispatchers.IO) {
                while (isActive) {
                    delay(3000)
                    launch(Dispatchers.Main) {
                        if (currentPosition == 0) {
                            binding.viewPager2.setCurrentItem(1, true)
                        } else {
                            binding.viewPager2.setCurrentItem(0, true)
                        }
                    }
                }
            }
        }

    }

    override fun initListener() {
        super.initListener()

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

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

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

        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initData() {
        isBackDisable = true
        page1.tvPath?.text = ""
        binding.tvClean.visibility = View.GONE
        lifecycleScope.launch(Dispatchers.IO) {

            list = getGroupData()
            launch(Dispatchers.Main) {
                adapter.notifyDataSetChanged()
            }

            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[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) {
                    page1.tvPath?.text = data.path
                }
            }
            delay(random)
            launch(Dispatchers.Main) {
                scanComplete()
                isStartAnimation = false
                adapter.notifyDataSetChanged()
            }
        }
    }

    private fun getGroupData(): MutableList<FileBean> {
        return mutableListOf(
            FileBean(getString(R.string.empty_folder), icon = R.drawable.icon_empty_junk, isSelected = true),
            FileBean(getString(R.string.apk_files), icon = R.drawable.icon_apk_junk, isSelected = true),
            FileBean(getString(R.string.temp_files), icon = R.drawable.icon_temp_junk, isSelected = true),
            FileBean(getString(R.string.logs_files), icon = R.drawable.icon_logs_junk, isSelected = true),
        )
    }

    private fun scanComplete() {
        isBackDisable = false
        binding.expandableFiles.visibility = View.VISIBLE
        binding.tvClean.visibility = View.VISIBLE
        updateSelection()
        page1.tvPath?.setText(R.string.scan_completed)
        page1.tvSize?.text = getString(R.string.found_f, total.toFormatSize())
    }

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

    companion object {

        fun getJunkSize(context: Context): Long {
            val files = MediaUtils.findSpecifiedFiles(context)
            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()

            val size = apkFiles.sumOf { it.length } + tempFiles.sumOf { it.length } + logsFiles.sumOf { it.length }

            return size
        }
    }
}