package melody.offline.music.activity

import android.annotation.SuppressLint
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.TextView
import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.adapter.OfflineSongsAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean
import melody.offline.music.databinding.ActivityOfflineSongsBinding
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.LogTag
import org.json.JSONObject

@OptIn(UnstableApi::class)
class MoOfflineSongsActivity : MoBaseActivity() {
    private val requests: Channel<Request> = Channel(Channel.UNLIMITED)

    sealed class Request {
        data object TryAgain : Request()
        data class OnFavorites(val bean: OfflineBean) : Request()
        data class OnDownloadRemove(val id: String) : Request()
        data class UpdateFavorite(val id: String) : Request()
        data class OnAddPlaylist(val bean: OfflineBean) : Request()
    }

    private lateinit var binding: ActivityOfflineSongsBinding
    private var adapter: OfflineSongsAdapter? = null
    private var offlineList: MutableList<OfflineBean> = mutableListOf()

    private var currentPosition = -1

    override suspend fun main() {
        binding = ActivityOfflineSongsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_ME_PAGE_LIST)
        initImmersionBar()
        initView()
        initAdapter()
        LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
        initData()
        onReceive()
    }

    private fun initImmersionBar() {
        immersionBar {
            statusBarDarkFont(false)
            statusBarView(binding.view)
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private suspend fun onReceive() {
        while (isActive) {
            select<Unit> {
                requests.onReceive {
                    when (it) {
                        Request.TryAgain -> {
                            initData()
                        }

                        is Request.OnFavorites -> {
                            val jsonObject = JSONObject()
                            jsonObject.put(
                                "song_title", it.bean.title
                            )
                            val songMap = mutableMapOf(
                                Pair(
                                    AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                                )
                            )
                            val currentFavoriteBean =
                                App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
                            if (currentFavoriteBean != null) {
                                currentFavoriteBean.isFavorite = !currentFavoriteBean.isFavorite
                                App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)
                                if (currentFavoriteBean.isFavorite) {
                                    AnalysisUtil.logEvent(
                                        AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap
                                    )
                                } else {
                                    AnalysisUtil.logEvent(
                                        AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, songMap
                                    )
                                }
                            } else {
                                insertFavoriteData(it.bean)
                                AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
                            }
                            requests.trySend(Request.UpdateFavorite(it.bean.videoId))
                        }

                        is Request.OnDownloadRemove -> {
                            val currentOfflineBean =
                                App.appOfflineDBManager.getOfflineBeanByID(it.id)
                            if (currentOfflineBean != null) {
                                App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
                            }
                            if (currentPosition >= 0) {
                                offlineList.remove(offlineList[currentPosition])
                            }
                            adapter?.notifyDataSetChanged()

                            hideBottomLayout()
                        }

                        is Request.UpdateFavorite -> {
                            val currentFavoriteBean =
                                App.appFavoriteDBManager.getFavoriteBeanByID(it.id)
                            if (currentFavoriteBean != null) {
                                updateFavoriteUi(currentFavoriteBean.isFavorite)
                            } else {
                                updateFavoriteUi(false)
                            }
                        }

                        is Request.OnAddPlaylist -> {
                            showAddPlaylistBottomDialog(
                                FavoriteBean(
                                    videoId = it.bean.videoId,
                                    title = it.bean.title,
                                    name = it.bean.name,
                                    thumbnail = it.bean.thumbnail,
                                    isFavorite = it.bean.isFavorite
                                )
                            )
                        }
                    }
                }
                events.onReceive {
                    when (it) {
                        Event.ActivityOnResume -> {
                            activityOnResume()
                        }

                        Event.AutomaticallySwitchSongs -> {
                            if (adapter != null) {
                                adapter?.notifyDataSetChanged()
                            }
                        }

                        else -> {}
                    }
                }
            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun activityOnResume() {
        addMusicPlayerViewToLayout(binding.playMusicLayout)

        if (adapter != null) {
            adapter?.notifyDataSetChanged()
        }

        LolAdWrapper.shared.loadAdShowNativeAd(
            this,
            AdPlacement.NATIVE_ME_PAGE_LIST,
            binding.frameAd,
            R.layout.ad_layout_admob_banner,
            R.layout.ad_layout_max_banner
        )
    }

    private fun initView() {
        binding.layoutInfo.setOnClickListener { }
        binding.backBtn.setOnClickListener {
            finish()
        }
        binding.tryAgainBtn.setOnClickListener {
            requests.trySend(Request.TryAgain)
        }
        binding.bottomCloseBtn.setOnClickListener {
            hideBottomLayout()
        }
        binding.bottomBlankLayout.setOnClickListener {
            hideBottomLayout()
        }
        binding.moreDownloadBtn.setOnClickListener {
            if (currentPosition >= 0) {
                val videoId = offlineList[currentPosition].videoId
                showRemoveDownloadDialogHint(videoId)
            }
        }
        binding.moreAddPlaylistBtn.setOnClickListener {
            if (currentPosition >= 0) {
                requests.trySend(Request.OnAddPlaylist(offlineList[currentPosition]))
                hideBottomLayout()
            }
        }
        binding.favoritesBtn.setOnClickListener {
            if (currentPosition >= 0) {
                requests.trySend(Request.OnFavorites(offlineList[currentPosition]))
            }
        }
    }

    private fun initAdapter() {
        adapter = OfflineSongsAdapter(this, offlineList)
        adapter?.setOnMoreClickListener(object : OfflineSongsAdapter.OnMoreClickListener {
            override fun onMoreClick(position: Int) {
                currentPosition = position
                toggleBottomLayout(position)
            }
        })
        binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.rv.adapter = adapter
    }

    @SuppressLint("NotifyDataSetChanged")
    private suspend fun initData() {
        showLoadingUi()

        offlineList.clear()
        val offlineBeans = App.appOfflineDBManager.getAllOfflineBeans()
        // 更新
        offlineBeans.forEach { offlineBean ->
            val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(offlineBean.videoId)
            if (favoriteBean != null) {
                if (offlineBean.id == favoriteBean.id) {
                    offlineBean.isFavorite = favoriteBean.isFavorite
                    App.appOfflineDBManager.updateOfflineBean(offlineBean)
                }
            }
        }
        val filteredBeans =
            offlineBeans.filter { it.bytesDownloaded?.let { bytes -> bytes > 0 } == true }
        offlineList.addAll(filteredBeans)
        if (offlineList.size > 0) {
            showDataUi()
        } else {
            showNoContentUi()
        }
        if (adapter != null) {
            adapter?.notifyDataSetChanged()
        }

    }

    private fun showRemoveDownloadDialogHint(id: String) {
        LogTag.LogD(TAG, "showRemoveDownloadDialogHint")
        val inflater = LayoutInflater.from(this)
        val dialogView = inflater.inflate(R.layout.dialog_hint, null)
        val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
        val cancelBtn = dialogView.findViewById<TextView>(R.id.dialog_cancel_btn)
        val dialogBuilder = AlertDialog.Builder(this).setView(dialogView)
        val dialog = dialogBuilder.create()
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.show()
        okBtn.setOnClickListener {
            dialog.dismiss()
            requests.trySend(Request.OnDownloadRemove(id))
        }
        cancelBtn.setOnClickListener {
            dialog.dismiss()
        }
    }

    private fun updateFavoriteUi(b: Boolean) {
        if (b) {
            binding.favoritesImg.setImageResource(R.drawable.favorited_icon)
        } else {
            binding.favoritesImg.setImageResource(R.drawable.not_favorited_icon)
        }
    }

    private fun toggleBottomLayout(position: Int) {
        if (binding.bottomLayout.visibility == View.VISIBLE) {
            hideBottomLayout()
        } else {
            showBottomLayout(position)
        }
    }

    private fun showBottomLayout(position: Int) {
        val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
        binding.bottomLayout.startAnimation(slideUpAnimation)
        binding.bottomLayout.visibility = View.VISIBLE

        val bean = offlineList[position]
        Glide.with(this).load(bean.thumbnail).into(binding.songImg)
        binding.title.text = bean.title
        if (bean.name.isEmpty()) {
            binding.name.visibility = View.GONE
        } else {
            binding.name.visibility = View.VISIBLE
            binding.name.text = bean.name
        }
        requests.trySend(Request.UpdateFavorite(bean.videoId))
    }

    private fun hideBottomLayout() {
        val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
        binding.bottomLayout.startAnimation(slideDownAnimation)
        binding.bottomLayout.visibility = View.GONE
    }

    private fun showDataUi() {
        binding.loadingLayout.visibility = View.GONE
        binding.noContentLayout.visibility = View.GONE
    }

    private fun showLoadingUi() {
        binding.loadingLayout.visibility = View.VISIBLE
        binding.noContentLayout.visibility = View.GONE
    }

    private fun showNoContentUi() {
        binding.loadingLayout.visibility = View.GONE
        binding.noContentLayout.visibility = View.VISIBLE
    }
}