package uz.mobiuz.mobiservice.dev.ui.auth.verification

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.os.bundleOf
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.android.synthetic.main.fragment_card_confirm.*
import kotlinx.coroutines.flow.collect
import uz.agr.sdk.coreui.extension.hideSoftInput
import uz.mobiuz.mobiservice.dev.R
import uz.mobiuz.mobiservice.dev.databinding.FragmentVerificationBinding
import uz.mobiuz.mobiservice.dev.model.SharedPref
import uz.mobiuz.mobiservice.dev.model.UserAuth
import uz.mobiuz.mobiservice.dev.network.model.UiStateObject
import uz.mobiuz.mobiservice.dev.ui.auth.AuthViewModel
import uz.mobiuz.mobiservice.dev.ui.base.BaseFragment
import uz.mobiuz.mobiservice.dev.ui.global.ButtonClick
import uz.mobiuz.mobiservice.dev.ui.global.CONSTANTS
import uz.mobiuz.mobiservice.dev.ui.global.TextWatcherWrapper
import uz.mobiuz.mobiservice.dev.utils.Utils
import uz.mobiuz.mobiservice.dev.utils.extensions.*
import uz.mobiuz.mobiservice.dev.utils.hideKeyboard
import uz.mobiuz.mobiservice.dev.utils.showKeyboard
import uz.mobiuz.mobiservice.dev.utils.sms.MessageDialog
import uz.mobiuz.mobiservice.dev.utils.sms.SmsBroadcastReceiver
import java.util.regex.Pattern
import javax.inject.Inject


@AndroidEntryPoint
class VerificationFragment : BaseFragment(R.layout.fragment_verification) {


    @Inject
    lateinit var pref: SharedPref

    private var _bn: FragmentVerificationBinding? = null
    private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
    private val viewModel: AuthViewModel by viewModels()
    private val navController: NavController by lazy(LazyThreadSafetyMode.NONE) { NavHostFragment.findNavController(this) }
    private var verificationCode = ""
    private var code = ""
    private var phone = ""
    private var type = ""

    private var smsBroadcastReceiver: SmsBroadcastReceiver? = null
    private var cardNumber = ""
    private var cardId = ""
    private var cardExpire = ""
    private var payCardnumber = ""
    private var monitoring = ""

    var transactionId = 0L
    var payAmount = 0L
    var saveCard: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            phone = it.getString(CONSTANTS.PHONE) ?: ""
            type = it.getString(CONSTANTS.TYPE_VERIFICATION) ?: ""
            verificationCode = it.getString(CONSTANTS.PIN_CODE) ?: ""

            //card
            cardId = it.getString(CONSTANTS.CARD_ID) ?: ""
            cardNumber = it.getString(CONSTANTS.CARD_NUMBER) ?: ""
            cardExpire = it.getString(CONSTANTS.CARD_EXPIRE) ?: ""
            payCardnumber = it.getString(CONSTANTS.PAY_CARD_NUMBER) ?: ""

            transactionId = it.getLong(CONSTANTS.TRANSACTION_ID)
            saveCard = it.getInt(CONSTANTS.SAVED_CARD, 0)
            payAmount = it.getLong(CONSTANTS.PAY_AMOUNT)
            monitoring = it.getString(CONSTANTS.PAY_MONITORING) ?: ""

        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        _bn = FragmentVerificationBinding.bind(view)
        setUpUI()
        count(true)
        startSmsUserConsent()
        registerBroadcastReceiver()
        collects()
    }

    override fun setUpUI() {
        bn.apply {

            toolbar.setNavigationOnClickListener {
                navController.navigateUp()
            }

            loadEdited()

            viewGroup.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    v?.hideKeyboard()
                }
            })

            frame.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    checkFocus().showKeyboard()
                    setColorPins(getColorCompat(R.color.black100))
                }
            })
            btnVerification.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    getLinePinCodes()
                    if (checkInternet()) {
                        val auth = UserAuth(phone.filter { it.isDigit() }, null, code)
                        when (type) {
                            CONSTANTS.TYPE_FORGET -> {
                                viewModel.checkResetCode(auth)
                            }
                            CONSTANTS.TYPE_ADD_CARD -> {
                                viewModel.cardConfirm(cardId, getLinePinCodes())
                            }
                            CONSTANTS.TYPE_ANOTHER_CARD -> {
                                viewModel.vendor(getLinePinCodes(), transactionId)
                            }
                            else -> {
                                viewModel.verification(auth)
                            }
                        }
                    }
                }
            })

            sentCodeAgain.setOnClickListener {
                when (type) {
                    CONSTANTS.TYPE_ADD_CARD -> {
                        viewModel.resendSms("998949125150", cardNumber, cardExpire)
                    }
                    CONSTANTS.TYPE_ANOTHER_CARD -> {
                        viewModel.vendorResendSms(transactionId)
                    }
                    else -> viewModel.resetSmsCode(UserAuth(phone.filter { it.isDigit() }))
                }
            }
            coutdownView.setOnCountdownEndListener {
                count(false)
            }
