package com.mobiuz.app.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.BIOMETRIC_STRONG
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
import androidx.biometric.BiometricPrompt
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.LinearLayoutManager
import co.infinum.goldfinger.Goldfinger
import com.mobiuz.app.R
import com.mobiuz.app.databinding.FragmentPinDialogBinding
import com.mobiuz.app.dev.MainViewModel
import com.mobiuz.app.dev.model.PinData
import com.mobiuz.app.dev.model.SharedPref
import com.mobiuz.app.dev.ui.auth.AuthActivity
import com.mobiuz.app.dev.ui.auth.pin.PinAdapter
import com.mobiuz.app.dev.ui.base.BaseFragment
import com.mobiuz.app.dev.utils.NetworkUtil
import com.mobiuz.app.dev.utils.extensions.showCustomDialog
import com.mobiuz.app.dev.utils.extensions.showMessage
import com.mobiuz.app.dev.utils.extensions.vibrate
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject


@AndroidEntryPoint
class FullScreenFragment : BaseFragment(R.layout.fragment_pin_dialog) {

    @Inject
    lateinit var pref: SharedPref
    private var _bn: FragmentPinDialogBinding? = null
    private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
    private val data = ArrayList<PinData>()
    private val pinAdapter = PinAdapter()
    private lateinit var mainViewModel: MainViewModel
    private var type = ""
    private var errorCount = 3
    private lateinit var goldfinger: Goldfinger
    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, "") ?: ""
        mainViewModel = ViewModelProvider(requireActivity())[MainViewModel::class.java]
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        _bn = FragmentPinDialogBinding.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()

        goldfinger = Goldfinger.Builder(requireContext()).build()

        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) loadBiometric()
            }

            BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
                bn.btnFingerPrint.isVisible = false
            }
            BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
                bn.btnFingerPrint.isVisible = false
            }
            else -> Unit
        }
    }

    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)
    }


    private fun loadFingerPrint() {
        if (goldfinger.canAuthenticate()) {
            val params = Goldfinger.PromptParams.Builder(this)
                .title(getString(R.string.biometric_enter))
                .description(getString(R.string.enter_from_finger_or_face))
                .negativeButtonText(getString(R.string.cancel))
                .build()

            goldfinger.authenticate(params, object : Goldfinger.Callback {
                override fun onResult(result: Goldfinger.Result) {
                    if (result.type() == Goldfinger.Type.SUCCESS) {
                        navigate()
                    }
                }

                override fun onError(e: Exception) {}
            })
        }

    }

    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()
    }
}