package uz.mobiuz.mobiservice.dev.ui.sdk.card

import android.app.Activity
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import com.google.android.gms.auth.api.phone.SmsRetriever
import com.google.android.material.textfield.TextInputEditText
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
import uz.agr.mobiuz.extension.SmsBroadcastReceiver
import uz.agr.mobiuz.ui.dialog.MessageDialog
import uz.agr.mobiuz.ui.fast_action.animation.getColorCompat
import uz.agr.mobiuz.ui.fast_action.animation.showKeyboard
import uz.agr.sdk.coreui.extension.hideSoftInput
import uz.agr.sdk.coreui.extension.visible
import uz.agr.sdk.coreui.ui.ButtonClick
import uz.agr.sdk.coreui.ui.TextWatcherWrapper
import uz.mobiuz.mobiservice.dev.R
import uz.mobiuz.mobiservice.dev.databinding.FragmentCardConfirmBinding
import uz.mobiuz.mobiservice.dev.model.SharedPref
import uz.mobiuz.mobiservice.dev.network.model.UiStateObject
import uz.mobiuz.mobiservice.dev.ui.base.BaseFragment
import uz.mobiuz.mobiservice.dev.ui.global.CONSTANTS
import uz.mobiuz.mobiservice.dev.utils.extensions.clearText
import uz.mobiuz.mobiservice.dev.utils.extensions.isEmpty
import uz.mobiuz.mobiservice.dev.utils.extensions.isNotEmpty
import uz.mobiuz.mobiservice.dev.utils.hideKeyboard
import java.util.regex.Pattern
import javax.inject.Inject

@AndroidEntryPoint
class CardConfirmFragment : BaseFragment(R.layout.fragment_card_confirm) {

    @Inject
    lateinit var pref: SharedPref

    private var _bn: FragmentCardConfirmBinding? = null
    private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
    private val viewModel: CardViewModel by viewModels()
    private val navController: NavController by lazy(LazyThreadSafetyMode.NONE) { NavHostFragment.findNavController(this) }
    private var smsBroadcastReceiver: SmsBroadcastReceiver? = null
    private var cardNumber = ""
    private var cardId = ""
    private var cardExpire = ""
//    private val phoneNumber: String by argument(CardConfirmFragment.ARG_PHONE_NUMBER)
//    private val maskedPhoneNumber: String by argument(CardConfirmFragment.ARG_MASKED_PHONE_NUMBER)

