package kr.co.vividnext.sodalive.mypage.alarm

import android.Manifest
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.View
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationManagerCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.gun0912.tedpermission.PermissionListener
import com.gun0912.tedpermission.normal.TedPermission
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.databinding.ActivityAlarmListBinding
import kr.co.vividnext.sodalive.extensions.moneyFormat
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
import org.koin.android.ext.android.inject

class AlarmListActivity : BaseActivity<ActivityAlarmListBinding>(
    ActivityAlarmListBinding::inflate
) {

    private val alarmViewModel: AlarmViewModel by viewModels()
    private val viewModel: AlarmListViewModel by inject()

    private lateinit var alarmAdapter: AlarmAdapter
    private lateinit var loadingDialog: LoadingDialog

    private lateinit var requestOverlayPermissionLauncher: ActivityResultLauncher<Intent>
    private lateinit var requestExactAlarmPermissionLauncher: ActivityResultLauncher<Intent>

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

        checkAndRequestOverlayPermission()

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            checkAndRequestExactAlarmPermission()
        }

        checkPermissions()
        bindData()
    }

    private fun checkAndRequestOverlayPermission() {
        requestOverlayPermissionLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(
                    this,
                    "알람서비스를 이용하시려면 다른 앱 위에 표시 권한을 허용하셔야 합니다.",
                    Toast.LENGTH_SHORT
                ).show()

                finish()
            }
        }

        if (!Settings.canDrawOverlays(this)) {
            Toast.makeText(
                this,
                "알람서비스를 이용하시려면 다른 앱 위에 표시 권한을 허용하셔야 합니다.",
                Toast.LENGTH_SHORT
            ).show()
            val intent = Intent(
                Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:$packageName")
            )
            requestOverlayPermissionLauncher.launch(intent)
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private fun checkAndRequestExactAlarmPermission() {
        requestExactAlarmPermissionLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
            if (!alarmManager.canScheduleExactAlarms()) {
                Toast.makeText(
                    this,
                    "알람서비스를 이용하시려면 권한을 허용하셔야 합니다.",
                    Toast.LENGTH_SHORT
                ).show()
                finish()
            }
        }

        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        if (!alarmManager.canScheduleExactAlarms()) {
            val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
            requestExactAlarmPermissionLauncher.launch(intent)
        }
    }

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

        binding.tvBack.text = "보이스 모닝콜 등록"
        binding.tvBack.setOnClickListener { finish() }
        binding.ivPlus.setOnClickListener {
            startActivity(
                Intent(
                    applicationContext,
                    AddAlarmActivity::class.java
                )
            )
        }

        alarmAdapter = AlarmAdapter(
            updateAlarm = {
                alarmViewModel.update(it)
                adapterRefresh()
            },
            deleteAlarm = { showDeleteConfirm(it) },
            onClick = {
                startActivity(
                    Intent(applicationContext, AddAlarmActivity::class.java).apply {
                        putExtra(Constants.EXTRA_ALARM_ID, it)
                    }
                )
            }
        )
        binding.rvAlarm.layoutManager = LinearLayoutManager(this)
        binding.rvAlarm.adapter = alarmAdapter
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun adapterRefresh() {
        alarmAdapter.notifyDataSetChanged()
    }

    private fun bindData() {
        alarmViewModel.allAlarms.observe(this) { alarms ->
            alarms?.let {
                alarmAdapter.submitList(it)
                binding.scrollView.visibility =
                    if (it.isEmpty()) View.GONE else View.VISIBLE
                binding.tvEmptyAlarms.visibility =
                    if (it.isEmpty()) View.VISIBLE else View.GONE


                viewModel.getSlotQuantityAndPrice()
            }
        }

        viewModel.toastLiveData.observe(this) {
            Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show()
        }

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

        viewModel.maxAlarmSlotLiveData.observe(this) {
            if (it > 0 && alarmAdapter.itemCount >= it) {
                binding.ivPlus.visibility = View.GONE
                binding.llBuyExtraSlot.visibility = View.VISIBLE
                binding.tvInfinity.visibility = if (it - 3 >= 2) {
                    View.VISIBLE
                } else {
                    View.GONE
                }

                binding.llBuyExtraSlot.setOnClickListener { showBuyConfirm() }
            } else {
                binding.ivPlus.visibility = View.VISIBLE
                binding.llBuyExtraSlot.visibility = View.GONE
            }
        }

        viewModel.extraSlotPriceLiveData.observe(this) {
            binding.tvPrice.text = it.moneyFormat()
        }
    }

    private fun checkPermissions() {
        val permissions = mutableListOf<String>()

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

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

                    override fun onPermissionDenied(deniedPermissions: MutableList<String>?) {
                        finish()
                    }
                })
                .setDeniedMessage(
                    "권한을 거부하시면 알람서비스를 이용하실 수 없습니다."
                )
                .setPermissions(*permissions.toTypedArray())
                .check()
        }
    }

    private fun showDeleteConfirm(alarm: Alarm) {
        SodaDialog(
            this,
            layoutInflater,
            title = "알림",
            desc = "알람을 삭제하시겠습니까?",
            confirmButtonTitle = "삭제",
            confirmButtonClick = {
                alarmViewModel.delete(alarm)
                Toast.makeText(
                    applicationContext,
                    "알람이 삭제되었습니다.",
                    Toast.LENGTH_SHORT
                ).show()
                adapterRefresh()
            },
            cancelButtonTitle = "취소",
        ).show(screenWidth)
    }

    private fun showBuyConfirm() {
        SodaDialog(
            this,
            layoutInflater,
            title = "알림",
            desc = "추가 슬롯을 구매하시겠습니까?",
            confirmButtonTitle = "구매",
            confirmButtonClick = { viewModel.buyExtraSlot() },
            cancelButtonTitle = "취소",
        ).show(screenWidth)
    }
}
