package com.adealink.weparty.share.poster.comp

import android.Manifest
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.net.toUri
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.AppBase
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.ext.copyToAlbum
import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.view.ViewComponent
import com.adealink.frame.mvvm.viewmodel.viewModels
import com.adealink.frame.util.AppUtil
import com.adealink.frame.util.ViewShotUtil
import com.adealink.frame.util.formatTime
import com.adealink.frame.util.getFileName
import com.adealink.weparty.commonui.BaseActivity
import com.adealink.weparty.commonui.ext.hide
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.toast.util.showToast
import com.adealink.weparty.commonui.widget.CommonDialog
import com.adealink.weparty.constant.STORAGE_PERMISSION_DIALOG
import com.adealink.weparty.module.profile.ProfileModule
import com.adealink.weparty.module.profile.data.UserPlaymateSkill
import com.adealink.weparty.permission.PermissionUtils
import com.adealink.weparty.share.R
import com.adealink.weparty.share.data.LastOrderData
import com.adealink.weparty.share.data.TAG_SHARE_POSTER
import com.adealink.weparty.share.databinding.LayoutSharePosterShotBinding
import com.adealink.weparty.share.poster.data.PhotoItemData
import com.adealink.weparty.share.poster.viewmodel.PosterViewModel
import com.adealink.weparty.storage.file.FilePath
import com.adealink.weparty.url.UrlConfig
import com.adealink.weparty.util.fetchImage
import com.adealink.weparty.util.formatStar
import com.adealink.weparty.util.suspendGenerateQRCode
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import com.adealink.weparty.R as APP_R