    private var code = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            cardId = it.getString(CONSTANTS.CARD_ID) ?: ""
            cardNumber = it.getString(CONSTANTS.CARD_NUMBER) ?: ""
            cardExpire = it.getString(CONSTANTS.CARD_EXPIRE) ?: ""
        }
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        _bn = FragmentCardConfirmBinding.bind(view)

        setUpUI()
        count(true)
        startSmsUserConsent()
        registerBroadcastReceiver()
        collects()

    }

    override fun setUpUI() {
        bn.apply {
            btnResend.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
//                    viewModel.resendSms(pref.userPhone.filter { it.isDigit() },cardNumber,cardExpire)
                    viewModel.resendSms("998949125150", cardNumber, cardExpire)
                }
            })

            btnConfirm.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    viewModel.cardConfirm(cardId, getLinePinCodes())
                }
            })

            toolbar.setNavigationOnClickListener { navController.navigateUp() }

            loadEdited()

            frame.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    checkFocus().showKeyboard()
                    setColorPins(getColorCompat(R.color.black100))
                }
            })

            coutdownView.setOnCountdownEndListener {
                count(false)
            }
        }

    }

    private fun count(status: Boolean) {
        bn.apply {
            btnResend.isVisible = !status
            coutdownViewHelperText.isVisible = !status
            coutdownView.isVisible = status
            if (status) coutdownView.start(CONSTANTS.RESEND_CODE_TIME)
        }
    }


    override fun collects() {
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.cardConfirmUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        showProgressDialog(false)
                        showSuccessDialog()
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)
                        setColorPins(getColorCompat(R.color.primary100))
                        bn.txtErrorCode.isVisible = true
                        bn.pinView.startAnimation(AnimationUtils.loadAnimation(requireContext(), R.anim.shake))
                        showToastMessage(it.message)
                    }
                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)

                    }
                    else -> Unit
                }
            }
        }
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.resendSmsUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        showProgressDialog(false)
                        count(true)
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)

                    }
                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)
                    }
                    else -> Unit
                }
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        activity?.hideSoftInput(bn.etConfirmCode)
        if (requestCode == 200) {
            if (resultCode == Activity.RESULT_OK && data != null) { //That gives all message to us.
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                message?.let {
                    getOtpFromMessage(message)
                }
            }
        }
    }

    private fun getOtpFromMessage(message: String) { // This will match any 6 digit number in the message
        val matcher = Pattern.compile("(|^)\\d{6}").matcher(message)
        if (matcher.find()) {
            setTextPinCodes(matcher.group(0))
//            etConfirmCode.setText(matcher.group(0))
        }
    }

    private fun showSuccessDialog() {
        val dialog = MessageDialog(
            requireContext(),
            getString(uz.agr.mobiuz.R.string.agr_mobi_uz_card_added),
            getString(uz.agr.mobiuz.R.string.agr_mobi_uz_close_process)
        )
        dialog.window!!.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.setCanceledOnTouchOutside(true)
        dialog.setOnOkClickListener(object : MessageDialog.OnClickListener {
            override fun dialogPositiveClicked() {
                dialog.dismiss()
                navController.popBackStack(R.id.cardsListFragment, false)
            }
        })
        dialog.show()
    }

    private fun getLinePinCodes(): String {
        bn.apply {
            code = ""
            code += pin1.text.toString()
            code += pin2.text.toString()
            code += pin3.text.toString()
            code += pin4.text.toString()
            code += pin5.text.toString()
            code += pin6.text.toString()
        }

        return code.filter { it.isDigit() }
    }

    private fun setColorPins(color: Int) {
        bn.apply {
            pin1.setTextColor(color)
            pin2.setTextColor(color)
            pin3.setTextColor(color)
            pin4.setTextColor(color)
            pin5.setTextColor(color)
            pin6.setTextColor(color)
        }

    }

    private fun checkFocus(): View {
        bn.apply {
            return when {
                pin1.isEmpty() -> pin1
                pin2.isEmpty() -> pin2
                pin3.isEmpty() -> pin3
                pin4.isEmpty() -> pin4
                pin5.isEmpty() -> pin5
                else -> pin6
            }
        }
    }

    private fun clearLatest(): View {
        bn.apply {
            return when {
                pin6.isNotEmpty() -> pin6.clearText()
                pin5.isNotEmpty() -> pin5.clearText()
                pin4.isNotEmpty() -> pin4.clearText()
                pin3.isNotEmpty() -> pin3.clearText()
                pin2.isNotEmpty() -> pin2.clearText()
                else -> pin1.clearText()
            }
        }
    }

    private fun setTextPinCodes(code: String) {
        bn.apply {
            if (code.length != 6) return
            pin1.setText(code[0].toString())
            pin2.setText(code[1].toString())
            pin3.setText(code[2].toString())
            pin4.setText(code[3].toString())
            pin5.setText(code[4].toString())
            pin6.setText(code[5].toString())
        }
    }

    private fun loadEdited() {
        bn.apply {

            for (i in 0 until pinView.childCount) {
                (pinView.getChildAt(i) as TextInputEditText).apply {
                    this.addTextChangedListener(object : TextWatcherWrapper() {
                        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                            super.onTextChanged(s, start, before, count)
                            bn.txtErrorCode.isVisible = false
                            txtErrorCode.visible(false)
                            if (s.toString().isNotEmpty()) {
                                if (i == pinView.childCount - 1) {
                                    pin6.hideKeyboard()
                                    btnConfirm.isEnabled = true
                                } else pinView.getChildAt(i + 1).requestFocus()
                                this@apply.setBackgroundResource(uz.agr.mobiuz.R.drawable.agr_bgn_ver_checked)
                            } else {
                                if (i == pinView.childCount - 1) {
                                    btnConfirm.isEnabled = false
                                }
                                this@apply.setBackgroundResource(uz.agr.mobiuz.R.drawable.agr_bgn_ver_unchecked)
                            }
                        }
                    })
                }
            }
            for (i in 0 until pinView.childCount) {
                pinView.getChildAt(i).setOnKeyListener { _, keyCode, event ->
                    if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_DEL) {
                        clearLatest().requestFocus()
                        return@setOnKeyListener false
                    }
                    false
                }
            }
        }
    }

    private fun startSmsUserConsent() {
        val client = SmsRetriever.getClient(requireContext())
        client.startSmsUserConsent(null)
            .addOnSuccessListener { /**/ }
            .addOnFailureListener { /**/ }
    }

    private fun registerBroadcastReceiver() {
        smsBroadcastReceiver = SmsBroadcastReceiver()
        smsBroadcastReceiver!!.smsBroadcastReceiverListener =
            object : SmsBroadcastReceiver.SmsBroadcastReceiverListener {
                override fun onSuccess(intent: Intent?) {
                    startActivityForResult(intent, 200)
                }

                override fun onFailure() {}
            }
        val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
        context?.registerReceiver(smsBroadcastReceiver, intentFilter)
    }


    override fun onDestroy() {
        requireActivity().unregisterReceiver(smsBroadcastReceiver)
        _bn = null
        super.onDestroy()
    }
}