package com.hx.utils.application.ui.calendar

import android.Manifest.permission.READ_PHONE_STATE
import android.Manifest.permission.READ_SMS
import android.Manifest.permission.RECEIVE_SMS
import android.Manifest.permission.SEND_SMS
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.app.role.RoleManager
import android.content.ContentValues
import android.content.Intent
import android.os.Build
import android.provider.Telephony
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.ToastUtils
import com.hx.utils.application.R
import com.hx.utils.application.base.BaseFragment
import com.hx.utils.application.databinding.FragmentSmsBinding
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.Calendar

class CalendarFragment : BaseFragment<FragmentSmsBinding, CalendarViewModel>() {

    override fun setupViewModel() {
        viewModel = ViewModelProvider(this)[CalendarViewModel::class.java]
    }

    override fun setupView() {
        binding.loading.visibility = View.GONE
        binding.insertMms.setOnClickListener {
            val smsPackageName = Telephony.Sms.getDefaultSmsPackage(context)
            val currentPackageName = context?.packageName
            if (!smsPackageName.isNullOrBlank()) {
                if (smsPackageName != currentPackageName) {
                    val intent: Intent?
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                        intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
                        intent.putExtra(
                            Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
                            requireContext().packageName
                        )
                        requireContext().startActivity(intent)
                    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        openSMSappChooser()
                    }
                    return@setOnClickListener
                }
            }

            val name = binding.name.text?.toString().orEmpty()
            val message = binding.message.text?.toString().orEmpty()
            if (name.isBlank()) {
                binding.name.error = getString(R.string.not_empty)
                return@setOnClickListener
            }

            if (message.isBlank()) {
                binding.message.error = getString(R.string.not_empty)
                return@setOnClickListener
            }

            binding.loading.visibility = View.VISIBLE
            insertSms()

        }

        binding.selectTime.setOnClickListener {
            val calendar = Calendar.getInstance()
            val datePickerDialog = DatePickerDialog(
                requireActivity(),
                { _, year, month, dayOfMonth ->
                    showTimePickerDialog(year, month, dayOfMonth)
                },
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH)
            )
            datePickerDialog.show()
        }
        binding.read.setOnCheckedChangeListener { _, b ->
            viewModel.read.postValue(b)
        }

        binding.name.doOnTextChanged { text, _, _, _ ->
            viewModel.name.postValue(text.toString())
        }

        binding.message.doOnTextChanged { text, _, _, _ ->
            viewModel.message.postValue(text.toString())
        }

        viewModel.message.observe(viewLifecycleOwner) {
            binding.showMsg.text = it
        }

        viewModel.name.observe(viewLifecycleOwner) {
            binding.materialTextView.text = StringUtils.getString(R.string.from_s, it)
        }

        viewModel.read.observe(viewLifecycleOwner) {
            binding.materialTextView3.setText(if (it) R.string.read else R.string.unread)
        }

        viewModel.showTime.observe(viewLifecycleOwner) {
            binding.selectTime.text = it
            binding.materialTextView2.text = it
        }

        (activity as? AppCompatActivity)?.supportActionBar?.title = arguments?.getString("data")
    }

    override fun setupBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSmsBinding {
        return FragmentSmsBinding.inflate(inflater, container, false)
    }


    override fun onStart() {
        super.onStart()
        getPermissions()
    }


    fun getPermissions() {
        val permissions = listOf(SEND_SMS, RECEIVE_SMS, READ_SMS, READ_PHONE_STATE).toTypedArray()
        PermissionUtils.permission(*permissions)
            .rationale { _, shouldRequest ->
                run {
                    shouldRequest.again(true)
                }
            }.callback(object : PermissionUtils.FullCallback {
                override fun onGranted(permissionsGranted: MutableList<String>) {
                    Log.d("hzshkj", "onGranted: $permissionsGranted")
                }

                override fun onDenied(forever: MutableList<String>, denied: MutableList<String>) {
                    if (forever.isNotEmpty()) {
                        AppUtils.launchAppDetailsSettings()
                    } else {
                        getPermissions()
                    }
                }
            }).request()
    }


    @OptIn(DelicateCoroutinesApi::class)
    private fun insertSms() {
        try {
            val values = ContentValues().apply {
                put(Telephony.Sms.ADDRESS, binding.name.text.toString())
                put(Telephony.Sms.DATE, viewModel.time.value)
                put(Telephony.Sms.DATE_SENT, viewModel.time.value?.minus(5000))
                put(Telephony.Sms.READ, viewModel.read.value)
                put(Telephony.Sms.TYPE, 1)
                put(Telephony.Sms.BODY, binding.message.text.toString())
                put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_INBOX)
            }
            context?.contentResolver?.insert(Telephony.Sms.CONTENT_URI, values)

            binding.name.text?.clear()
            binding.message.text?.clear()
            viewModel.time.postValue(0)
            viewModel.showTime.postValue("")

        } catch (e: Exception) {
            e.message?.let {
                GlobalScope.launch(Dispatchers.Main) {
                    delay(2000)
                    ToastUtils.showLong(it)
                }
            }
        } finally {
            GlobalScope.launch(Dispatchers.Main) {
                delay(2000)
                binding.loading.visibility = View.GONE
            }
        }

    }

    private fun showTimePickerDialog(year: Int, month: Int, dayOfMonth: Int) {
        val calendar = Calendar.getInstance()
        val timePickerDialog = TimePickerDialog(
            requireActivity(),
            { _, h, m ->
                val selectedCalendar = Calendar.getInstance()
                selectedCalendar.set(year, month, dayOfMonth, h, m)
                val selectedTimestamp = selectedCalendar.timeInMillis

                handleSelectedTimestamp(
                    selectedTimestamp,
                    TimeUtils.date2String(TimeUtils.millis2Date(selectedTimestamp))
                )
            },
            calendar.get(Calendar.HOUR_OF_DAY),
            calendar.get(Calendar.MINUTE),
            true
        )
        timePickerDialog.show()
    }

    private fun handleSelectedTimestamp(timestamp: Long, showTxt: String) {
        viewModel.time.postValue(timestamp)
        viewModel.showTime.postValue(showTxt)


    }

    private fun openSMSappChooser() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val roleManager = context?.getSystemService(RoleManager::class.java)
            if (roleManager!!.isRoleAvailable(RoleManager.ROLE_SMS)) {
                if (!roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
                    val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
                    startActivityForResult(intent, 1314)
                }
            }
        } else {
            val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, context?.packageName)
            startActivity(intent)
        }
    }


}