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

import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.text.InputFilter;
import android.util.Log;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
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.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.EditTextErrorRemover;
import com.app.simplitend.apputils.TextUtils;
import com.app.simplitend.databinding.RegisterFragmentBinding;
import com.app.simplitend.welcome.welcomepatient.mvvm.WelcomeContracts;
import com.app.simplitend.welcome.welcomepatient.mvvm.WelcomeViewModel;
import com.app.simplitend.welcome.welcomepatient.mvvm.models.PatientData;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class RegisterFragment extends Fragment implements WelcomeContracts.VerifyEmailCallBack {

    private static final String TAG = "RegisterFragment";

    // view binding
    protected RegisterFragmentBinding binding;

    // view model
    private WelcomeViewModel viewModel;

    private ArrayList<String> countryCodeList;

    private ProgressDialog progressDialog;

    private DatePickerDialog datePickerDialog;

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

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

        initViews();

        clickEvents();

        return binding.getRoot();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (getActivity() != null) {
            getActivity().getWindow()
                    .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        }
    }

    private void initViews() {

        progressDialog = new ProgressDialog(requireContext());

        // date picker dialog
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 18);

        datePickerDialog = new DatePickerDialog(requireContext(),
                (datePicker, year, month, dayOfMonth) -> {
                    setDOB(year, month, dayOfMonth);

                    binding.contactNumber.requestFocus();

                    if (getActivity() != null) {
                        getActivity().getWindow()
                                .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
                    }
                }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
        datePickerDialog.getDatePicker().setMaxDate(calendar.getTimeInMillis());

        // max age 120 years
        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 18 - 122);
        datePickerDialog.getDatePicker().setMinDate(calendar.getTimeInMillis());
        datePickerDialog.setTitle("Select a date");
        datePickerDialog.setMessage("Note: Click on the date, month or year to edit manually");

        countryCodeList = viewModel.loadCountryCodeDropDown(requireContext());

        binding.countryCodes.setLifecycleOwner(this);

        binding.countryCodes.setItems(countryCodeList);

        if (!countryCodeList.contains("+1")) {
            countryCodeList.add("+1");
        }

        binding.countryCodes.selectItemByIndex(countryCodeList.indexOf("+1"));

        binding.countryCodes.setDismissWhenNotifiedItemSelected(true);

        binding.countryCodes.setIsFocusable(true);

        setPhoneNumberInputFilter();

        loadPatientDataSavedState();

        setFocusManager();

        // not allowing leading spaces
        binding.name.addTextChangedListener(TextUtils.LEADING_SPACE_WATCHER);
        binding.email.addTextChangedListener(TextUtils.LEADING_SPACE_WATCHER);

        // error remover
        new EditTextErrorRemover(
                binding.name,
                binding.email,
                binding.contactNumber
        );
    }

    private void setFocusManager() {
        binding.name.setOnEditorActionListener((textView, i, keyEvent) -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.name.clearFocus();

            pickDate();
            return true;
        });
    }

    // This adds textChangeListener to all the EditTexts available to remove error if available
    private void setPhoneNumberInputFilter() {
        // phone number formatting
        // to deal with input pasting in the edit text
        InputFilter phoneFilter = (charSequence, i, i1, spanned, i2, i3) -> {
            String phone_number_str = charSequence.toString();

            String country_code;

            if (binding.countryCodes.getSelectedIndex() == -1) {
                country_code = "+1";
            } else {
                country_code = countryCodeList.get(binding.countryCodes.getSelectedIndex());
            }

            try {
                PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
                Phonenumber.PhoneNumber phoneNumber = phoneNumberUtil.parse(charSequence, "US");

                phone_number_str = String.valueOf(phoneNumber.getNationalNumber());
                country_code = "+" + phoneNumber.getCountryCode();
            } catch (Exception e) {
                // nothing
            }

            if (!countryCodeList.contains(country_code)) {
                countryCodeList.add(country_code);
            }

            binding.countryCodes.selectItemByIndex(countryCodeList.indexOf(country_code));

            if (phone_number_str.length() > 10) {
                // pasted number length is greater than 10
                return phone_number_str.substring(0, 10);
            }

            String total_phone_number = binding.contactNumber.getText().toString() + phone_number_str;

            if (total_phone_number.length() > 10) {
                // max length should be 10
                return "";
            } else {
                return phone_number_str;
            }
        };

        binding.contactNumber.setFilters(new InputFilter[]{phoneFilter});

    }

    private void loadPatientDataSavedState() {
        // loading data from view model
        PatientData patientData = viewModel.getPatientData();

        binding.name.setText(patientData.first_name);
        binding.dob.setText(patientData.date_of_birth);

        if (patientData.phone_number != null) {
            binding.contactNumber.setText(patientData.phone_number);
        }

        binding.email.setText(patientData.email);
    }

    private void clickEvents() {

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

        binding.nextBtn.setOnClickListener(v -> {

            removeExistingErrors();

            if (allOkay()) {
                AppUtil.closeKeyboard(requireActivity());

                progressDialog.setTitle("Please wait...");
                progressDialog.setMessage("while we verify your entered email.");
                progressDialog.setCancelable(false);
                progressDialog.show();

                viewModel.verifyEmail(binding.email.getText().toString().trim(), this);
            }
        });

        binding.dob.setOnClickListener(v -> {
            binding.dob.setError(null);

            pickDate();
        });

        binding.tncBtn.setOnClickListener(v -> {
            AppUtil.openLink(requireActivity(), getString(R.string.terms_n_conditions_link),
                    getString(R.string.terms_conditions_));
        });

        binding.countryCodes.setOnClickListener(v -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.countryCodes.showOrDismiss();
        });

    }

    private void removeExistingErrors() {
        binding.name.setError(null);
        binding.dob.setError(null);
        binding.contactNumber.setError(null);
        binding.email.setError(null);
    }

    private boolean allOkay() {

        boolean allOkay = true;

        if (binding.name.getText().toString().trim().isEmpty()) {
            binding.name.setError("Required");
            allOkay = false;
        }else if (binding.name.getText().toString().trim().length() < 2){
            binding.name.setError("Minimum 2 characters");
            allOkay = false;
        }

        if (binding.dob.getText().toString().trim().isEmpty()) {
            binding.dob.setError("Required");
            allOkay = false;
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());
            try {
                Date selected_date = sdf.parse(binding.dob.getText().toString().trim());
                Calendar selected_calender = Calendar.getInstance();

                if (selected_date == null) throw new Exception();

                selected_calender.setTime(selected_date);

                Calendar minAdultAge = Calendar.getInstance();
                minAdultAge.add(Calendar.YEAR, -18);

                if (minAdultAge.before(selected_calender)) {
                    Toast.makeText(requireContext(), "Age must be above 18+ years", Toast.LENGTH_SHORT).show();
                }

            } catch (Exception e) {
                Log.e(TAG, "allOkay: ", e);
                // TODO: 17-07-2023 check out this thing
            }
        }

        if (binding.contactNumber.getText().toString().trim().isEmpty()) {
            binding.contactNumber.setError("Required");
            allOkay = false;
        } else if (binding.contactNumber.getText().toString().trim().length() < 10) {
            binding.contactNumber.setError("Phone number should be 10 digits");
        } else if (binding.countryCodes.getSelectedIndex() == -1 ||
                binding.countryCodes.getSelectedIndex() >= countryCodeList.size()) {
            allOkay = false;
            Toast.makeText(requireContext(), "Select a country code.", Toast.LENGTH_SHORT).show();
        } else {
            // validating phone number
            try {
                Phonenumber.PhoneNumber phone_number = PhoneNumberUtil.getInstance().parse(countryCodeList.get(binding.countryCodes.getSelectedIndex()) +
                        binding.contactNumber.getText().toString(), "US");

                if (!PhoneNumberUtil.getInstance().isValidNumber(phone_number)) {
                    binding.contactNumber.setError("Invalid phone number");
                    allOkay = false;
                }
            } catch (NumberParseException e) {
                // do nothing as we couldn't validate phone number
            }
        }

        if (binding.email.getText().toString().trim().isEmpty()) {
            binding.email.setError("Required");
            allOkay = false;
        } else if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.getText().toString()).matches()) {
            binding.email.setError("Invalid email");
            allOkay = false;
        }

        if (!binding.tncCheck.isChecked() && allOkay) {
            AppUtil.showAlert(requireContext(),
                    "Accept terms and conditions",
                    "Please check terms and conditions to continue.",
                    "Ok",
                    ((dialogInterface, i) -> {
                        // do nothing
                    }), null, null
            );
            allOkay = false;
        }

        return allOkay;
    }

    public void goForward() {
        PatientData patientData = viewModel.getPatientData();

        patientData.first_name = patientData.user_name = binding.name.getText().toString().trim();
        patientData.phone_number = countryCodeList.get(binding.countryCodes.getSelectedIndex())
                + " " + binding.contactNumber.getText().toString();
        patientData.date_of_birth = binding.dob.getText().toString();
        patientData.email = binding.email.getText().toString().trim();

        Navigation.findNavController(binding.getRoot()).navigate(R.id.action_registerFragment_to_locationFragment);
    }

    @Override
    public void onEmailVerified(boolean exists, String message) {
        progressDialog.dismiss();
        if (exists) {
            AppUtil.showAlert(requireContext(),
                    "Email already exists.",
                    message,
                    getString(R.string.ok),
                    ((dialog, which) -> {
                        dialog.dismiss();
                    }), null, null);
        } else {
            Toast.makeText(requireContext(), "Email verification success.", Toast.LENGTH_SHORT).show();
            goForward();
        }
    }

    @Override
    public void onVerificationFailed() {
        progressDialog.dismiss();
        goForward();
    }

    private void pickDate() {

        if (datePickerDialog == null) return;

        datePickerDialog.show();

    }

    private void setDOB(int year, int month, int dayOfMonth) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);

        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());

        String selected_time = sdf.format(cal.getTime());
        binding.dob.setText(selected_time);
    }
}
