package com.app.simplitend.patientprofile.medicalinfo;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.text.InputFilter;
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 com.app.simplitend.apputils.EditTextErrorRemover;
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.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.databinding.AddMedicalInfoBinding;
import com.app.simplitend.patientprofile.ProfileContracts;
import com.app.simplitend.patientprofile.medicalinfo.mvvm.MedicalInfoViewModel;
import com.app.simplitend.patientprofile.medicalinfo.mvvm.MedicationInfo;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;

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

import okhttp3.MediaType;
import okhttp3.RequestBody;

public class AddMedicalInfoFragment extends Fragment implements
        ProfileContracts.AddMedicalIntoCallback {

    // view binding
    protected AddMedicalInfoBinding binding;

    private MedicalInfoViewModel medicalInfoViewModel;

    private ProgressDialog progressDialog;

    private MedicationInfo medicalInfo;
    public static final String MEDICAL_INFO_KEY = "medical_info";
    private ArrayList<String> countryCodeList;

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

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

        medicalInfoViewModel = new ViewModelProvider(requireActivity()).get(MedicalInfoViewModel.class);

        initViews();

        clickEvents();

        return binding.getRoot();
    }

    private void initViews() {
        progressDialog = new ProgressDialog(requireContext());

        // populating country code list

        countryCodeList = medicalInfoViewModel.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);

        // 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 = null;

            if (binding.countryCodes.getSelectedIndex() != -1){
                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 (country_code != null && !countryCodeList.contains(country_code)){
                countryCodeList.add(country_code);
            }

            if (country_code != null){
                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.phoneNumber.getText().toString() + phone_number_str;

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

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

        // arguments

        Bundle bundle = getArguments();

        if (bundle != null && bundle.getSerializable(MEDICAL_INFO_KEY) != null){
            medicalInfo = (MedicationInfo) bundle.getSerializable(MEDICAL_INFO_KEY);
            setLayoutInfo();
        }

        binding.primaryDoc.addTextChangedListener(TextUtils.LEADING_SPACE_WATCHER);
        new EditTextErrorRemover(binding.diagnosis,
                binding.allergies,
                binding.primaryDoc,
                binding.phoneNumber,
                binding.hospitalPref,
                binding.dietRestrict);
    }

    private void setLayoutInfo() {
        if (medicalInfo == null) return;

        binding.diagnosis.setText(medicalInfo.diagnosis);
        binding.primaryDoc.setText(medicalInfo.primary_care_doctor);

        if (medicalInfo.doctor_phone_number != null)
        {
            binding.phoneNumber.setText(medicalInfo.doctor_phone_number);
        }

        binding.hospitalPref.setText(medicalInfo.hospital_preference);
        binding.allergies.setText(medicalInfo.allergies);
        binding.dietRestrict.setText(medicalInfo.diet_restriction);

        binding.addBtn.setText(getString(R.string.save));
    }

    private void clickEvents() {

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

        binding.addBtn.setOnClickListener(v -> {

            if (allOkay()){
                if (medicalInfo != null){
                    AppUtil.showSOSDecision(requireContext(),
                            getString(R.string.make_changes), getString(R.string.yes), getString(R.string.no),
                            yes -> {
                                // yes click
                                addMedicationInfo();
                            }, no -> {
                                // no click
                            });
                }else{
                    addMedicationInfo();
                }
            }
        });

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

    private void addMedicationInfo() {

        progressDialog.setTitle("Please wait");
        progressDialog.setMessage("while we add your medical information.");
        progressDialog.setCancelable(false);
        progressDialog.show();

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

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

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

        String phoneNumber = "";

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

        phoneNumber += " ";
        phoneNumber += binding.phoneNumber.getText().toString();

        RequestBody doc_contact_body = RequestBody.create(phoneNumber,
                MediaType.parse("text/plain"));
        body.put("doctor_phone_number", doc_contact_body);

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

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

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

        RequestBody is_update_body;
        if (medicalInfo == null){
            // intent is to add medical info
            // thus, is_update is 0

            is_update_body = RequestBody.create("0",
                    MediaType.parse("text/plain"));

        }else{
            // intent is to update info
            // thus, is_update is 1

            is_update_body = RequestBody.create("1",
                    MediaType.parse("text/plain"));
        }

        body.put("is_update", is_update_body);

        String token = "Bearer " + AppUtil.getPatientToken(requireContext());

        medicalInfoViewModel.addNUpdateMedicalInfo(body,
                AppUtil.getPatientUid(requireContext()),
                token,
                this);

    }

    private boolean allOkay() {
        boolean allOkay = true;

        if (binding.diagnosis.getText().toString().trim().isEmpty()){
            allOkay = false;
            binding.diagnosis.setError("Required");
        }

        if (binding.primaryDoc.getText().toString().trim().isEmpty()){
            allOkay = false;
            binding.primaryDoc.setError("Required");
        }

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

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

        if (binding.hospitalPref.getText().toString().trim().isEmpty()){
            allOkay = false;
            binding.hospitalPref.setError("Required");
        }

        if (binding.allergies.getText().toString().trim().isEmpty()){
            allOkay = false;
            binding.allergies.setError("Required");
        }

        if (binding.dietRestrict.getText().toString().trim().isEmpty()){
            allOkay = false;
            binding.dietRestrict.setError("Required");
        }

        if (allOkay && binding.countryCodes.getSelectedIndex() == -1){
            allOkay = false;
            Toast.makeText(requireContext(), "Select a country code", Toast.LENGTH_SHORT).show();
        }

        return allOkay;
    }

    @Override
    public void onMedicalInfoAdded(MedicationInfo medicationInfo) {
        progressDialog.dismiss();

        String title;

        if (this.medicalInfo == null){
            title = getString(R.string.med_added_successful);
        }else{
            title = getString(R.string.changes_successful);
        }

        AppUtil.showAnimateDBS(requireContext(),
                title,
                R.raw.done_anim_primary, 3600,
                yes -> {
                    Activity activity = getActivity();
                    if (activity != null){
                        activity.onBackPressed();
                    }
                });

    }

    @Override
    public void onMedicalInfoAddFailed(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);
    }
}
