package kr.co.vividnext.sodalive.live.room.detail

import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.URLUtil
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.CircleCropTransformation
import coil.transform.RoundedCornersTransformation
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kr.co.vividnext.sodalive.R
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.databinding.FragmentLiveRoomDetailBinding
import kr.co.vividnext.sodalive.databinding.ItemLiveDetailUserSummaryBinding
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.convertDateFormat
import kr.co.vividnext.sodalive.extensions.dpToPx
import org.koin.android.ext.android.inject
import java.util.Locale

class LiveRoomDetailFragment(
    private val roomId: Long,
    private val onClickParticipant: () -> Unit,
    private val onClickReservation: () -> Unit,
    private val onClickModify: (GetRoomDetailResponse) -> Unit,
    private val onClickStart: () -> Unit,
    private val onClickCancel: () -> Unit
) : BottomSheetDialogFragment() {

    private val viewModel: LiveRoomDetailViewModel by inject()

    private lateinit var binding: FragmentLiveRoomDetailBinding
    private var isAllProfileOpen = false

    private lateinit var adapter: LiveRoomDetailAdapter
    private lateinit var loadingDialog: LoadingDialog
    private lateinit var roomDetail: GetRoomDetailResponse

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentLiveRoomDetailBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        loadingDialog = LoadingDialog(requireActivity(), layoutInflater)

        val bottomSheet = dialog?.findViewById<FrameLayout>(
            com.google.android.material.R.id.design_bottom_sheet
        )
        val behavior = BottomSheetBehavior.from<View>(bottomSheet!!)
        behavior.state = BottomSheetBehavior.STATE_EXPANDED

        setupAdapter()
        bindData()
        binding.ivClose.setOnClickListener { dismiss() }
        viewModel.getDetail(roomId) { dismiss() }
    }

    private fun setupAdapter() {
        val recyclerView = binding.rvParticipate
        adapter = LiveRoomDetailAdapter {}

        recyclerView.layoutManager = GridLayoutManager(requireContext(), 5)
        recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(
                outRect: Rect,
                view: View,
                parent: RecyclerView,
                state: RecyclerView.State
            ) {
                super.getItemOffsets(outRect, view, parent, state)

                outRect.top = 13.3f.dpToPx().toInt()
                outRect.bottom = 13.3f.dpToPx().toInt()
            }
        })
        recyclerView.adapter = adapter
    }

    private fun bindData() {
        viewModel.isLoading.observe(viewLifecycleOwner) {
            if (it) {
                loadingDialog.show(resources.displayMetrics.widthPixels)
            } else {
                loadingDialog.dismiss()
            }
        }

        viewModel.toastLiveData.observe(viewLifecycleOwner) {
            it?.let { Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show() }
        }

        viewModel.liveRoomDetailLiveData.observe(viewLifecycleOwner) {
            roomDetail = it
            setRoomDetail(it)
        }
    }

    @SuppressLint("SetTextI18n", "NotifyDataSetChanged")
    private fun setRoomDetail(response: GetRoomDetailResponse) {
        binding.tv19.visibility = if (response.isAdult) {
            View.VISIBLE
        } else {
            View.GONE
        }

        binding.tvTitle.text = response.title
        binding.tvDate.text = response.beginDateTime.convertDateFormat(
            from = "yyyy.MM.dd EEE hh:mm a",
            to = "yyyy년 MM월 dd일 (E) a hh시 mm분",
            inputLocale = Locale.ENGLISH
        )

        if (response.price > 0) {
            binding.tvCan.text = response.price.toString()
            binding.tvCan.setCompoundDrawablesWithIntrinsicBounds(
                0,
                0,
                R.drawable.ic_can,
                0
            )
        } else {
            binding.tvCan.text = "무료"
            binding.tvCan.setCompoundDrawablesWithIntrinsicBounds(
                0,
                0,
                0,
                0
            )
        }

        setManagerProfile(manager = response.manager)

        binding.tvTags.text = response.tags.joinToString(" ") { "#$it" }
        binding.tvContent.text = response.notice

        binding.ivShare.setOnClickListener { shareRoom(response) }
        binding.ivShare2.setOnClickListener { shareRoom(response) }

        if (response.channelName.isNullOrBlank()) {
            binding.tvParticipateExpression.text = "예약자"
            when {
                response.manager.id == SharedPreferenceManager.userId -> {
                    binding.llStartDelete.visibility = View.VISIBLE
                    binding.tvReservationComplete.visibility = View.GONE
                    binding.tvParticipateNow.visibility = View.GONE
                    binding.tvReservation.visibility = View.GONE
                    binding.tvModify.setOnClickListener {
                        onClickModify(roomDetail)
                        dismiss()
                    }
                    binding.tvLiveStart.setOnClickListener {
                        onClickStart()
                        dismiss()
                    }
                    binding.tvLiveCancel.setOnClickListener {
                        onClickCancel()
                        dismiss()
                    }
                }

                response.isPaid -> {
                    binding.tvReservationComplete.visibility = View.VISIBLE
                    binding.tvParticipateNow.visibility = View.GONE
                    binding.tvReservation.visibility = View.GONE
                    binding.llStartDelete.visibility = View.GONE
                }

                else -> {
                    binding.tvReservationComplete.visibility = View.GONE
                    binding.tvParticipateNow.visibility = View.GONE
                    binding.tvReservation.visibility = View.VISIBLE
                    binding.tvReservation.setOnClickListener {
                        onClickReservation()
                        dismiss()
                    }
                    binding.llStartDelete.visibility = View.GONE
                }
            }
        } else {
            binding.tvReservationComplete.visibility = View.GONE
            binding.tvParticipateNow.visibility = View.VISIBLE
            binding.tvReservation.visibility = View.GONE
            binding.tvParticipateNow.setOnClickListener {
                onClickParticipant()
                dismiss()
            }
            binding.llStartDelete.visibility = View.GONE
        }

        if (response.manager.id == SharedPreferenceManager.userId) {
            setParticipantUserSummary(response.participatingUsers)

            binding.llParticipateWrapper.visibility = View.VISIBLE
            binding.tvParticipate.text = response.numberOfParticipants.toString()
            binding.tvTotal.text = "/${response.numberOfParticipantsTotal}"

            binding.tvOpenAllProfile.visibility = if (response.numberOfParticipants <= 0) {
                View.GONE
            } else {
                View.VISIBLE
            }

            binding.tvOpenAllProfile.setOnClickListener {
                isAllProfileOpen = !isAllProfileOpen
                if (isAllProfileOpen) {
                    binding.llProfiles.visibility = View.GONE
                    binding.rvParticipate.visibility = View.VISIBLE
                    binding.tvParticipateExpression.visibility = View.VISIBLE
                    binding.tvOpenAllProfile.text = "닫기"
                    binding.tvOpenAllProfile.setCompoundDrawablesWithIntrinsicBounds(
                        R.drawable.ic_live_detail_top,
                        0,
                        0,
                        0
                    )
                } else {
                    binding.llProfiles.visibility = View.VISIBLE
                    binding.rvParticipate.visibility = View.GONE
                    binding.tvParticipateExpression.visibility = View.GONE
                    binding.tvOpenAllProfile.text = "펼쳐보기"
                    binding.tvOpenAllProfile.setCompoundDrawablesWithIntrinsicBounds(
                        R.drawable.ic_live_detail_bottom,
                        0,
                        0,
                        0
                    )
                }
            }

            adapter.items.addAll(response.participatingUsers)
            adapter.notifyDataSetChanged()
        } else {
            binding.llParticipateWrapper.visibility = View.GONE
        }
    }

    private fun setManagerProfile(manager: GetRoomDetailManager) {
        binding.tvManagerNickname.text = manager.nickname
        binding.tvManagerIntroduce.text = manager.introduce
        binding.ivManagerProfile.load(manager.profileImageUrl) {
            crossfade(true)
            placeholder(R.drawable.ic_place_holder)
            transformations(CircleCropTransformation())
        }

        if (
            manager.websiteUrl.isNullOrBlank() ||
            !URLUtil.isValidUrl(manager.websiteUrl)
        ) {
            binding.ivManagerWebsite.visibility = View.GONE
        } else {
            binding.ivManagerWebsite.visibility = View.VISIBLE
            binding.ivManagerWebsite.setOnClickListener {
                startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(manager.websiteUrl)))
            }
        }

        if (
            manager.blogUrl.isNullOrBlank() ||
            !URLUtil.isValidUrl(manager.blogUrl)
        ) {
            binding.ivManagerBlog.visibility = View.GONE
        } else {
            binding.ivManagerBlog.visibility = View.VISIBLE
            binding.ivManagerBlog.setOnClickListener {
                startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(manager.blogUrl)))
            }
        }

        if (
            manager.instagramUrl.isNullOrBlank() ||
            !URLUtil.isValidUrl(manager.instagramUrl)
        ) {
            binding.ivManagerInstagram.visibility = View.GONE
        } else {
            binding.ivManagerInstagram.visibility = View.VISIBLE
            binding.ivManagerInstagram.setOnClickListener {
                startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(manager.instagramUrl)))
            }
        }

        if (
            manager.youtubeUrl.isNullOrBlank() ||
            !URLUtil.isValidUrl(manager.youtubeUrl)
        ) {
            binding.ivManagerYoutube.visibility = View.GONE
        } else {
            binding.ivManagerYoutube.visibility = View.VISIBLE
            binding.ivManagerYoutube.setOnClickListener {
                startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(manager.youtubeUrl)))
            }
        }

        if (manager.isCreator) {
            binding.tvManagerProfile.visibility = View.VISIBLE
            binding.tvManagerProfile.setOnClickListener {
                val intent = Intent(requireActivity(), UserProfileActivity::class.java)
                intent.putExtra(Constants.EXTRA_USER_ID, manager.id)
                startActivity(intent)
            }
        } else {
            binding.tvManagerProfile.visibility = View.GONE
        }
    }

    private fun setParticipantUserSummary(participatingUsers: List<GetRoomDetailUser>) {
        val userCount = if (participatingUsers.size > 10) {
            10
        } else {
            participatingUsers.size
        }

        for (index in 0 until userCount) {
            val user = participatingUsers[index]
            val itemView = ItemLiveDetailUserSummaryBinding.inflate(layoutInflater)
            itemView.ivProfile.load(user.profileImageUrl) {
                crossfade(true)
                placeholder(R.drawable.ic_place_holder)
                transformations(RoundedCornersTransformation(16.7f.dpToPx()))
            }

            val lp = LinearLayout.LayoutParams(33.3f.dpToPx().toInt(), 33.3f.dpToPx().toInt())
            if (index > 0) {
                lp.setMargins(-16.7f.dpToPx().toInt(), 0, 0, 0)
            }
            itemView.root.layoutParams = lp

            binding.llProfiles.addView(itemView.root)
        }
    }

    private fun shareRoom(response: GetRoomDetailResponse) {
        viewModel.shareRoomLink(
            response.roomId,
            response.isPrivateRoom,
            response.password
        ) {
            val intent = Intent(Intent.ACTION_SEND)
            intent.type = "text/plain"
            intent.putExtra(Intent.EXTRA_TEXT, it)

            val shareIntent = Intent.createChooser(intent, "라이브 공유")
            startActivity(shareIntent)
        }
    }
}
