package com.app.simplitend.welcome.welcomecg.fragments;

import static com.app.simplitend.welcome.welcomecg.fragments.CgConnectFragment.CAREGIVER_EMAIL;

import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.Spanned;
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.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Toast;

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

import com.app.simplitend.apputils.TextUtils;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.onesignal.OneSignal;
import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.CaregiverDataCache;
import com.app.simplitend.apputils.EditTextErrorRemover;
import com.app.simplitend.databinding.CgRegisterFragmentBinding;
import com.app.simplitend.databinding.PasswordPopUpBinding;
import com.app.simplitend.welcome.welcomecg.WelcomeContracts;
import com.app.simplitend.welcome.welcomecg.mvvm.CareGiverData;
import com.app.simplitend.welcome.welcomecg.mvvm.CgWelcomeViewModel;

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

import okhttp3.MediaType;
import okhttp3.RequestBody;

public class CgRegisterFragment extends Fragment implements WelcomeContracts.RegisterCareGiverCallback {

    private static final String TAG = "CgRegisterFragment";

    protected CgRegisterFragmentBinding binding;

    private ProgressDialog progressDialog;

    private CgWelcomeViewModel viewModel;

    private DatePickerDialog datePickerDialog;

    private ArrayList<String> countryCodeList;

    private PopupWindow passwordWindow;

    private String mPassword;

    private Calendar dob_selected;

    public CgRegisterFragment() {
        // required
    }

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

        // password details 'i' button popup view
        PasswordPopUpBinding popUpBinding = PasswordPopUpBinding.inflate(inflater);
        passwordWindow = new PopupWindow(popUpBinding.getRoot(), LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT,
                true);

        viewModel = new ViewModelProvider(requireActivity()).get(CgWelcomeViewModel.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");

        dob_selected = Calendar.getInstance();

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

        setErrorRemovers();

        setFocusManager();

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

    private void clickEvents() {

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

        binding.submit.setOnClickListener(v -> {
            if (allOkay()) {
                AppUtil.closeKeyboard(requireActivity());

                progressDialog.setTitle("Please wait...");
                progressDialog.setMessage("while we register you as a caregiver.");
                progressDialog.setCancelable(false);
                progressDialog.show();

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

                RequestBody name_body = RequestBody.create(binding.name.getText().toString().trim(), MediaType.parse("text/plain"));
                body.put("full_name", name_body);

                RequestBody dob_body = RequestBody.create(binding.dob.getHint().toString(), MediaType.parse("text/plain"));
                body.put("date_of_birth", dob_body);

                String phone_number = "";

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

                phone_number += binding.contactNumber.getText().toString();

                RequestBody contact_body = RequestBody.create(phone_number, MediaType.parse("text/plain"));
                body.put("contact_number", contact_body);

                RequestBody email_body = RequestBody.create(binding.email.getText().toString().trim(), MediaType.parse("text/plain"));
                body.put("email", email_body);

                if (binding.password.getText() == null) {
                    mPassword = "";
                } else {
                    mPassword = binding.password.getText().toString();
                }

                RequestBody password_body = RequestBody.create(mPassword, MediaType.parse("text/plain"));
                body.put("password", password_body);

                String sub_id = OneSignal.getUser().getPushSubscription().getId();

                if (sub_id != null){
                    RequestBody one_signal_player_id_body = RequestBody.create(sub_id, MediaType.parse("text/plain;charset=utf-8") );
                    body.put("one_signal_player_id", one_signal_player_id_body);
                }

                viewModel.registerCareGiver(body, this);

            }
        });

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

            pickDate();
        });

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

        binding.pwdInfo.setOnClickListener(v -> {
            passwordWindow.showAsDropDown(binding.pwdTitle);
        });

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

    }

    private void setErrorRemovers() {
        new EditTextErrorRemover(
                binding.name,
                binding.contactNumber,
                binding.email
        );

        // 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 setFocusManager() {
        binding.name.setOnEditorActionListener((textView, i, keyEvent) -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.name.clearFocus();
            pickDate();
            return true;
        });
    }

    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());
        SimpleDateFormat sdf2 = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault());

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

        // time in dd-mm-yyyy format in the hint for registering the caregiver
        binding.dob.setHint(sdf2.format(cal.getTime()));
    }

    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.getText().toString().trim().length() < 10) {
            binding.contactNumber.setError("Invalid");
            allOkay = false;
        } 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 (allOkay && binding.password.getText() != null && binding.confirmPassword.getText() != null) {
            String password = binding.password.getText().toString();

            if (password.length() < 8) {
                allOkay = false;
                Toast.makeText(requireContext(), "Password must be at least 8 characters.", Toast.LENGTH_SHORT).show();
            } else if (password.contains(" ")) {
                allOkay = false;
                Toast.makeText(requireContext(), "Password should not contains white spaces.", Toast.LENGTH_SHORT).show();
            } else if (!password.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^a-zA-Z0-9]).{8,}$")) {
                allOkay = false;
                Toast.makeText(requireContext(), "Password doesn't match the required criteria.", Toast.LENGTH_SHORT).show();
                passwordWindow.showAsDropDown(binding.pwdTitle);
            } else if (!binding.confirmPassword.getText().toString().equals(password)) {
                allOkay = false;
                Toast.makeText(requireContext(), "Confirm password doesn't match.", Toast.LENGTH_SHORT).show();
            }
        }

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

    @Override
    public void onCareGiverRegistered(CareGiverData careGiverData, String token) {
        Toast.makeText(requireContext(), "Caregiver registered successfully.", Toast.LENGTH_SHORT).show();

        CaregiverDataCache.setCareGiverData(careGiverData);

        AppUtil.saveCgData(token, careGiverData.patientId, requireContext());

        Bundle bundle = new Bundle();
        bundle.putString(CAREGIVER_EMAIL, careGiverData.email);

        progressDialog.dismiss();

        NavOptions navOptions = new NavOptions.Builder()
                .setPopUpTo(R.id.welcomeFragment, true)
                .build();

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

    @Override
    public void onRegisterFailed(Throwable t, String message) {
        progressDialog.dismiss();
        AppUtil.showAlert(requireContext(),
                getString(R.string.something_went_wrong),
                message,
                getString(R.string.ok),
                ((dialogInterface, i) -> {
                }),
                null, null);
    }
}
