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.TextView
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
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.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.PlaylistSongsAdapter
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.ActivityPlaylistSongsBinding
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.FileSizeConverter
import melody.offline.music.util.LogTag
import melody.offline.music.view.ListMoreBottomSheetDialog
import org.json.JSONObject

@OptIn(UnstableApi::class)
class MoPlaylistSongsActivity : MoBaseActivity(), ListMoreBottomSheetDialog.ListMoreViewListener,
    ListMoreBottomSheetDialog.UpdateAdapterListener {
    companion object {
        const val PLAYLIST_ID = "playlist_id"
        const val PLAYLIST_TITLE = "playlist_title"
    }

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

    sealed class Request {
        data object TryAgain : Request()
        data class UpdateFavorite(val bean: PlaylistItem) : Request()

        data class OnFavorites(
            val bean: PlaylistItem
        ) : Request()

        data class OnDownload(
            val bean: PlaylistItem
        ) : Request()

        data class OnDownloadRemove(val playlistItem: PlaylistItem) : Request()
        data class OnUpdateDownloadUi(val playlistItem: PlaylistItem) : Request()
        data class OnRemovePlaylist(
            val bean: PlaylistItem
        ) : Request()

    }

    private lateinit var binding: ActivityPlaylistSongsBinding
    private var adapter: PlaylistSongsAdapter? = null
    private var playlistItems: MutableList<PlaylistItem> = mutableListOf()
    private var playlistId = -1
    private var playlistTitle = ""
    private var moreDialog: ListMoreBottomSheetDialog? = null

    override suspend fun main() {
        binding = ActivityPlaylistSongsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        playlistId = intent.getIntExtra(PLAYLIST_ID, -1)
        playlistTitle = intent.getStringExtra(PLAYLIST_TITLE) ?: ""
        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.UpdateFavorite -> {
                            val currentFavoriteBean =
                                App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
                            if (currentFavoriteBean != null) {
                                updateFavoriteUi(currentFavoriteBean.isFavorite)
                            } else {
                                updateFavoriteUi(false)
                            }
                        }

                        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 {
                                val b = FavoriteBean(
                                    videoId = it.bean.videoId,
                                    title = it.bean.title,
                                    name = it.bean.name,
                                    thumbnail = it.bean.thumbnail,
                                    isFavorite = true
                                )
                                App.appFavoriteDBManager.insertFavoriteBean(b)
                                AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
                            }
                            requests.trySend(Request.UpdateFavorite(it.bean))
                        }

                        is Request.OnDownload -> {
                            val id = it.bean.videoId
                            val offBean =
                                App.appOfflineDBManager.getOfflineBeanByID(id)//得到当前ID的本地数据
                            if (offBean != null && offBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
                                showRemoveDownloadDialogHint(it.bean)
                            } else {
                                val isFavorite =
                                    App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
                                //判断是否已经下载了这条数据，已经下载，就直接进行数据库数据存储，反之走下载流程。
                                if (DownloadUtil.downloadResourceExist(id)) {
                                    val favoriteBean = FavoriteBean(
                                        id,
                                        it.bean.title,
                                        it.bean.name,
                                        it.bean.thumbnail,
                                        isFavorite?.isFavorite ?: false
                                    )
                                    insertOfflineData(favoriteBean)
                                    it.bean.isOffline = true//更改状态
                                    requests.trySend(Request.OnUpdateDownloadUi(it.bean))
                                } else {
                                    val downloadRequest = DownloadRequest.Builder(id, id.toUri())
                                        .setCustomCacheKey(id).build()

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

                                        LolAdWrapper.shared.showAdTiming(
                                            this@MoPlaylistSongsActivity, AdPlacement.INST_DOWNLOAD
                                        )
                                        val favoriteBean = FavoriteBean(
                                            id,
                                            it.bean.title,
                                            it.bean.name,
                                            it.bean.thumbnail,
                                            isFavorite?.isFavorite ?: false
                                        )
                                        insertOfflineData(favoriteBean)
                                        val jsonObject = JSONObject()
                                        jsonObject.put(
                                            "download_id", favoriteBean.videoId
                                        )
                                        val songMap = mutableMapOf(
                                            Pair(
                                                AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                                            )
                                        )
                                        AnalysisUtil.logEvent(
                                            AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap
                                        )

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

                        is Request.OnDownloadRemove -> {
                            val currentOfflineBean =
                                App.appOfflineDBManager.getOfflineBeanByID(it.playlistItem.videoId)
                            if (currentOfflineBean != null) {
                                App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)

                                it.playlistItem.isOffline = false
                            }

                            requests.trySend(Request.OnUpdateDownloadUi(it.playlistItem))
                        }

                        is Request.OnUpdateDownloadUi -> {
                            moreDialog?.updateDownloadBtnUi(it.playlistItem.isOffline)//更新对话框的ui
                            runOnUiThread {
                                adapter?.notifyDataSetChanged()//更新adapter
                            }
                        }

                        is Request.OnRemovePlaylist -> {
                            App.appPlaylistDBManager.deletePlaylistItem(it.bean)
                            playlistItems.remove(it.bean)
                            runOnUiThread {
                                adapter?.notifyDataSetChanged()//更新adapter
                            }
                        }
                    }
                }
                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()
        }

        try {
            LolAdWrapper.shared.loadAdShowNativeAd(
                this,
                AdPlacement.NATIVE_ME_PAGE_LIST,
                binding.frameAd,
                R.layout.ad_layout_admob_banner,
                R.layout.ad_layout_max_banner
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    private fun initView() {
        binding.titleText.text = playlistTitle
        binding.backBtn.setOnClickListener {
            finish()
        }
        binding.tryAgainBtn.setOnClickListener {
            requests.trySend(Request.TryAgain)
        }
    }


    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.OnRemovePlaylist(playlistItem)
        )
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onUpdateAdapterListener(download: Download, playlistItem: PlaylistItem) {
        if (playlistItem.videoId == download.request.id) {
            playlistItem.isOffline = true
            playlistItem.bytesDownloaded = download.bytesDownloaded
            playlistItem.size = FileSizeConverter(download.bytesDownloaded).formattedSize()
            //更新adapter
            adapter?.notifyDataSetChanged()
        }
    }

    private fun initAdapter() {
        adapter = PlaylistSongsAdapter(this, playlistItems)
        adapter?.setOnMoreClickListener(object : PlaylistSongsAdapter.OnMoreClickListener {
            override fun onMoreClick(position: Int) {
                moreDialog =
                    ListMoreBottomSheetDialog(
                        this@MoPlaylistSongsActivity,
                        playlistItems[position],
                        this@MoPlaylistSongsActivity,
                        this@MoPlaylistSongsActivity,
                        true
                    )
                moreDialog?.setListMoreViewListener(this@MoPlaylistSongsActivity)
                moreDialog?.show()
            }
        })
        binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.rv.adapter = adapter
    }

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

        //根据list id获取所有的item数据
        val items = App.appPlaylistDBManager.getPlaylistItems(playlistId)
        App.appFavoriteDBManager.getAllFavoriteBeans().map {
            LogTag.LogD(TAG, "getAllFavoriteBeans->$it")
        }
        //更新收藏与喜欢
        val updatedPlaylistItems = items.map { item ->
            val offlineBean = App.appOfflineDBManager.getOfflineBeanByID(item.videoId)
            val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(item.videoId)

            item.copy(
                isOffline = offlineBean?.isOffline ?: false,
                isFavorite = favoriteBean?.isFavorite ?: false,
                bytesDownloaded = offlineBean?.bytesDownloaded,
                size = offlineBean?.size
            )
        }
        App.appPlaylistDBManager.updatePlaylistItems(updatedPlaylistItems)

        playlistItems.clear()
        playlistItems.addAll(updatedPlaylistItems)
        if (playlistItems.size > 0) {
            showDataUi()
        } else {
            showNoContentUi()
        }
        if (adapter != null) {
            adapter?.notifyDataSetChanged()
        }
    }

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

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

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