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

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.Settings;
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.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.app.simplitend.R;
import com.app.simplitend.databinding.ContactListFragmentBinding;
import com.app.simplitend.welcome.welcomepatient.fragments.contacts.mvvm.Contact;
import com.app.simplitend.welcome.welcomepatient.fragments.contacts.mvvm.ContactViewModel;
import com.app.simplitend.welcome.welcomepatient.fragments.contacts.mvvm.models.ContactData;

import java.util.ArrayList;

public class ContactListFragment extends Fragment {

    // view binding
    protected ContactListFragmentBinding binding;

    protected ContactListAdapter contactListAdapter;

    protected ContactViewModel contactViewModel;

    protected ActivityResultLauncher<String> permissionLauncher;
    protected ActivityResultLauncher<Intent> settingsIntent;

    protected ActivityResultLauncher<Intent> insertContactLauncher;

    private ArrayList<ArrayList<Contact>> contactList;

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

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

        initializeViews();

        clickEvents();

        return binding.getRoot();
    }

    private void clickEvents() {

        binding.backBtn.setOnClickListener(v -> {
            requireActivity().onBackPressed();
        });

        binding.createContact.setOnClickListener(v ->
                {
                    // insert contact intent
                    Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
                    intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

                    insertContactLauncher.launch(intent);
                }
        );

        contactListAdapter.setContactClickListener(contact ->
                {
                    Bundle bundle = new Bundle();
                    bundle.putBoolean(CreateContactFragment.TO_EDIT_KEY, false);
                    bundle.putSerializable(CreateContactFragment.CONTACT_KEY, new ContactData(contact));

                    try {
                        Navigation.findNavController(binding.getRoot()).navigate(R.id.action_contactListFragment_to_createContactFragment, bundle);
                    }catch (Exception e){
                        // this fragment is not only opened by the welcome_vav_graph
                        try {
                            getParentFragmentManager().beginTransaction()
                                    .replace(R.id.fcv_profile_shower, CreateContactFragment.class, bundle)
                                    .addToBackStack("create_contact_f")
                                    .commitAllowingStateLoss();
                        } catch (Exception ex) {
                            // user may be out of context
                        }
                    }
                }
        );

        binding.askPermission.setOnClickListener(v -> {
            askContactPermission();
        });

        binding.search.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) {
                filterContactList(s.toString().trim().toLowerCase());
            }
        });

    }

    private void askContactPermission() {
        if (requireActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            if(!shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)){
                // user has selected to never ask them again for the permission
                binding.errorView.setVisibility(View.VISIBLE);
                binding.title.setText(getString(R.string.we_understand_your_privacy));
                binding.subTitle.setText(getString(R.string.to_help_you_connect_with_your_loved_ones_allow_simplitend_to_access_your_contacts));
                binding.askPermission.setVisibility(View.VISIBLE);

                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", requireContext().getPackageName(), null));
                settingsIntent.launch(intent);
                return;
            }

            permissionLauncher.launch(Manifest.permission.READ_CONTACTS);
        }

        // permission is already granted
        loadContacts();
    }

    // filters contact list w.r.t searchInput
    private void filterContactList(String searchInput) {

        new Thread(() -> {

            if (searchInput.isEmpty()) {
                submitContactList(contactList);
                return;
            }

            ArrayList<ArrayList<Contact>> filteredList = new ArrayList<>();

            for (ArrayList<Contact> contacts: contactList){
                if (contacts == null || contacts.isEmpty() || contacts.get(0).first_name == null) continue;

                if (contacts.get(0).first_name.trim().toLowerCase().contains(searchInput.trim().toLowerCase())){
                    filteredList.add(contacts);
                }

            }

            if (filteredList.isEmpty()) {
                new Handler(Looper.getMainLooper()).post(() -> {
                    Toast.makeText(requireContext(), "No match found", Toast.LENGTH_SHORT).show();
                });
            }

            if (contactListAdapter != null) contactListAdapter.submitList(filteredList);

            binding.contactRv.smoothScrollToPosition(0);

        }).start();

    }

    private void submitContactList(ArrayList<ArrayList<Contact>> list) {
        if (contactList != null && contactList.isEmpty()){
            binding.errorView.setVisibility(View.VISIBLE);
            binding.askPermission.setVisibility(View.GONE);

            binding.title.setText(getString(R.string.no_contacts_found));
            binding.subTitle.setText(getString(R.string.there_are_no_contacts_added_in_your_contact_directory_please_click_on_the_create_new_contact_button_above));
        }else{
            binding.errorView.setVisibility(View.GONE);
            binding.contactRv.setVisibility(View.VISIBLE);

            if (contactListAdapter != null) contactListAdapter.submitList(list);
        }
    }

    @SuppressLint("Range")
    private void initializeViews() {
        // initiating recycler view for contact list
        contactListAdapter = new ContactListAdapter();
        binding.contactRv.setLayoutManager(new LinearLayoutManager(requireContext()));
        binding.contactRv.setAdapter(contactListAdapter);

        permissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
                granted -> {
                    if (granted) {
                        // user granted the READ_CONTACT permission
                        binding.errorView.setVisibility(View.GONE);
                        loadContacts();
                    } else {
                        // user didn't allow permission to read contacts
                        binding.errorView.setVisibility(View.VISIBLE);
                        binding.title.setText(getString(R.string.we_understand_your_privacy));
                        binding.subTitle.setText(getString(R.string.to_help_you_connect_with_your_loved_ones_allow_simplitend_to_access_your_contacts));
                        binding.askPermission.setVisibility(View.VISIBLE);
                    }
                }
        );

        insertContactLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                result -> {

                    loadContacts();

                });

        settingsIntent = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    loadContacts();
                });

        loadContacts();

    }

    /*
        loads user's local contacts
     */
    private void loadContacts() {
        if (requireActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            permissionLauncher.launch(Manifest.permission.READ_CONTACTS);
            return;
        }

        contactViewModel = new ViewModelProvider(requireActivity()).get(ContactViewModel.class);

        contactList = null;
        contactList = contactViewModel.getContactList(requireContext());

        if (binding.search.getText().toString().trim().isEmpty())
        {
            submitContactList(contactList);
        }
        else {
            binding.errorView.setVisibility(View.GONE);
            filterContactList(binding.search.getText().toString().trim().toLowerCase());
        }
    }
}
