package kr.co.vividnext.sodalive.audio_content.detail

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.RelativeLayout
import android.widget.SeekBar
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.CircleCropTransformation
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.google.gson.Gson
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
import kr.co.vividnext.sodalive.audio_content.PurchaseOption
import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentFragment
import kr.co.vividnext.sodalive.audio_content.modify.AudioContentModifyActivity
import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderConfirmDialog
import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderFragment
import kr.co.vividnext.sodalive.audio_content.order.OrderType
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.base.SodaDialog
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.common.Utils
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentDetailBinding
import kr.co.vividnext.sodalive.explorer.profile.CreatorFollowNotifyFragment
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.moneyFormat
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationDialog
import kr.co.vividnext.sodalive.mypage.auth.Auth
import kr.co.vividnext.sodalive.mypage.auth.AuthVerifyRequest
import kr.co.vividnext.sodalive.mypage.auth.BootpayResponse
import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity
import kr.co.vividnext.sodalive.mypage.can.payment.CanPaymentTempActivity
import kr.co.vividnext.sodalive.report.ReportType
import org.koin.android.ext.android.inject
import kotlin.math.ceil

class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBinding>(
    ActivityAudioContentDetailBinding::inflate
) {
    private val viewModel: AudioContentDetailViewModel by inject()

    private lateinit var loadingDialog: LoadingDialog
    private lateinit var creatorOtherContentAdapter: OtherContentAdapter
    private lateinit var sameThemeOtherContentAdapter: OtherContentAdapter

    private var audioContentId: Long = 0
    private var isAlertPreview = false
    private val audioContentReceiver = AudioContentReceiver()

    private var creatorId: Long = 0
    private val handler = Handler(Looper.getMainLooper())

    private var refresh = false
    private var title = ""

    private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    private lateinit var audioContent: GetAudioContentDetailResponse
    private lateinit var orderType: OrderType
    private lateinit var imm: InputMethodManager

    @SuppressLint("SetTextI18n")
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        binding.scrollView.scrollTo(0, 0)
        binding.sbProgress.progress = 0
        binding.ivPlayOrPause.setImageResource(0)
        binding.tvTotalDuration.text = " / 00:00:00"
        binding.tvCurrentDuration.text = "00:00:00"
        binding.rlPreviewAlert.visibility = View.GONE

        audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
        viewModel.getAudioContentDetail(audioContentId = audioContentId) { finish() }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
        super.onCreate(savedInstanceState)

        imm = getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager

        if (audioContentId <= 0) {
            Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
            finish()
        }

        activityResultLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            if (it.resultCode == Activity.RESULT_OK) {
                contentOrder(audioContent, orderType)
            }
        }

        bindData()
        viewModel.getAudioContentDetail(audioContentId = audioContentId) { finish() }
    }

    override fun onResume() {
        super.onResume()
        val intentFilter = IntentFilter(Constants.ACTION_AUDIO_CONTENT_RECEIVER)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(audioContentReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)
        } else {
            registerReceiver(audioContentReceiver, intentFilter)
        }

        if (refresh) {
            viewModel.getAudioContentDetail(audioContentId = audioContentId) { finish() }
        }
    }

    override fun onPause() {
        unregisterReceiver(audioContentReceiver)
        super.onPause()
    }

    override fun setupView() {
        loadingDialog = LoadingDialog(this, layoutInflater)
        binding.tvBack.text = "콘텐츠 상세"
        binding.tvBack.setOnClickListener { finish() }
        binding.ivClosePreviewAlert.setOnClickListener { viewModel.toggleShowPreviewAlert() }
        binding.ivMenu.setOnClickListener {
            showOptionMenu()
        }

        creatorOtherContentAdapter = OtherContentAdapter {
            val intent = Intent(applicationContext, AudioContentDetailActivity::class.java)
                .apply {
                    putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it)
                    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                }
            startActivity(intent)
        }

        binding.rvCreatorOtherContent.layoutManager = LinearLayoutManager(
            applicationContext,
            LinearLayoutManager.HORIZONTAL,
            false
        )

        binding.swipeRefreshLayout.setOnRefreshListener {
            viewModel.getAudioContentDetail(
                audioContentId = audioContentId
            ) { finish() }
            binding.swipeRefreshLayout.isRefreshing = false
        }

        binding.rvCreatorOtherContent.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(
                outRect: Rect,
                view: View,
                parent: RecyclerView,
                state: RecyclerView.State
            ) {
                super.getItemOffsets(outRect, view, parent, state)

                when (parent.getChildAdapterPosition(view)) {
                    0 -> {
                        outRect.left = 0
                        outRect.right = 6.7f.dpToPx().toInt()
                    }

                    creatorOtherContentAdapter.itemCount - 1 -> {
                        outRect.left = 6.7f.dpToPx().toInt()
                        outRect.right = 0
                    }

                    else -> {
                        outRect.left = 6.7f.dpToPx().toInt()
                        outRect.right = 6.7f.dpToPx().toInt()
                    }
                }
            }
        })

        binding.rvCreatorOtherContent.adapter = creatorOtherContentAdapter

        sameThemeOtherContentAdapter = OtherContentAdapter {
            val intent = Intent(applicationContext, AudioContentDetailActivity::class.java)
                .apply {
                    putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it)
                    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                }
            startActivity(intent)
        }

        binding.rvThemeOtherContent.layoutManager = LinearLayoutManager(
            applicationContext,
            LinearLayoutManager.HORIZONTAL,
            false
        )

        binding.rvThemeOtherContent.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(
                outRect: Rect,
                view: View,
                parent: RecyclerView,
                state: RecyclerView.State
            ) {
                super.getItemOffsets(outRect, view, parent, state)

                when (parent.getChildAdapterPosition(view)) {
                    0 -> {
                        outRect.left = 0
                        outRect.right = 6.7f.dpToPx().toInt()
                    }

                    creatorOtherContentAdapter.itemCount - 1 -> {
                        outRect.left = 6.7f.dpToPx().toInt()
                        outRect.right = 0
                    }

                    else -> {
                        outRect.left = 6.7f.dpToPx().toInt()
                        outRect.right = 6.7f.dpToPx().toInt()
                    }
                }
            }
        })

        binding.rvThemeOtherContent.adapter = sameThemeOtherContentAdapter

        binding.sbProgress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
            }

            override fun onStartTrackingTouch(p0: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                if (seekBar != null) {
                    val intent = Intent(
                        this@AudioContentDetailActivity,
                        AudioContentPlayService::class.java
                    )
                    intent.action = AudioContentPlayService.MusicAction.PROGRESS.name
                    intent.putExtra(Constants.EXTRA_AUDIO_CONTENT_PROGRESS, seekBar.progress)
                    startService(intent)
                }
            }
        })

        val ivCoverLp = binding.ivCover.layoutParams as RelativeLayout.LayoutParams
        ivCoverLp.width = (screenWidth - 13.3f.dpToPx()).toInt()
        ivCoverLp.height = (screenWidth - 13.3f.dpToPx()).toInt()
        binding.ivCover.layoutParams = ivCoverLp

        val flSoldOutLp = binding.flSoldOut.layoutParams as RelativeLayout.LayoutParams
        flSoldOutLp.width = (screenWidth - 13.3f.dpToPx()).toInt()
        flSoldOutLp.height = (screenWidth - 13.3f.dpToPx()).toInt()
        binding.flSoldOut.layoutParams = flSoldOutLp

        binding.ivPlayLoop.setOnClickListener { viewModel.togglePlayLoop() }
        binding.llDonation.setOnClickListener {
            val dialog = LiveRoomDonationDialog(
                this,
                LayoutInflater.from(this)
            ) { can, message, _ ->
                if (can <= 0) {
                    showToast("1캔 이상 후원하실 수 있습니다.")
                } else if (message.isBlank()) {
                    showToast("함께 보낼 메시지를 입력하세요.")
                } else {
                    donation(can, message)
                }
            }

            dialog.show(screenWidth - 26.7f.dpToPx().toInt())
        }
    }

    private fun donation(can: Int, message: String) {
        viewModel.donation(audioContentId, can, message) {
            viewModel.getAudioContentDetail(audioContentId = audioContentId) { finish() }
        }
    }

    private fun showOptionMenu() {
        val dialog = AudioContentDetailMenuBottomSheetDialog(
            isPin = viewModel.audioContentLiveData.value!!.isPin,
            isCreator = viewModel.audioContentLiveData.value!!
                .creator.creatorId == SharedPreferenceManager.userId,
            onClickPin = {
                if (viewModel.audioContentLiveData.value!!.isPin) {
                    viewModel.unPinContent(audioContentId)
                } else {
                    if (viewModel.audioContentLiveData.value!!.isAvailablePin) {
                        viewModel.pinContent(audioContentId)
                    } else {
                        SodaDialog(this@AudioContentDetailActivity,
                            layoutInflater,
                            "고정 한도 도달",
                            "이 콘텐츠를 고정하시겠어요? " +
                                "채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다." +
                                "이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.",
                            "확인",
                            { viewModel.pinContent(audioContentId) },
                            "취소",
                            {}
                        ).show(screenWidth)
                    }
                }
            },
            onClickModify = {
                refresh = true
                setResult(RESULT_OK)
                startActivity(
                    Intent(applicationContext, AudioContentModifyActivity::class.java)
                        .apply {
                            putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContentId)
                        }
                )
            },
            onClickDelete = { showDeleteDialog() },
            onClickReport = { showReportDialog() }
        )
        dialog.show(supportFragmentManager, dialog.tag)
    }

    private fun showDeleteDialog() {
        AudioContentDeleteDialog(
            this,
            layoutInflater,
            this.title,
            confirmButtonClick = {
                viewModel.deleteAudioContent(audioContentId) {
                    setResult(RESULT_OK)
                    finish()
                }
            }
        ).show(screenWidth)
    }

    private fun showReportDialog() {
        AudioContentReportDialog(this, layoutInflater) {
            viewModel.report(
                type = ReportType.AUDIO_CONTENT,
                contentId = audioContentId,
                reason = it
            )
        }.show(screenWidth)
    }

    @SuppressLint("NotifyDataSetChanged", "SetTextI18n")
    private fun bindData() {
        viewModel.toastLiveData.observe(this) {
            it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
        }

        viewModel.isLoading.observe(this) {
            if (it) {
                loadingDialog.show(screenWidth, "")
            } else {
                loadingDialog.dismiss()
            }
        }

        viewModel.isExpandDetail.observe(this) {
            binding.tvDetail.maxLines = if (it) {
                Int.MAX_VALUE
            } else {
                2
            }
        }

        viewModel.isShowPreviewAlert.observe(this) {
            binding.rlPreviewAlert.visibility = if (it) {
                View.VISIBLE
            } else {
                View.GONE
            }
        }

        viewModel.audioContentLiveData.observe(this) {
            refresh = false
            startService(
                Intent(this, AudioContentPlayService::class.java).apply {
                    action = AudioContentPlayService.MusicAction.INIT.name
                    putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it.contentId)
                }
            )

            title = it.title
            setupCreatorArea(it.creator)
            setupMosaicArea(it.isMosaic)
            setupPlayArea(it)
            setupInfoArea(it)
            setupPurchaseButton(it)
            setupCommentArea(it)
            setupCreatorOtherContentListArea(it.creatorOtherContentList)
            setupSameThemeOtherContentList(it.sameThemeOtherContentList)
        }

        viewModel.isContentPlayLoopLiveData.observe(this) {
            if (it) {
                binding.ivPlayLoop.setImageResource(R.drawable.btn_player_repeat)
            } else {
                binding.ivPlayLoop.setImageResource(R.drawable.btn_player_repeat_done)
            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun setupSameThemeOtherContentList(
        sameThemeOtherContentList: List<OtherContentResponse>
    ) {
        if (sameThemeOtherContentList.isEmpty()) {
            binding.rvThemeOtherContent.visibility = View.GONE
            binding.llThemeOtherContentPreparing.visibility = View.VISIBLE
        } else {
            binding.rvThemeOtherContent.visibility = View.VISIBLE
            binding.llThemeOtherContentPreparing.visibility = View.GONE

            sameThemeOtherContentAdapter.items.clear()
            sameThemeOtherContentAdapter.items.addAll(sameThemeOtherContentList)
            sameThemeOtherContentAdapter.notifyDataSetChanged()
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun setupCreatorOtherContentListArea(
        creatorOtherContentList: List<OtherContentResponse>
    ) {
        if (creatorOtherContentList.isEmpty()) {
            binding.rvCreatorOtherContent.visibility = View.GONE
            binding.llCreatorOtherContentPreparing.visibility = View.VISIBLE
        } else {
            binding.rvCreatorOtherContent.visibility = View.VISIBLE
            binding.llCreatorOtherContentPreparing.visibility = View.GONE

            creatorOtherContentAdapter.items.clear()
            creatorOtherContentAdapter.items.addAll(creatorOtherContentList)
            creatorOtherContentAdapter.notifyDataSetChanged()
        }
    }

    private fun setupCommentArea(response: GetAudioContentDetailResponse) {
        if (
            response.isCommentAvailable &&
            response.contentUrl.isNotBlank() &&
            response.releaseDate == null
        ) {
            binding.llDonation.visibility = View.VISIBLE
            binding.llComment.visibility = View.VISIBLE
            binding.tvCommentCount.text = "${response.commentCount}"

            if (response.commentCount > 0) {
                binding.ivCommentProfile.load(response.commentList[0].profileUrl) {
                    crossfade(true)
                    placeholder(R.drawable.bg_placeholder)
                    transformations(CircleCropTransformation())
                }
                binding.tvCommentText.text = response.commentList[0].comment
                binding.tvCommentText.visibility = View.VISIBLE
                binding.rlInputComment.visibility = View.GONE
                binding.tvSecret.visibility = View.GONE

                binding.llComment.setOnClickListener {
                    showCommentBottomSheetDialog(
                        isShowSecret = response.existOrdered
                    )
                }
            } else {
                binding.tvCommentText.visibility = View.GONE
                binding.rlInputComment.visibility = View.VISIBLE
                binding.ivCommentProfile.load(SharedPreferenceManager.profileImage) {
                    crossfade(true)
                    placeholder(R.drawable.bg_placeholder)
                    transformations(CircleCropTransformation())
                }

                binding.ivCommentSend.setOnClickListener {
                    hideKeyboard()
                    val comment = binding.etComment.text.toString()
                    val isSecret = binding.tvSecret.isSelected
                    viewModel.registerComment(audioContentId, comment, isSecret)

                    binding.etComment.setText("")
                    binding.tvSecret.isSelected = false
                }

                if (response.existOrdered) {
                    binding.tvSecret.visibility = View.VISIBLE
                    binding.tvSecret.setOnClickListener {
                        binding.tvSecret.isSelected = !binding.tvSecret.isSelected
                    }
                } else {
                    binding.tvSecret.visibility = View.GONE
                }

                binding.llComment.setOnClickListener {}
            }
        } else {
            binding.llComment.visibility = View.GONE
            binding.llDonation.visibility = View.GONE
        }
    }

    private fun showCommentBottomSheetDialog(isShowSecret: Boolean) {
        val dialog = AudioContentCommentFragment(
            creatorId = creatorId,
            audioContentId = audioContentId,
            isShowSecret = isShowSecret
        )
        dialog.show(
            supportFragmentManager,
            dialog.tag
        )
    }

    private fun setupPurchaseButton(response: GetAudioContentDetailResponse) {
        if (response.releaseDate != null) {
            binding.llPurchase.visibility = View.VISIBLE
            binding.llPurchasePrice.visibility = View.GONE
            binding.tvPurchaseSoldOut.visibility = View.GONE
            binding.tvReleaseDate.visibility = View.VISIBLE
            binding.llPurchase.background = ContextCompat.getDrawable(
                applicationContext,
                R.drawable.bg_round_corner_5_3_525252
            )

            binding.tvReleaseDate.text = response.releaseDate
        } else if (
            response.price > 0 &&
            !response.existOrdered &&
            response.orderType == null &&
            response.creator.creatorId != SharedPreferenceManager.userId
        ) {
            if (
                response.totalContentCount != null && response.remainingContentCount != null &&
                response.remainingContentCount <= 0
            ) {
                binding.llPurchase.visibility = View.GONE
                binding.tvPurchaseSoldOut.visibility = View.VISIBLE
            } else {
                binding.tvPurchaseSoldOut.visibility = View.GONE
                binding.tvReleaseDate.visibility = View.GONE
                binding.llPurchase.visibility = View.VISIBLE
                binding.llPurchasePrice.visibility = View.VISIBLE
                binding.llPurchase.background = ContextCompat.getDrawable(
                    applicationContext,
                    R.drawable.bg_round_corner_5_3_3bb9f1
                )

                binding.ivCan.visibility = if (SharedPreferenceManager.userId == 17958L) {
                    View.GONE
                } else {
                    View.VISIBLE
                }

                binding.tvPrice.text = if (SharedPreferenceManager.userId == 17958L) {
                    (response.price * 110).moneyFormat()
                } else {
                    response.price.moneyFormat()
                }

                binding.tvUnit.text = if (SharedPreferenceManager.userId == 17958L) {
                    "원으로"
                } else {
                    "캔으로"
                }

                when (response.purchaseOption) {
                    PurchaseOption.BOTH -> {
                        binding.tvStrPurchaseOrRental.text = " 구매하기"
                        binding.llPurchase.setBackgroundResource(
                            R.drawable.bg_round_corner_5_3_3bb9f1
                        )
                    }

                    PurchaseOption.BUY_ONLY -> {
                        binding.tvStrPurchaseOrRental.text = " 소장하기"
                        binding.llPurchase.setBackgroundResource(
                            R.drawable.bg_round_corner_5_3_59548f
                        )
                    }

                    PurchaseOption.RENT_ONLY -> {
                        binding.tvStrPurchaseOrRental.text = " 대여하기"
                        binding.llPurchase.setBackgroundResource(
                            R.drawable.bg_round_corner_5_3_548f7d
                        )
                    }
                }

                val limitedEdition = response.totalContentCount != null &&
                    response.remainingContentCount != null

                binding.llPurchase.setOnClickListener {
                    if (limitedEdition || response.purchaseOption == PurchaseOption.BUY_ONLY) {
                        showOrderConfirmDialog(audioContent = response, OrderType.KEEP)
                    } else if (response.purchaseOption == PurchaseOption.RENT_ONLY) {
                        showOrderConfirmDialog(audioContent = response, OrderType.RENTAL)
                    } else {
                        showOrderDialog(audioContent = response)
                    }
                }
            }
        } else {
            binding.llPurchase.visibility = View.GONE
            binding.tvPurchaseSoldOut.visibility = View.GONE
        }
    }

    @SuppressLint("SetTextI18n")
    private fun setupPlayArea(response: GetAudioContentDetailResponse) {
        Glide
            .with(this)
            .load(response.coverImageUrl)
            .centerCrop()
            .placeholder(R.drawable.bg_black)
            .apply(RequestOptions().override((screenWidth - 13.3f.dpToPx()).toInt()))
            .into(binding.ivCover)

        binding.flSoldOut.visibility = View.GONE
        binding.tvSoldOutBig.visibility = View.GONE
        binding.ivPlayOrPause.visibility = View.GONE
        binding.tvPreviewNo.visibility = View.GONE
        binding.tvTotalDuration.text = " / ${response.duration}"

        isAlertPreview = response.creator.creatorId != SharedPreferenceManager.userId &&
            !response.existOrdered &&
            response.price > 0

        if (
            response.creator.creatorId != SharedPreferenceManager.userId && !response.existOrdered &&
            response.totalContentCount != null && response.remainingContentCount != null &&
            response.remainingContentCount <= 0
        ) {
            binding.flSoldOut.visibility = View.VISIBLE
            binding.tvSoldOutBig.visibility = View.VISIBLE
        } else if (
            response.releaseDate == null &&
            !isAlertPreview ||
            (response.isActivePreview && response.contentUrl.isNotBlank())
        ) {
            binding.ivPlayOrPause.visibility = View.VISIBLE
            binding.ivPlayOrPause.setOnClickListener {
                startService(
                    Intent(this, AudioContentPlayService::class.java).apply {
                        putExtra(
                            Constants.EXTRA_AUDIO_CONTENT_COVER_IMAGE_URL,
                            response.coverImageUrl
                        )
                        putExtra(Constants.EXTRA_AUDIO_CONTENT_URL, response.contentUrl)
                        putExtra(Constants.EXTRA_NICKNAME, response.creator.nickname)
                        putExtra(Constants.EXTRA_AUDIO_CONTENT_TITLE, response.title)
                        putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, response.contentId)
                        putExtra(
                            Constants.EXTRA_AUDIO_CONTENT_CREATOR_ID,
                            response.creator.creatorId
                        )
                        putExtra(Constants.EXTRA_AUDIO_CONTENT_FREE, response.price <= 0)
                        putExtra(
                            Constants.EXTRA_AUDIO_CONTENT_PREVIEW,
                            !response.existOrdered && response.price > 0
                        )
                    }
                )
            }

            binding.ivPlayOrPause.setImageResource(
                if (!isAlertPreview) {
                    R.drawable.btn_audio_content_play
                } else {
                    R.drawable.btn_audio_content_preview_play
                }
            )
        } else if (response.releaseDate == null) {
            binding.tvPreviewNo.visibility = View.VISIBLE
        }
    }

    @SuppressLint("SetTextI18n")
    private fun setupInfoArea(response: GetAudioContentDetailResponse) {
        binding.tvScheduledToOpen.visibility = if (response.releaseDate != null) {
            View.VISIBLE
        } else {
            View.GONE
        }
        binding.tvTheme.text = response.themeStr
        binding.tv19.visibility = if (response.isAdult) {
            View.VISIBLE
        } else {
            View.GONE
        }

        if (response.orderType != null && response.orderType == OrderType.KEEP) {
            binding.tvPurchased.visibility = View.VISIBLE
            binding.tvRental.visibility = View.GONE
            binding.tvRemainingTime.visibility = View.GONE
        } else if (response.orderType != null && response.orderType == OrderType.RENTAL) {
            binding.tvPurchased.visibility = View.GONE
            binding.tvRental.visibility = View.VISIBLE
            binding.tvRemainingTime.visibility = View.VISIBLE
            binding.tvRemainingTime.text = response.remainingTime
        } else {
            binding.tvPurchased.visibility = View.GONE
            binding.tvRental.visibility = View.GONE
            binding.tvRemainingTime.visibility = View.GONE
        }

        binding.tvTitle.text = response.title
        binding.tvDetail.text = response.detail
        binding.tvDetail.setOnClickListener { viewModel.toggleExpandDetail() }

        if (response.tag.isNotBlank()) {
            binding.tvTag.visibility = View.VISIBLE
            binding.tvTag.text = response.tag
        } else {
            binding.tvTag.visibility = View.GONE
        }

        if (response.contentUrl.isNotBlank() && response.releaseDate == null) {
            binding.svActionButtons.visibility = View.VISIBLE
            binding.llLike.visibility = View.VISIBLE
            binding.ivLike.setImageResource(
                if (response.isLike) {
                    R.drawable.ic_audio_content_heart_pressed
                } else {
                    R.drawable.ic_audio_content_heart_normal
                }
            )

            binding.tvLike.text = "${response.likeCount}"
            binding.llLike.setOnClickListener {
                viewModel.likeContent(contentId = audioContentId) {
                    val likeCount = binding.tvLike.text.toString().toInt()
                    if (it) {
                        binding.tvLike.text = "${likeCount + 1}"
                        binding.ivLike.setImageResource(R.drawable.ic_audio_content_heart_pressed)
                    } else {
                        binding.tvLike.text = if (likeCount - 1 < 0) {
                            "0"
                        } else {
                            "${likeCount - 1}"
                        }
                        binding.ivLike.setImageResource(R.drawable.ic_audio_content_heart_normal)
                    }
                }
            }

            binding.tvShare.visibility = View.VISIBLE
            binding.tvShare.setOnClickListener {
                viewModel.shareAudioContent(
                    audioContentId = audioContentId,
                    contentImage = response.coverImageUrl,
                    contentTitle = "${response.title} - ${response.creator.nickname}"
                ) {
                    val intent = Intent(Intent.ACTION_SEND)
                    intent.type = "text/plain"
                    intent.putExtra(Intent.EXTRA_TEXT, it)

                    val shareIntent = Intent.createChooser(intent, "오디오콘텐츠 공유")
                    startActivity(shareIntent)
                }
            }
        } else {
            binding.svActionButtons.visibility = View.GONE
            binding.llLike.visibility = View.GONE
            binding.tvShare.visibility = View.GONE
        }

        if (response.totalContentCount != null && response.remainingContentCount != null) {
            binding.rlLimitedEdition.visibility = View.VISIBLE

            if (response.existOrdered) {
                binding.tvRemaining.visibility = View.GONE
                binding.tvTotalCount.visibility = View.VISIBLE
                binding.tvRemainingCount.visibility = View.VISIBLE

                binding.tvRemainingCount.text = "${response.orderSequence}"
                binding.tvTotalCount.text = " / ${response.totalContentCount}"
            } else if (response.remainingContentCount <= 0) {
                binding.tvRemainingCount.visibility = View.GONE
                binding.tvTotalCount.visibility = View.GONE
                binding.tvRemaining.visibility = View.GONE

                binding.tvSoldOutSmall.visibility = View.VISIBLE
            } else {
                binding.tvRemainingCount.visibility = View.VISIBLE
                binding.tvRemaining.visibility = View.VISIBLE
                binding.tvTotalCount.visibility = View.GONE

                binding.tvRemainingCount.text = "${response.remainingContentCount}"
            }
        } else {
            binding.rlLimitedEdition.visibility = View.GONE
        }
    }

    private fun setupMosaicArea(isMosaic: Boolean) {
        if (isMosaic) {
            binding.alert19Bg.visibility = View.VISIBLE
            binding.llAlert19.visibility = View.VISIBLE

            binding.tvAuth.setOnClickListener {
                Auth.auth(this, applicationContext) { data ->
                    val bootpayResponse = Gson().fromJson(data, BootpayResponse::class.java)
                    val request = AuthVerifyRequest(receiptId = bootpayResponse.data.receiptId)
                    runOnUiThread {
                        viewModel.authVerify(audioContentId = audioContentId, request = request)
                    }
                }
            }
        } else {
            binding.alert19Bg.visibility = View.GONE
            binding.llAlert19.visibility = View.GONE
            binding.tvAuth.setOnClickListener {}
        }
    }

    private fun setupCreatorArea(creator: AudioContentCreator) {
        this.creatorId = creator.creatorId
        binding.rlProfile.setOnClickListener {
            startActivity(
                Intent(applicationContext, UserProfileActivity::class.java).apply {
                    putExtra(Constants.EXTRA_USER_ID, creator.creatorId)
                }
            )
        }

        binding.ivProfile.load(creator.profileImageUrl) {
            crossfade(true)
            placeholder(R.drawable.bg_placeholder)
            transformations(CircleCropTransformation())
        }

        binding.tvProfileNickname.text = creator.nickname

        if (creator.creatorId != SharedPreferenceManager.userId) {
            binding.ivFollow.visibility = View.VISIBLE

            if (creator.isFollow) {
                binding.ivFollow.setImageResource(
                    if (creator.isNotify) {
                        R.drawable.btn_following_big
                    } else {
                        R.drawable.btn_following_no_alarm_big
                    }
                )

                binding.ivFollow.setOnClickListener {
                    val notifyFragment = CreatorFollowNotifyFragment(
                        onClickNotifyAll = {
                            viewModel.follow(
                                contentId = audioContentId,
                                creatorId = creator.creatorId,
                                follow = true,
                                notify = true
                            )
                        },
                        onClickNotifyNone = {
                            viewModel.follow(
                                contentId = audioContentId,
                                creatorId = creator.creatorId,
                                follow = true,
                                notify = false
                            )
                        },
                        onClickUnFollow = {
                            viewModel.follow(
                                contentId = audioContentId,
                                creatorId = creator.creatorId,
                                follow = false,
                                notify = false
                            )
                        }
                    )

                    if (notifyFragment.isAdded) return@setOnClickListener
                    notifyFragment.show(supportFragmentManager, notifyFragment.tag)
                }
            } else {
                binding.ivFollow.setImageResource(R.drawable.btn_follow_big)
                binding.ivFollow.setOnClickListener {
                    viewModel.follow(contentId = audioContentId, creatorId = creator.creatorId)
                }
            }
        } else {
            binding.ivFollow.visibility = View.GONE
        }
    }

    private fun showOrderDialog(audioContent: GetAudioContentDetailResponse) {
        val dialog = AudioContentOrderFragment(
            price = audioContent.price,
            onClickKeep = { showOrderConfirmDialog(audioContent, OrderType.KEEP) },
            onClickRental = { showOrderConfirmDialog(audioContent, OrderType.RENTAL) }
        )

        dialog.show(
            supportFragmentManager,
            dialog.tag
        )
    }

    private fun showOrderConfirmDialog(
        audioContent: GetAudioContentDetailResponse,
        orderType: OrderType
    ) {
        AudioContentOrderConfirmDialog(
            activity = this,
            layoutInflater = layoutInflater,
            title = audioContent.title,
            theme = audioContent.themeStr,
            coverImageUrl = audioContent.coverImageUrl,
            profileImageUrl = audioContent.creator.profileImageUrl,
            nickname = audioContent.creator.nickname,
            duration = audioContent.duration,
            orderType = orderType,
            price = if (
                audioContent.purchaseOption == PurchaseOption.BOTH &&
                orderType == OrderType.RENTAL
            ) {
                ceil(audioContent.price * 0.7).toInt()
            } else {
                audioContent.price
            },
            confirmButtonClick = {
                startService(
                    Intent(this, AudioContentPlayService::class.java).apply {
                        action = AudioContentPlayService.MusicAction.CONDITIONAL_STOP.name
                        putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContent.contentId)
                    }
                )

                binding.rlPreviewAlert.visibility = View.GONE

                if (SharedPreferenceManager.userId == 17958L) {
                    this@AudioContentDetailActivity.audioContent = audioContent
                    this@AudioContentDetailActivity.orderType = orderType
                    activityResultLauncher.launch(
                        Intent(applicationContext, CanPaymentTempActivity::class.java).apply {
                            putExtra("title", audioContent.title)
                            putExtra(
                                "can",
                                if (orderType == OrderType.RENTAL) {
                                    ceil(audioContent.price * 0.7).toInt()
                                } else {
                                    audioContent.price
                                }
                            )
                        }
                    )
                } else {
                    contentOrder(audioContent, orderType)
                }
            },
        ).show(screenWidth)
    }

    private fun contentOrder(
        audioContent: GetAudioContentDetailResponse,
        orderType: OrderType
    ) {
        viewModel.order(
            contentId = audioContent.contentId,
            orderType = orderType
        ) {
            val intent = Intent(applicationContext, CanChargeActivity::class.java)
            intent.putExtra(Constants.EXTRA_GO_TO_PREV_PAGE, true)
            startActivity(intent)
        }
    }

    private fun hideKeyboard() {
        handler.postDelayed({
            imm.hideSoftInputFromWindow(
                window.decorView.applicationWindowToken,
                InputMethodManager.HIDE_NOT_ALWAYS
            )
        }, 100)
    }

    inner class AudioContentReceiver : BroadcastReceiver() {
        @SuppressLint("SetTextI18n")
        override fun onReceive(context: Context?, intent: Intent?) {
            val nextAction = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                intent?.getSerializableExtra(
                    Constants.EXTRA_AUDIO_CONTENT_NEXT_ACTION,
                    AudioContentPlayService.MusicAction::class.java
                )
            } else {
                intent?.getSerializableExtra(Constants.EXTRA_AUDIO_CONTENT_NEXT_ACTION)
            }

            val duration = intent?.getIntExtra(Constants.EXTRA_AUDIO_CONTENT_DURATION, 0)
            val progress = intent?.getIntExtra(Constants.EXTRA_AUDIO_CONTENT_PROGRESS, 0)
            val contentId = intent?.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
            val isPlaying = intent?.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_PLAYING, false)
            val changeUi = intent?.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_CHANGE_UI, false)
            val alertPreview = intent?.getBooleanExtra(
                Constants.EXTRA_AUDIO_CONTENT_ALERT_PREVIEW,
                false
            )
            val isLoading = intent?.getBooleanExtra(
                Constants.EXTRA_AUDIO_CONTENT_LOADING,
                false
            )

            viewModel.isLoading.value = isLoading ?: false

            if (this@AudioContentDetailActivity.audioContentId == contentId) {
                runOnUiThread {
                    if (changeUi != null && changeUi) {
                        binding.ivPlayOrPause.setImageResource(
                            if (isPlaying != null && isPlaying) {
                                R.drawable.btn_audio_content_pause
                            } else {
                                if (isAlertPreview) {
                                    R.drawable.btn_audio_content_preview_play
                                } else {
                                    R.drawable.btn_audio_content_play
                                }
                            }
                        )
                    }
                }

                if (duration != null && duration > 0) {
                    binding.sbProgress.max = duration
                    binding.tvTotalDuration.text = " / ${Utils.convertDurationToString(duration)}"
                }

                if (progress != null && progress > 0) {
                    binding.sbProgress.progress = progress
                    binding.tvCurrentDuration.text = Utils.convertDurationToString(progress)
                }

                if (alertPreview != null && alertPreview && isAlertPreview) {
                    viewModel.toggleShowPreviewAlert()
                }

                if (nextAction != null) {
                    startService(
                        Intent(
                            this@AudioContentDetailActivity,
                            AudioContentPlayService::class.java
                        ).apply {
                            action = (nextAction as AudioContentPlayService.MusicAction).name
                        }
                    )
                }
            }
        }
    }
}
