package kr.co.vividnext.sodalive.main

import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import coil.load
import coil.transform.RoundedCornersTransformation
import com.google.firebase.messaging.FirebaseMessaging
import com.gun0912.tedpermission.PermissionListener
import com.gun0912.tedpermission.normal.TedPermission
import com.orhanobut.logger.Logger
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
import kr.co.vividnext.sodalive.audio_content.main.AudioContentMainFragment
import kr.co.vividnext.sodalive.base.BaseActivity
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.ActivityMainBinding
import kr.co.vividnext.sodalive.databinding.ItemMainTabBinding
import kr.co.vividnext.sodalive.explorer.ExplorerFragment
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.live.LiveFragment
import kr.co.vividnext.sodalive.message.MessageFragment
import kr.co.vividnext.sodalive.mypage.MyPageFragment
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog
import org.koin.android.ext.android.inject

class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {

    private val viewModel: MainViewModel by inject()

    private lateinit var liveFragment: LiveFragment
    private lateinit var loadingDialog: LoadingDialog
    private lateinit var notificationSettingsDialog: NotificationSettingsDialog

    private val handler = Handler(Looper.getMainLooper())
    private val audioContentReceiver = AudioContentReceiver()

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        executeDeeplink(intent)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        checkPermissions()
        pushTokenUpdate()
        gaidUpdate()

        getMemberInfo()
        getEventPopup()

