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

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.LinearLayoutManager
import uz.mobiuz.mobiservice.dev.MainActivity
import uz.mobiuz.mobiservice.dev.R
import uz.mobiuz.mobiservice.dev.databinding.FragmentInstallPinBinding
import uz.mobiuz.mobiservice.dev.model.PinData
import uz.mobiuz.mobiservice.dev.model.SharedPref
import uz.mobiuz.mobiservice.dev.ui.auth.AuthActivity
import uz.mobiuz.mobiservice.dev.ui.base.BaseFragment
import uz.mobiuz.mobiservice.dev.ui.global.CONSTANTS
import uz.mobiuz.mobiservice.dev.utils.Utils
import uz.mobiuz.mobiservice.dev.utils.extensions.*
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class InstallPinFragment : BaseFragment(R.layout.fragment_install_pin) {

    @Inject
    lateinit var pref: SharedPref
    private var _bn: FragmentInstallPinBinding? = null
    private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
    private val navController: NavController by lazy(LazyThreadSafetyMode.NONE) { NavHostFragment.findNavController(this) }
    private lateinit var biometricManager: BiometricManager
    private val pinAdapter = InstallPinAdapter()
    private val data = ArrayList<PinData>()
    private var titleText = ""
    private var pinCode = ""
    private var type = ""
    private var count = 3


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            type = it.getString(CONSTANTS.TYPE_PIN, "") ?: ""
            pinCode = it.getString(CONSTANTS.PIN_CODE, "") ?: ""
        }
        biometricManager = BiometricManager.from(requireContext())
    }


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

        setUpUI()
        collects()

    }

    override fun setUpUI() {
        bn.apply {
            loadData()
            toolbar.setNavigationOnClickListener {
                handleBackStack()
            }
            requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    handleBackStack()
                }
            })
            rvPin.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
            rvPin.setHasFixedSize(true)

            rvPin.adapter = pinAdapter
            titleText = when (type) {
                CONSTANTS.NEW_PIN -> {
                    getString(R.string.install_pin)
                }
                CONSTANTS.CONFIRM_NEW_PIN -> {
                    getString(R.string.confirm_pin)
                }
                CONSTANTS.CURRENT_PIN -> {
                    getString(R.string.enter_old_pin)
                }
                CONSTANTS.CHANGE_NEW_PIN -> {
                    getString(R.string.enter_new_pin)
                }
                CONSTANTS.CONFIRM_CHANGE_NEW_PIN -> {
                    getString(R.string.confirm_new_pin)
                }
                else -> {
                    getString(R.string.install_pin)
                }
            }

            txtEnterPin.text = titleText
            txtNotPin.isVisible = false

            pinAdapter.setOnDoneListener {
                when (type) {
                    CONSTANTS.NEW_PIN -> {
                        navController.navigate(R.id.installPinFragment,
                            bundleOf(CONSTANTS.TYPE_PIN to CONSTANTS.CONFIRM_NEW_PIN, CONSTANTS.PIN_CODE to it),
                            Utils.navOptions())
                    }
                    CONSTANTS.CONFIRM_NEW_PIN -> {
                        if(pinCode == it){
                            pref.pinCode = pinCode
                            navigate()
                        }else{
                            vibrate(requireContext())
                            cardPin.startAnimation(AnimationUtils.loadAnimation(requireContext(), R.anim.shake))
                            txtNotPin.isVisible = true
                        }
                    }
                    CONSTANTS.CURRENT_PIN -> {
                        if(pref.pinCode == it){
                            navController.navigate(R.id.installPinFragment,
                                bundleOf( CONSTANTS.TYPE_PIN to CONSTANTS.CHANGE_NEW_PIN), Utils.navOptions())
                        }else{
                            loadError()
                        }
                    }
                    CONSTANTS.CHANGE_NEW_PIN -> {
                        if(pref.pinCode == it){
                            showMessage(getString(R.string.cannot_change_pin))
                        }else{
                            navController.navigate(R.id.installPinFragment,
                                bundleOf(CONSTANTS.TYPE_PIN to CONSTANTS.CONFIRM_CHANGE_NEW_PIN, CONSTANTS.PIN_CODE to it),
                                Utils.navOptions())
                        }
                    }
                    CONSTANTS.CONFIRM_CHANGE_NEW_PIN -> {
                        if(pinCode == it){
                            pref.pinCode = pinCode
                            showCustomDialog(getString(R.string.pin_code_updated),true){
                                navController.popBackStack(R.id.securityFragment, false)
                            }

                        }else{
                            vibrate(requireContext())
                            cardPin.startAnimation(AnimationUtils.loadAnimation(requireContext(), R.anim.shake))
                            txtNotPin.isVisible = true
                        }
                    }
                    else -> {

                    }
                }
            }

            for (i in 0 until btnViewGroup.childCount) {
                btnViewGroup.getChildAt(i).setOnClickListener {
                    bn.txtNotPin.isVisible = false
                    if (it.id == R.id.btn_remove) {
                        pinAdapter.removeItem()
                    } else {
                        val text = it as TextView
                        pinAdapter.addItem(text.text.toString().toInt())
                    }
                }
            }

        }
    }

    private fun handleBackStack() {
        if (type == CONSTANTS.NEW_PIN){
            when {
                navController.popBackStack(R.id.registerFragment,false) -> {}
                navController.popBackStack(R.id.loginFragment,false) -> {}
                else -> navController.navigateUp()
            }
        }else navController.navigateUp()
    }

    private fun checkBiometric() : Boolean {
        return when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or BIOMETRIC_WEAK)) {
            BiometricManager.BIOMETRIC_SUCCESS -> true
            else -> false
        }
    }


    private fun loadError(){
        bn.apply {
            count--
            if (count == 0){
                showCustomDialog(getString(R.string.popitok_error),false){
                    navigateToLogin()
                }

            }else{
                vibrate(requireContext())
                cardPin.startAnimation(AnimationUtils.loadAnimation(requireContext(), R.anim.shake))
               showMessage(getString(R.string.popitok,count.toString()))
            }
        }
    }

    private fun navigateToLogin() {
        pref.clearUserData()
        val intent = Intent(requireContext(), AuthActivity::class.java)
        intent.putExtra(CONSTANTS.TYPE_AUTH, CONSTANTS.LOGIN)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
        startActivity(intent)
        requireActivity().finishAffinity()
    }

    private fun navigate() {

        if (checkBiometric()) {
            navController.navigate(R.id.biometricFragment, null, Utils.navOptions())
        } else {
            val intent = Intent(requireContext(), MainActivity::class.java)
            intent.putExtra(CONSTANTS.FIRST, CONSTANTS.FIRST)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
            startActivity(intent)
            requireActivity().finishAffinity()
        }
    }

    private fun loadData() {
        data.clear()
        for (i in 0..3) {
            data.add(PinData(-1))
        }
        pinAdapter.submitList(data)
    }

    override fun collects() {}

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