package com.mobiuz.app.dev.ui.auth.verification

import android.os.Bundle
import android.view.KeyEvent
import android.view.View
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.material.textfield.TextInputEditText
import com.mobiuz.app.R
import com.mobiuz.app.databinding.FragmentVerificationBinding
import com.mobiuz.app.dev.model.SharedPref
import com.mobiuz.app.dev.model.UserAuth
import com.mobiuz.app.dev.network.model.UiStateObject
import com.mobiuz.app.dev.ui.auth.AuthViewModel
import com.mobiuz.app.dev.ui.base.BaseFragment
import com.mobiuz.app.dev.ui.global.ButtonClick
import com.mobiuz.app.dev.ui.global.CONSTANTS
import com.mobiuz.app.dev.ui.global.TextWatcherWrapper
import com.mobiuz.app.dev.utils.Utils
import com.mobiuz.app.dev.utils.extensions.clearText
import com.mobiuz.app.dev.utils.extensions.getColorCompat
import com.mobiuz.app.dev.utils.extensions.isEmpty
import com.mobiuz.app.dev.utils.extensions.isNotEmpty
import com.mobiuz.app.dev.utils.hideKeyboard
import com.mobiuz.app.dev.utils.showKeyboard
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
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 code = ""
    private var verificationCode = ""


    private var phone = ""
    private var type = ""

    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) ?: ""
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        _bn = FragmentVerificationBinding.bind(view)
        setUpUI()
        count(true)
        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))
                }
            })
            btnLogin.setOnClickListener(object : ButtonClick() {
                override fun onSingleClick(v: View?) {
                    getLinePinCodes()
                    val auth = UserAuth(phone.replace("+", "").replace(" ", ""), null, code)
                    if (type == CONSTANTS.TYPE_FORGET) {
                        viewModel.checkResetCode(auth)
                    } else {
                        viewModel.verification(auth)
                    }

                }
            })

            sentCodeAgain.setOnClickListener {
                viewModel.resetSmsCode(UserAuth(phone.replace("+", "").replace(" ", "")))
            }
            coutdownView.setOnCountdownEndListener {
                count(false)
            }
            setVerificationCode()
        }
    }

    private fun setVerificationCode() {
        if(verificationCode.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()
                btnLogin.isEnabled = true
            }
        }
    }

    private fun getLinePinCodes() {
        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()
        }
    }

    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()
                                    btnLogin.isEnabled = true
                                } else pinView.getChildAt(i + 1).requestFocus()
                                this@apply.setBackgroundResource(R.drawable.bgn_ver_checked)
                            } else {
                                if (i == pinView.childCount - 1) {
                                    btnLogin.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.pinFragment, 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 -> {
                        showToastMessage(it.data)
                        verificationCode = it.data
                        setVerificationCode()
                        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
                }
            }
        }
    }

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

}