        handler.postDelayed({ executeDeeplink(intent) }, 500)
    }

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

        startService(
            Intent(this, AudioContentPlayService::class.java).apply {
                action = AudioContentPlayService.MusicAction.INIT.name
            }
        )
    }

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

    override fun setupView() {
        loadingDialog = LoadingDialog(this, layoutInflater)
        liveFragment = LiveFragment()

        notificationSettingsDialog = NotificationSettingsDialog(
            this,
            layoutInflater
        ) { isNotifiedLive, isNotifiedUploadContent, isNotifiedMessage ->
            viewModel.updateNotificationSettings(
                isNotifiedLive,
                isNotifiedUploadContent,
                isNotifiedMessage
            )
        }

        setupBottomTabLayout()
    }

    private fun executeDeeplink(intent: Intent) {
        val bundle = intent.getBundleExtra(Constants.EXTRA_DATA)
        if (bundle != null) {
            try {
                val roomId = bundle.getLong(Constants.EXTRA_ROOM_ID)
                val channelId = bundle.getLong(Constants.EXTRA_USER_ID)
                val messageId = bundle.getLong(Constants.EXTRA_MESSAGE_ID)
                val contentId = bundle.getLong(Constants.EXTRA_AUDIO_CONTENT_ID)
                val isLiveReservation = bundle.getBoolean(Constants.EXTRA_LIVE_RESERVATION_RESPONSE)

                if (roomId > 0) {
                    changeFragment(MainViewModel.CurrentTab.LIVE)
                    setTabSelected(binding.tabLive, isSelected = true)
                    setTabSelected(binding.tabExplorer, isSelected = false)
                    setTabSelected(binding.tabMessage, isSelected = false)
                    setTabSelected(binding.tabMy, isSelected = false)
                    setTabSelected(binding.tabContent, isSelected = false)

                    handler.postDelayed({
                        if (isLiveReservation) {
                            liveFragment.reservationRoom(roomId)
                        } else {
                            liveFragment.enterLiveRoom(roomId)
                        }
                    }, 500)
                } else if (channelId > 0) {
                    val nextIntent = Intent(applicationContext, UserProfileActivity::class.java)
                    nextIntent.putExtra(Constants.EXTRA_USER_ID, channelId)
                    startActivity(nextIntent)
                } else if (contentId > 0) {
                    val nextIntent = Intent(
                        applicationContext,
                        AudioContentDetailActivity::class.java
                    )
                    nextIntent.putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, contentId)
                    startActivity(nextIntent)
                } else if (messageId > 0) {
                    handler.postDelayed({
                        changeFragment(MainViewModel.CurrentTab.MESSAGE)
                        setTabSelected(binding.tabLive, isSelected = false)
                        setTabSelected(binding.tabExplorer, isSelected = false)
                        setTabSelected(binding.tabMessage, isSelected = true)
                        setTabSelected(binding.tabMy, isSelected = false)
                        setTabSelected(binding.tabContent, isSelected = false)
                    }, 500)
                }
            } catch (_: IllegalStateException) {
            }
        }
    }

    private fun setupBottomTabLayout() {
        setupTab(
            binding = binding.tabContent,
            title = "콘텐츠",
            imageSrc = R.drawable.ic_tabbar_content,
            colorStateList = ContextCompat.getColorStateList(
                applicationContext,
                R.color.color_tabbar_title
            ),
            tab = MainViewModel.CurrentTab.CONTENT
        )

        setupTab(
            binding = binding.tabLive,
            title = "라이브",
            imageSrc = R.drawable.ic_tabbar_live,
            colorStateList = ContextCompat.getColorStateList(
                applicationContext,
                R.color.color_tabbar_title
            ),
            tab = MainViewModel.CurrentTab.LIVE
        )

        setupTab(
            binding = binding.tabExplorer,
            title = "탐색",
            imageSrc = R.drawable.ic_tabbar_explorer,
            colorStateList = ContextCompat.getColorStateList(
                applicationContext,
                R.color.color_tabbar_title
            ),
            tab = MainViewModel.CurrentTab.EXPLORER
        )

        setupTab(
            binding = binding.tabMessage,
            title = "메시지",
            imageSrc = R.drawable.ic_tabbar_message,
            colorStateList = ContextCompat.getColorStateList(
                applicationContext,
                R.color.color_tabbar_title
            ),
            tab = MainViewModel.CurrentTab.MESSAGE
        )

        setupTab(
            binding = binding.tabMy,
            title = "마이",
            imageSrc = R.drawable.ic_tabbar_my,
            colorStateList = ContextCompat.getColorStateList(
                applicationContext,
                R.color.color_tabbar_title
            ),
            tab = MainViewModel.CurrentTab.MY
        )

        viewModel.currentTab.observe(this) {
            setTabSelected(binding.tabContent, isSelected = false)
            setTabSelected(binding.tabLive, isSelected = false)
            setTabSelected(binding.tabExplorer, isSelected = false)
            setTabSelected(binding.tabMessage, isSelected = false)
            setTabSelected(binding.tabMy, isSelected = false)

            changeFragment(it)
            when (it) {
                MainViewModel.CurrentTab.CONTENT -> {
                    setTabSelected(binding.tabContent, isSelected = true)
                }

                MainViewModel.CurrentTab.LIVE -> {
                    setTabSelected(binding.tabLive, isSelected = true)
                }

                MainViewModel.CurrentTab.EXPLORER -> {
                    setTabSelected(binding.tabExplorer, isSelected = true)
                }

                MainViewModel.CurrentTab.MESSAGE -> {
                    setTabSelected(binding.tabMessage, isSelected = true)
                }

                MainViewModel.CurrentTab.MY -> {
                    setTabSelected(binding.tabMy, isSelected = true)
                }

                else -> {
                }
            }
        }
    }

    private fun setupTab(
        binding: ItemMainTabBinding,
        title: String,
        imageSrc: Int,
        colorStateList: ColorStateList?,
        tab: MainViewModel.CurrentTab
    ) {
        binding.tvTab.text = title
        binding.tvTab.setTextColor(colorStateList)
        binding.ivTab.setImageResource(imageSrc)
        binding.root.setOnClickListener { viewModel.clickTab(tab) }
    }

    private fun setTabSelected(binding: ItemMainTabBinding, isSelected: Boolean) {
        binding.tvTab.isSelected = isSelected
        binding.ivTab.isSelected = isSelected

        val fontRes = if (isSelected) {
            R.font.gmarket_sans_bold
        } else {
            R.font.gmarket_sans_light
        }
        binding.tvTab.typeface = ResourcesCompat.getFont(applicationContext, fontRes)
    }

    private fun changeFragment(currentTab: MainViewModel.CurrentTab) {
        val tag = currentTab.toString()

        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()

        val currentFragment = fragmentManager.primaryNavigationFragment
        if (currentFragment != null) {
            fragmentTransaction.hide(currentFragment)
        }

        var fragment = fragmentManager.findFragmentByTag(tag)
        if (fragment == null) {
            fragment = when (currentTab) {
                MainViewModel.CurrentTab.LIVE -> liveFragment
                MainViewModel.CurrentTab.CONTENT -> AudioContentMainFragment()
                MainViewModel.CurrentTab.EXPLORER -> ExplorerFragment()
                MainViewModel.CurrentTab.MESSAGE -> MessageFragment()
                MainViewModel.CurrentTab.MY -> MyPageFragment()
            }

            fragmentTransaction.add(R.id.fl_container, fragment, tag)
        } else {
            fragmentTransaction.show(fragment)
        }

        fragmentTransaction.setPrimaryNavigationFragment(fragment)
        fragmentTransaction.setReorderingAllowed(true)
        fragmentTransaction.commitNow()
    }

    private fun checkPermissions() {
        val permissions = mutableListOf(Manifest.permission.RECORD_AUDIO)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permissions.add(Manifest.permission.POST_NOTIFICATIONS)
        }

        TedPermission.create()
            .setPermissionListener(object : PermissionListener {
                override fun onPermissionGranted() {
                }

                override fun onPermissionDenied(deniedPermissions: MutableList<String>?) {
                }
            })
            .setDeniedMessage(R.string.record_audio_permission_denied_message)
            .setPermissions(*permissions.toTypedArray())
            .check()
    }

    private fun pushTokenUpdate() {
        FirebaseMessaging.getInstance().token.addOnCompleteListener {
            if (!it.isSuccessful) {
                Logger.v("Fetching FCM registration token failed", it.exception)
                return@addOnCompleteListener
            }

            val pushToken = it.result
            if (pushToken != null) {
                SharedPreferenceManager.pushToken = pushToken
                viewModel.pushTokenUpdate(pushToken)
            }
        }
    }

    private fun gaidUpdate() {
        viewModel.fetchAndUpdateGaid(context = applicationContext)
    }

    private fun getMemberInfo() {
        viewModel.getMemberInfo {
            notificationSettingsDialog.show(screenWidth)
        }
    }

    private fun getEventPopup() {
        viewModel.getEventPopup {
            if (SharedPreferenceManager.notShowingEventPopupId != it.id) {
                val eventPopupDialog = EventPopupDialogFragment(
                    screenWidth = screenWidth,
                    eventItem = it
                ) {
                    startActivity(
                        Intent(
                            applicationContext,
                            EventDetailActivity::class.java
                        ).apply {
                            putExtra(Constants.EXTRA_EVENT, it)
                        }
                    )
                }

                eventPopupDialog.show(supportFragmentManager, eventPopupDialog.tag)
            }
        }
    }

    inner class AudioContentReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val contentId = intent?.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
            val title = intent?.getStringExtra(Constants.EXTRA_AUDIO_CONTENT_TITLE)
            val nickname = intent?.getStringExtra(Constants.EXTRA_NICKNAME)
            val coverImageUrl = intent?.getStringExtra(
                Constants.EXTRA_AUDIO_CONTENT_COVER_IMAGE_URL
            )

            val isPlaying = intent?.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_PLAYING, false)
            val isShowing = intent?.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_SHOWING, false)

            if (isShowing == true) {
                binding.rlMiniPlayer.visibility = View.VISIBLE
                if (contentId != null && contentId > 0) {
                    binding.rlMiniPlayer.setOnClickListener {
                        startActivity(
                            Intent(applicationContext, AudioContentDetailActivity::class.java)
                                .apply {
                                    putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, contentId)
                                }
                        )
                    }
                }

                if (isPlaying == true) {
                    binding.ivPlayOrPause.setImageResource(R.drawable.ic_noti_pause)
                    binding.ivPlayOrPause.setOnClickListener {
                        startService(
                            Intent(
                                this@MainActivity,
                                AudioContentPlayService::class.java
                            ).apply {
                                action = AudioContentPlayService.MusicAction.PAUSE.name
                            }
                        )
                    }
                } else {
                    binding.ivPlayOrPause.setImageResource(R.drawable.ic_noti_play)
                    binding.ivPlayOrPause.setOnClickListener {
                        startService(
                            Intent(
                                this@MainActivity,
                                AudioContentPlayService::class.java
                            ).apply {
                                action = AudioContentPlayService.MusicAction.PLAY.name
                            }
                        )
                    }
                }

                binding.ivStop.setOnClickListener {
                    startService(
                        Intent(
                            this@MainActivity,
                            AudioContentPlayService::class.java
                        ).apply {
                            action = AudioContentPlayService.MusicAction.STOP.name
                        }
                    )
                }

                if (!title.isNullOrBlank()) {
                    binding.tvTitle.text = title
                }

                if (!nickname.isNullOrBlank()) {
                    binding.tvNickname.text = nickname
                }

                if (!coverImageUrl.isNullOrBlank()) {
                    binding.ivCover.load(coverImageUrl) {
                        crossfade(true)
                        placeholder(R.drawable.bg_placeholder)
                        transformations(RoundedCornersTransformation(5.3f.dpToPx()))
                    }
                }
            } else {
                handler.post {
                    binding.ivPlayOrPause.setImageResource(0)
                    binding.ivCover.setImageResource(0)
                    binding.tvTitle.text = ""
                    binding.tvNickname.text = ""
                    binding.rlMiniPlayer.visibility = View.GONE
                    binding.ivPlayOrPause.setOnClickListener {}
                    viewModel.addAllPlaybackTracking()
                }
            }
        }
    }
}