//            setVerificationCode()
        }
    }

    private fun setVerificationCode(code: String) {
        if (code.length == 6) {
            bn.apply {
                pin1.setText(verificationCode[0].toString())
                pin2.setText(verificationCode[1].toString())
                pin3.setText(verificationCode[2].toString())
                pin4.setText(verificationCode[3].toString())
                pin5.setText(verificationCode[4].toString())
                pin6.setText(verificationCode[5].toString())
                pin6.requestFocus()
                btnVerification.isEnabled = true
            }
        }
    }

    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
    }

    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 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
                            if (s.toString().isNotEmpty()) {
                                if (i == pinView.childCount - 1) {
                                    pin6.hideKeyboard()
                                    btnVerification.isEnabled = true
                                } else pinView.getChildAt(i + 1).requestFocus()
                                this@apply.setBackgroundResource(R.drawable.bgn_ver_checked)
                            } else {
                                if (i == pinView.childCount - 1) {
                                    btnVerification.isEnabled = false
                                }
                                this@apply.setBackgroundResource(R.drawable.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
                }
            }
        }
    }

    override fun collects() {
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.verificationUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        showProgressDialog(false)
                        pref.userPhone = phone
                        navController.navigate(R.id.installPinFragment, bundleOf(CONSTANTS.TYPE_PIN to CONSTANTS.NEW_PIN), Utils.navOptions())
                    }
                    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.resetSmsCodeUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        count(true)
                        showProgressDialog(false)
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)
                        showToastMessage(it.message)
                    }

                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)
                    }
                    else -> Unit
                }
            }
        }
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.checkResetCodeUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        showProgressDialog(false)
                        pref.userPhone = phone
                        navController.navigate(
                            R.id.registerFragment,
                            bundleOf(
                                CONSTANTS.PHONE to phone,
                                CONSTANTS.TYPE_VERIFICATION to CONSTANTS.TYPE_FORGET,
                                CONSTANTS.PIN_CODE to code,
                            ),
                            Utils.navOptions()
                        )
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)
                        setColorPins(getColorCompat(R.color.primary100))
                        bn.pinView.startAnimation(AnimationUtils.loadAnimation(requireContext(), R.anim.shake))
                        showToastMessage(it.message)
                    }
                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)
                    }
                    else -> Unit
                }
            }
        }

        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.cardConfirmUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        showProgressDialog(false)
                        customLog("UiStateObject.SUCCESS")
                        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
                }
            }
        }
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.vendorUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        navController.navigate(
                            R.id.paymentSuccessfulFragment,
                            bundleOf(
                                CONSTANTS.PAY_SAVE_CARD to saveCard,
                                CONSTANTS.PAY_CARD_NUMBER to payCardnumber,
                                CONSTANTS.PAY_MONITORING to monitoring
                            )
                        )
                        showProgressDialog(false)
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)
                        showMessage(it.message)
                    }
                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)
                    }
                    else -> Unit
                }
            }
        }
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.vendorResendSmsUiState.collect {
                when (it) {
                    is UiStateObject.SUCCESS -> {
                        count(true)
                        showProgressDialog(false)
                    }
                    is UiStateObject.ERROR -> {
                        showProgressDialog(false)
                        showMessage(it.message)
                    }
                    is UiStateObject.LOADING -> {
                        showProgressDialog(true)
                    }
                    else -> Unit
                }
            }
        }
    }

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


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        customLog("onActivityResult:")
        activity?.hideSoftInput(bn.pinView)
        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()) {
            customLog("verification code:${matcher.group(0)} ")
            setVerificationCode(matcher.group(0))
        }
    }

    private fun showSuccessDialog() {
        try {

            showCustomDialog(getString(R.string.agr_mobi_uz_card_added),true){
                navController.popBackStack(R.id.cardsListFragment, false)
            }
//
        }catch (e:Exception){
            navController.popBackStack(R.id.cardsListFragment, false)
            customLog(e.localizedMessage)
        }

    }

    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() {
        context?.unregisterReceiver(smsBroadcastReceiver)
        _bn = null
        super.onDestroy()
    }

}
