package com.app.simplitend.welcome.welcomepatient.fragments.forgotpin;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;

import com.bumptech.glide.Glide;
import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.databinding.CheckMailFragmentBinding;
import com.app.simplitend.welcome.welcomepatient.mvvm.WelcomeContracts;
import com.app.simplitend.welcome.welcomepatient.mvvm.WelcomeViewModel;
import com.app.simplitend.welcome.welcomepatient.mvvm.models.OTPSentResponse;

import java.util.HashMap;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.RequestBody;

public class CheckMailFragment extends Fragment implements WelcomeContracts.VerifyOTPCallback,
        WelcomeContracts.SendOTPToEmailCallback{

    // view binding
    protected CheckMailFragmentBinding binding;

    private WelcomeViewModel viewModel;

    private ProgressDialog progressDialog;

    private String user_id;

    private String email_id;

    public CheckMailFragment() {
        // required empty const.
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = CheckMailFragmentBinding.inflate(inflater, container, false);

        viewModel = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class);

        initViews();

        clickEvents();

        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Bundle bundle = getArguments();

        if (bundle == null || bundle.getString(ForgotPinFragment.USER_ID_KEY) == null || bundle.getString(ForgotPinFragment.EMAIL_KEY) == null) {
            Toast.makeText(requireContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
            Navigation.findNavController(binding.getRoot()).popBackStack();
            return;
        }

        user_id = bundle.getString(ForgotPinFragment.USER_ID_KEY);
        email_id = bundle.getString(ForgotPinFragment.EMAIL_KEY);
        try {
            binding.email.setText(encodeEmail(bundle.getString(ForgotPinFragment.EMAIL_KEY)));
        }catch (Exception e){
            binding.email.setText(email_id);
        }

    }

    private void initViews() {

        progressDialog = new ProgressDialog(requireContext());

        // showing gif
        Glide.with(binding.image)
                .asGif()
                .load(R.raw.email_sending_anim)
                .placeholder(R.drawable.forgot_pin_email_img)
                .into(binding.image);

        initOTPBoxes();

    }

    /*
       setting text change listener for every edit text for otp
    */
    private void initOTPBoxes() {

        binding.otp1.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().trim().isEmpty()) {
                    binding.otp2.requestFocus();
                    if (checkOTPInputs()){
                        AppUtil.closeKeyboard(requireActivity());
                    }
                }

                // check if all otp boxes are filled

            }
        });

        binding.otp2.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().trim().isEmpty()) {
                    binding.otp3.requestFocus();
                    if (checkOTPInputs()){
                        AppUtil.closeKeyboard(requireActivity());
                    }
                } else {
                    binding.otp1.requestFocus();
                }

                // check if all otp boxes are filled

            }
        });

        binding.otp3.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().trim().isEmpty()) {
                    binding.otp4.requestFocus();
                    if (checkOTPInputs()){
                        AppUtil.closeKeyboard(requireActivity());
                    }
                } else {
                    binding.otp2.requestFocus();
                }

                // check if all otp boxes are filled

            }
        });

        binding.otp4.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().trim().isEmpty()) {
                    // last otp inserted
                    AppUtil.closeKeyboard(getActivity());
                } else {
                    binding.otp3.requestFocus();
                }

                // check if all otp boxes are filled

            }
        });

    }

    private void clickEvents() {

        binding.backBtn.setOnClickListener(v -> {
            if (getActivity() != null){
                getActivity().onBackPressed();
            }
        });

        binding.submit.setOnClickListener(v -> {

            if (checkOTPInputs()){
                verifyOTP();
            }else {
                Toast.makeText(requireContext(), "Enter PIN received on your email.", Toast.LENGTH_SHORT).show();
            }

        });

        binding.resendOtp.setOnClickListener(v -> {
            sendOTP();
        });

    }

    private void verifyOTP() {
        progressDialog.setTitle("Please wait");
        progressDialog.setMessage("while we verify your OTP.");
        progressDialog.setCancelable(false);
        progressDialog.show();

        Map<String, RequestBody> body = new HashMap<>();

        RequestBody otp_body = RequestBody.create(getOTPFromInputs(), MediaType.parse("text/plain"));
        body.put("otp_code", otp_body);
        RequestBody user_id_body = RequestBody.create(user_id, MediaType.parse("text/plain"));
        body.put("user_id", user_id_body);

        viewModel.verifyOTP(body, this);
    }

    private void sendOTP() {
        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("while we resend an OTP to your email.");
        progressDialog.setCancelable(false);
        progressDialog.show();

        viewModel.sendOTPToEmail(email_id,
                this);

    }

    private String getOTPFromInputs() {
        return binding.otp1.getText().toString() +
                binding.otp2.getText().toString() +
                binding.otp3.getText().toString() +
                binding.otp4.getText().toString();
    }

    public boolean checkOTPInputs(){

        if (binding.otp3.getText().toString().trim().length() != 1){
            return false;
        }else if (binding.otp2.getText().toString().trim().length() != 1){
            return false;
        }else if (binding.otp3.getText().toString().trim().length() != 1){
            return false;
        }else if (binding.otp4.getText().toString().trim().length() != 1){
            return false;
        }

        return true;
    }

    public String encodeEmail(String email) throws Exception{
        String[] arr = email.split("@");
        String email_name = arr[0];

        StringBuilder encoded_email = new StringBuilder();

        for (int i = 0; i<email_name.length()-1; i++){
            encoded_email.append("*");
        }

        encoded_email.append(email_name.charAt(email_name.length()-1));

        return encoded_email + "@" + arr[1];
    }

    private void clearInputs() {
        binding.otp1.setText(null);
        binding.otp2.setText(null);
        binding.otp3.setText(null);
        binding.otp4.setText(null);

        binding.otp1.requestFocus();
    }

    @Override
    public void onOTPVerified() {
        progressDialog.dismiss();

        Toast.makeText(requireContext(), "OTP verified successfully", Toast.LENGTH_SHORT).show();

        Bundle bundle = new Bundle();
        bundle.putString(ForgotPinFragment.EMAIL_KEY, email_id);

        Navigation.findNavController(binding.getRoot())
                .navigate(R.id.action_checkMailFragment_to_changePinFragment, bundle);
    }

    @Override
    public void onOTPVerificationFailed(Throwable t, String message) {
        progressDialog.dismiss();

        Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
    }

    // resend otp call back

    @Override
    public void onOTPSent(OTPSentResponse otpSentResponse) {
        progressDialog.dismiss();

        user_id = otpSentResponse.principal_xid;
        Toast.makeText(requireContext(), "OTP resent successfully.", Toast.LENGTH_SHORT).show();

        clearInputs();
    }

    @Override
    public void onOTPSentFailed(Throwable t, String message) {
        progressDialog.dismiss();

        AppUtil.showAlert(requireContext(),
                getString(R.string.something_went_wrong),
                message,
                getString(R.string.ok),
                ((dialog, which) -> {
                    dialog.dismiss();
                }), null, null);
    }
}
