package uz.mobiuz.mobiservice.dev.ui.global

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.*
import androidx.biometric.BiometricPrompt
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.LinearLayoutManager
import uz.mobiuz.mobiservice.dev.MainViewModel
import uz.mobiuz.mobiservice.dev.R
import uz.mobiuz.mobiservice.dev.databinding.FragmentPinBinding
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.auth.pin.InstallPinAdapter
import uz.mobiuz.mobiservice.dev.ui.base.BaseFragment
import uz.mobiuz.mobiservice.dev.utils.extensions.showCustomDialog
import uz.mobiuz.mobiservice.dev.utils.extensions.showMessage
import uz.mobiuz.mobiservice.dev.utils.extensions.vibrate
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import uz.mobiuz.mobiservice.dev.utils.NetworkUtil
import uz.mobiuz.mobiservice.dev.utils.extensions.customLog
import javax.inject.Inject


@AndroidEntryPoint
class PinFragment : BaseFragment(R.layout.fragment_pin) {

    @Inject
    lateinit var pref: SharedPref
    private var _bn: FragmentPinBinding? = null
    private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
    private val data = ArrayList<PinData>()
    private val pinAdapter = InstallPinAdapter()
    private val mainViewModel: MainViewModel by activityViewModels()
    private var type = ""
    private var errorCount = 3
    private lateinit var biometricManager: BiometricManager
    private lateinit var biometricPrompt: BiometricPrompt
    private lateinit var promptInfo: BiometricPrompt.PromptInfo

    private val navController: NavController by lazy(LazyThreadSafetyMode.NONE) { NavHostFragment.findNavController(this) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        type = arguments?.getString(CONSTANTS.TYPE_PIN, "") ?: ""
    }

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

        val window = requireActivity().window.decorView
        window.systemUiVisibility = window.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

        mainViewModel.bottomSheet(false)
        mainViewModel.swipeDrawer(false)

        setUpUI()

        biometricManager = BiometricManager.from(requireContext())

        checkBiometric()

    }

    private fun checkBiometric() {
        when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or BIOMETRIC_WEAK)) {
            BiometricManager.BIOMETRIC_SUCCESS -> {
                bn.btnFingerPrint.isVisible = true
                if (pref.isUseFingerPrint){
                    lifecycleScope.launchWhenCreated {
                        delay(300)
                        loadBiometric()
                    }
                }
            }
            else -> {
                bn.btnFingerPrint.isVisible = false
            }
        }
    }

    private fun loadBiometric() {
        biometricPrompt = BiometricPrompt(this, object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                navigate()
            }
        })
        promptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle(getString(R.string.biometric_enter))
            .setSubtitle(getString(R.string.subtitle_biometric))
            .setConfirmationRequired(true)
            .setNegativeButtonText(getString(R.string.cancel))
            .build()

        biometricPrompt.authenticate(promptInfo)
    }


    override fun setUpUI() {
        bn.apply {
            loadData()

            rvPin.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)

            rvPin.adapter = pinAdapter
            txtNotPin.isVisible = false

            requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    requireActivity().finish()
                }
            })

            pinAdapter.setOnDoneListener {
                if (pref.pinCode == it) {
                    txtNotPin.isVisible = false
                    navigate()
                } else {
                    errorCount--
                    if (errorCount == 0) {
                        showCustomDialog(getString(R.string.pin_code_error3), false) {
                            loadWithPassword()
                        }
                    }
                    vibrate(requireContext())
                    cardPin.startAnimation(AnimationUtils.loadAnimation(context, R.anim.shake))
                    txtNotPin.isVisible = true
                }
            }


            for (i in 0 until btnViewGroup.childCount) {
                btnViewGroup.getChildAt(i).setOnClickListener {
                    when (it.id) {
                        R.id.btn_remove -> {
                            pinAdapter.removeItem()
                            txtNotPin.isVisible = false
                        }
                        R.id.with_password -> {
                            loadWithPassword()
                        }
                        R.id.btn_finger_print -> {
                            loadBiometric()
                        }
                        else -> {
                            val text = it as TextView
                            txtNotPin.isVisible = false
                            pinAdapter.addItem(text.text.toString().toInt())
                        }
                    }
                }
            }
        }
    }

    private fun loadWithPassword() {
       val  isOffline = NetworkUtil.getConnectivityStatus(requireContext())
        if (isOffline != 0){
            pref.clearUserData()
            val intent = Intent(requireContext(), AuthActivity::class.java)
            intent.putExtra(CONSTANTS.TYPE_AUTH, CONSTANTS.LOGIN)
            startActivity(intent)
            requireActivity().finish()
        }else{
            showMessage(getString(R.string.check_internet_and_try_again))
        }
    }


    private fun navigate() {
        navController.popBackStack()
        requireActivity().sendBroadcast(Intent(CONSTANTS.MY_CONNECTIVITY_CHANGE))
        if (type == CONSTANTS.OFFLINE) {
            navController.navigate(R.id.serviceFragment, bundleOf(CONSTANTS.TYPE_SERVICE to CONSTANTS.OFFLINE))
        } else if (type != CONSTANTS.TYPE_AFTER) {
            navController.navigate(R.id.homeFragment)
        }

    }

    override fun collects() {}

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


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