class SharePosterComp(
    lifecycleOwner: LifecycleOwner,
    val rootView: View
) : ViewComponent(lifecycleOwner) {

    private val posterViewModel by viewModels<PosterViewModel>()


    private var lastOrder: LastOrderData? = null
    private var selectPhotoItemData: PhotoItemData? = null
    private var selectSkillList: List<UserPlaymateSkill>? = null

    //保存图片需要检查存储权限
    @SuppressLint("CheckResult")
    fun sharePoster(
        selectPhotoItemData: PhotoItemData? = null,
        selectSkillList: List<UserPlaymateSkill>? = null
    ) {
        this.selectPhotoItemData = selectPhotoItemData
        this.selectSkillList = selectSkillList
        val context = activity ?: return
        val permission = getMediaImagePermission()
        if (PermissionUtils.hasPermissions(context, *permission)) {
            sharePosterInner()
        } else {
            PermissionUtils.getRxPermissions(context)
                .request(*permission).subscribe { granted ->
                    if (granted) {
                        sharePosterInner()
                    } else {
                        showPermissionNoGrantedDialog()
                    }
                }
        }
    }

    private fun sharePosterInner() {
        (activity as? BaseActivity)?.showLoading()
        viewLifecycleOwner.lifecycleScope.launch {
            if (lastOrder == null) {
                lastOrder = posterViewModel.getLastOrder()
            }

            val link = UrlConfig.posterShare.toUri().buildUpon().apply {
                appendQueryParameter("id", ProfileModule.getMyUid())
                appendQueryParameter("share", "app")
            }.toString()

            var qrCodeImg: Bitmap?
            try {
                qrCodeImg = suspendGenerateQRCode(link)
                val shotView = inflateShotView(qrCodeImg)
                if (shotView == null) {
                    throw IllegalStateException("inflateShotView fail")
                }
                val posterPath = generatePosterBitmap(shotView)
                savePosterToAlbum(posterPath)
                showToast(R.string.share_save_poster_success)
            } catch (e: Exception) {
                Log.d(TAG_SHARE_POSTER, "sharePoster fail, for ${e.message}", e)
                showToast(R.string.share_save_poster_fail)
            } finally {
                (activity as? BaseActivity)?.dismissLoading()
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private suspend fun inflateShotView(qrCode: Bitmap?): View? {
        return withContext(Dispatcher.UI) {
            //加载模版布局
            val fragmentContentView = (rootView as? ViewGroup) ?: return@withContext null
            var shotViewContainer =
                fragmentContentView.findViewById<FrameLayout>(APP_R.id.id_shot_view_container)
            if (shotViewContainer == null) {
                shotViewContainer = FrameLayout(fragmentContentView.context).apply {
                    id = APP_R.id.id_shot_view_container
                    visibility = View.INVISIBLE
                }
                fragmentContentView.addView(shotViewContainer, ViewGroup.LayoutParams(0, 0))
            }

            var shotView = shotViewContainer.findViewById<View>(APP_R.id.id_shot_view)
            if (shotView == null) {
                shotView =
                    LayoutInflater.from(context)
                        .inflate(R.layout.layout_share_poster_shot, null, false)
                shotView.id = APP_R.id.id_shot_view
                shotViewContainer.addView(
                    shotView,
                    FrameLayout.LayoutParams(
                        SHOT_WIDTH,
                        SHOT_HEIGHT
                    )
                )
            }

            val shotViewBinding = LayoutSharePosterShotBinding.bind(shotView)
            shotViewBinding.tvNews.text = lastOrder?.let {
                getCompatString(
                    R.string.share_poster_news,
                    formatTime(it.finishTime, "MM.dd.yyyy"),
                    it.nickname,
                    it.categoryName
                )
            } ?: getCompatString(R.string.share_poster_default_news)

            val myUserInfo = ProfileModule.getMyUserInfo()
            shotViewBinding.tvName.text = myUserInfo?.nickName
            shotViewBinding.vGender.setGender(myUserInfo?.gender)
            shotViewBinding.vGender.setAge(myUserInfo?.age)
            shotViewBinding.ivPhoto.setImageBitmap(fetchImage(selectPhotoItemData?.data?.url))
            shotViewBinding.tvEvaluate.text = formatStar(myUserInfo?.star)
            shotViewBinding.tvSummary.text = myUserInfo?.intro

            val item1 = selectSkillList?.getOrNull(0)
            if (item1 != null) {
                shotViewBinding.vGame1.root.show()
                shotViewBinding.vGame1.ivGame.setImageBitmap(fetchImage(item1.icon))
                shotViewBinding.vGame1.tvGame.text = item1.name
            } else {
                shotViewBinding.vGame1.root.hide()
            }

            val item2 = selectSkillList?.getOrNull(1)
            if (item2 != null) {
                shotViewBinding.vGame2.root.show()
                shotViewBinding.vGame2.ivGame.setImageBitmap(fetchImage(item2.icon))
                shotViewBinding.vGame2.tvGame.text = item2.name
            } else {
                shotViewBinding.vGame2.root.hide()
            }

            val item3 = selectSkillList?.getOrNull(2)
            if (item3 != null) {
                shotViewBinding.vGame3.root.show()
                shotViewBinding.vGame3.ivGame.setImageBitmap(fetchImage(item3.icon))
                shotViewBinding.vGame3.tvGame.text = item3.name
            } else {
                shotViewBinding.vGame3.root.hide()
            }

            if (qrCode != null && !qrCode.isRecycled) {
                shotViewBinding.ivQrCode.setImageBitmap(qrCode)
            }

            shotView
        }
    }

    private suspend fun generatePosterBitmap(shotView: View): String? {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            delay(200)
            //创建 Bitmap 并绘制
            val savePath = FilePath.shareImagePath
            if (savePath.isNullOrEmpty()) {
                Log.e(TAG_SHARE_POSTER, "shotViewAndSave fail, for shareImagePath is null.")
                return@withContext null
            }
            val shotPath = ViewShotUtil.of(shotView)
                .setSavePath(savePath)
                .setFilename(SHOT_IMG_NAME)
                .minWidth(SHOT_WIDTH)
                .maxWidth(SHOT_WIDTH)
                .toPNG()
                .save()
            if (shotPath.isNullOrEmpty()) {
                Log.e(
                    TAG_SHARE_POSTER,
                    "shotViewAndSave fail, for ViewShot fail."
                )
                return@withContext null
            }
            return@withContext shotPath
        }
    }

    private suspend fun savePosterToAlbum(posterPath: String?) {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            if (posterPath.isNullOrEmpty()) {
                Log.d(TAG_SHARE_POSTER, "saveImage fail, for shotView fail.")
                return@withContext
            }
            val imgName = getFileName(posterPath)
            if (imgName.isNullOrEmpty()) {
                Log.d(TAG_SHARE_POSTER, "saveImage fail, for can not find imgName.")
                return@withContext
            }
            withContext(Dispatcher.WENEXT_THREAD_POOL) {
                File(posterPath).copyToAlbum(AppUtil.appContext, imgName, AppBase.appName)
            }
        }
    }


    private fun getMediaImagePermission(): Array<String> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arrayOf(Manifest.permission.READ_MEDIA_IMAGES)
        } else {
            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }

    private fun showPermissionNoGrantedDialog() {
        val permissionDialog = CommonDialog.Builder()
            .message(getCompatString(APP_R.string.toast_storage_permission_no_granted))
            .onPositive {
                PermissionUtils.startPermissionSettingActivity(activity)
            }
            .dismissAfterClick(true)
            .setShowDefaultCancel(true)
            .build()
        permissionDialog.show(fragmentManager, STORAGE_PERMISSION_DIALOG)
    }

    companion object {

        private const val SHOT_IMG_NAME = "poster"
        private const val SHOT_WIDTH = 750 //像素
        private const val SHOT_HEIGHT = 1492 //像素
    }

}