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.Animation
import android.view.animation.AnimationUtils
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.offline.DownloadRequest
import androidx.media3.exoplayer.offline.DownloadService
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetDialog
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.LikedSongsAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.ActivityLikedSongsBinding
import melody.offline.music.fragment.MoMeFragment
import melody.offline.music.service.MyDownloadService
import melody.offline.music.service.ViewModelMain
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.LogTag
import melody.offline.music.util.asPlaylistItem
import melody.offline.music.view.ListMoreBottomSheetDialog
import org.json.JSONObject

@OptIn(UnstableApi::class)
class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavoritesClickListener,
    LikedSongsAdapter.OnMoreClickListener, ListMoreBottomSheetDialog.ListMoreViewListener,
    ListMoreBottomSheetDialog.UpdateAdapterListener {

    private val requests: Channel<Request> = Channel(Channel.UNLIMITED)

    sealed class Request {
        data object TryAgain : Request()
        data class OnFavorites(val bean: PlaylistItem) : Request()
        data class OnDownload(val bean: PlaylistItem) : Request()
        data class OnDownloadRemove(val bean: PlaylistItem) : Request()
        data class OnUpdateDownloadUi(val bean: PlaylistItem) : Request()
        data class OnAddPlaylist(val bean: PlaylistItem) : Request()
        data class OnUpdateCurrentListItem(val bean: PlaylistItem): Request()
    }

    private lateinit var binding: ActivityLikedSongsBinding
    private var adapter: LikedSongsAdapter? = null
    private var myList: MutableList<PlaylistItem> = mutableListOf()
    private var moreDialog: ListMoreBottomSheetDialog? = null

    override suspend fun main() {
        binding = ActivityLikedSongsBinding.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) {
                        is Request.TryAgain -> {
                            initData()
                        }

                        is Request.OnFavorites -> {
                            it.bean.isFavorite = !it.bean.isFavorite
                            adapter?.notifyDataSetChanged()//更新list

                            updateFavoriteUi(it.bean.isFavorite)//更新对话框

                            val currentFavoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
                            if (currentFavoriteBean != null) {
                                currentFavoriteBean.isFavorite = it.bean.isFavorite
                                App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)//更新数据库
                            }
                        }

                        is Request.OnDownload -> {
                            val id = it.bean.videoId
                            LogTag.LogD(TAG, "OnDownload id->${id}")
                            val currentOfflineBean = App.appOfflineDBManager.getOfflineBeanByID(id)
                            if (currentOfflineBean != null && currentOfflineBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
                                showRemoveDownloadDialogHint(it.bean)
                            } else {
                                //判断是否已经下载了这条数据，已经下载，就直接进行数据库数据存储，反之走下载流程。
                                if (DownloadUtil.downloadResourceExist(id)) {
                                    insertOfflineData(FavoriteBean(
                                        videoId = it.bean.videoId,
                                        title = it.bean.title,
                                        name =  it.bean.name,
                                        thumbnail = it.bean.thumbnail,
                                        isFavorite = it.bean.isFavorite
                                    ))
                                    it.bean.isOffline = true
                                    requests.trySend(Request.OnUpdateDownloadUi(it.bean))
                                    requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
                                } else {
                                    val downloadRequest = DownloadRequest.Builder(id, id.toUri())
                                        .setCustomCacheKey(id).build()

                                    val downloadCount = DownloadUtil.getCurrentDownloads()
                                    if (downloadCount >= 3) {
                                        Toast.makeText(
                                            this@MoLikedSongsActivity,
                                            getString(R.string.download_tips),
                                            Toast.LENGTH_LONG
                                        ).show()
                                    } else {
                                        DownloadService.sendAddDownload(
                                            this@MoLikedSongsActivity,
                                            MyDownloadService::class.java,
                                            downloadRequest,
                                            false
                                        )


                                        LolAdWrapper.shared.showAdTiming(
                                            this@MoLikedSongsActivity, AdPlacement.INST_DOWNLOAD
                                        )

                                        insertOfflineData(FavoriteBean(
                                            videoId = it.bean.videoId,
                                            title = it.bean.title,
                                            name =  it.bean.name,
                                            thumbnail = it.bean.thumbnail,
                                            isFavorite = it.bean.isFavorite
                                        ))
                                        val jsonObject = JSONObject()
                                        jsonObject.put(
                                            "download_id", it.bean.videoId
                                        )
                                        val songMap = mutableMapOf(
                                            Pair(
                                                AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                                            )
                                        )
                                        AnalysisUtil.logEvent(
                                            AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap
                                        )

                                        LolAdWrapper.shared.loadAdIfNotCached(
                                            this@MoLikedSongsActivity, AdPlacement.INST_DOWNLOAD
                                        )
                                    }
                                }
                            }
                        }

                        is Request.OnDownloadRemove -> {
                            val currentOfflineBean =
                                App.appOfflineDBManager.getOfflineBeanByID(it.bean.videoId)
                            if (currentOfflineBean != null) {
                                App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
                                it.bean.isOffline = false
                            }
                            requests.trySend(Request.OnUpdateDownloadUi(it.bean))
                            requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
                        }

                        is Request.OnUpdateDownloadUi -> {
                            moreDialog?.updateDownloadBtnUi(it.bean.isOffline)
                        }

                        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
                            ))
                        }

                        is Request.OnUpdateCurrentListItem -> {
                            //更新数据集合当前的item数据
                            updateCurrentItem(it.bean.videoId)
                        }
                    }
                }
                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.backBtn.setOnClickListener {
            finish()
        }
        binding.tryAgainBtn.setOnClickListener {
            requests.trySend(Request.TryAgain)
        }
    }

    private fun showRemoveDownloadDialogHint(bean: PlaylistItem) {
        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(bean))
        }
        cancelBtn.setOnClickListener {
            dialog.dismiss()
        }
    }

    private fun initAdapter() {
        adapter = LikedSongsAdapter(this, myList)
        adapter?.setOnFavoritesItemClickListener(this)
        adapter?.setOnMoreClickListener(this)
        binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.rv.adapter = adapter
    }

    override fun onFavoritesItemClick(position: Int) {
        requests.trySend(Request.OnFavorites(myList[position]))
    }

    override fun onMoreClick(position: Int) {
        moreDialog = ListMoreBottomSheetDialog(
            this@MoLikedSongsActivity,
            myList[position],
            this@MoLikedSongsActivity,
            this@MoLikedSongsActivity
        )
        moreDialog?.setListMoreViewListener(this@MoLikedSongsActivity)
        moreDialog?.show()
    }

    private fun updateFavoriteUi(b: Boolean) {
        if (moreDialog != null) {
            moreDialog?.updateFavoriteUi(b)
        }
    }

    private suspend fun updateCurrentItem(id: String) {
        //更新当前界面的数据集合
        myList.forEach { item ->
            if (item.videoId == id) {
                val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(item.videoId)
                val offlineBean = App.appOfflineDBManager.getOfflineBeanByID(item.videoId)
                item.isFavorite = favoriteBean?.isFavorite ?: false
                item.isOffline = offlineBean?.isOffline ?: false
                item.bytesDownloaded = offlineBean?.bytesDownloaded
                item.size = offlineBean?.size
            }
        }
        myList.forEach { item ->
            if (item.videoId == id) {
                LogTag.LogD(TAG, "updateCurrentItem -> $item")
            }
        }
    }

    override fun onFavoritesClicked(playlistItem: PlaylistItem) {
        requests.trySend(Request.OnFavorites(playlistItem))
    }

    override fun onDownloadClicked(playlistItem: PlaylistItem) {
        requests.trySend(Request.OnDownload(playlistItem))
    }

    override fun onAddToPlaylistClicked(playlistItem: PlaylistItem) {
        requests.trySend(Request.OnAddPlaylist(playlistItem))
    }

    override fun onUpdateAdapterListener(download: Download, playlistItem: PlaylistItem) {
        requests.trySend(Request.OnUpdateCurrentListItem(playlistItem))
    }

    @SuppressLint("NotifyDataSetChanged")
    private suspend fun initData() {
        showLoadingUi()
        val beans = App.appFavoriteDBManager.getAllFavoriteBeans()
        val filteredBeans = beans.filter { it.isFavorite }
        if (filteredBeans.isNotEmpty()) {
            myList.clear()
            filteredBeans.forEach { favoriteItem->
                val offlineBean = App.appOfflineDBManager.getOfflineBeanByID(favoriteItem.videoId)
                myList.add(PlaylistItem(
                    videoId = favoriteItem.videoId,
                    title = favoriteItem.title,
                    name = favoriteItem.name,
                    thumbnail = favoriteItem.thumbnail,
                    isOffline = offlineBean?.isOffline ?: false,
                    isFavorite = favoriteItem.isFavorite,
                    bytesDownloaded = offlineBean?.bytesDownloaded,
                    size = offlineBean?.size
                ))
            }

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

    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
    }
}