package com.lemenzo.multisms;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public final class MultiContactPickerActivity extends Activity {
    static final String EXTRA_SELECTED_NAMES = "selected_names";
    static final String EXTRA_SELECTED_NUMBERS = "selected_numbers";
    static final String EXTRA_SELECTED_DATA_IDS = "selected_data_ids";

    static final class ContactEntry {
        final long dataId;
        final String name;
        final String number;
        ContactEntry(long dataId, String name, String number) {
            this.dataId = dataId;
            this.name = name;
            this.number = number;
        }
    }

    private final ExecutorService io = Executors.newSingleThreadExecutor();
    private final ArrayList<ContactEntry> all = new ArrayList<>();
    private final ArrayList<ContactEntry> shown = new ArrayList<>();
    private final LinkedHashMap<String, ContactEntry> selected = new LinkedHashMap<>();

    private ContactAdapter adapter;
    private EditText search;
    private TextView empty;
    private TextView selectedCount;
    private String query = "";

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        restoreSelection();
        build();
        loadContacts();
    }

    @Override
    protected void onDestroy() {
        io.shutdownNow();
        super.onDestroy();
    }

    private void restoreSelection() {
        String[] names = getIntent().getStringArrayExtra(EXTRA_SELECTED_NAMES);
        String[] numbers = getIntent().getStringArrayExtra(EXTRA_SELECTED_NUMBERS);
        long[] ids = getIntent().getLongArrayExtra(EXTRA_SELECTED_DATA_IDS);
        if (numbers == null) return;

        for (int i = 0; i < numbers.length; i++) {
            String number = GroupStore.normalize(numbers[i]);
            if (number.isEmpty()) continue;
            String name = names != null && i < names.length ? names[i] : number;
            long id = ids != null && i < ids.length ? ids[i] : -1;
            selected.put(number, new ContactEntry(id, name, number));
        }
    }

    private void build() {
        LinearLayout root = new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);
        root.setBackgroundColor(getColor(R.color.lemenzo_background));
        root.setPadding(Ui.dp(this, 18), Ui.dp(this, 8), Ui.dp(this, 18), Ui.dp(this, 12));
        Ui.applySafeInsets(root);

        LinearLayout header = new LinearLayout(this);
        header.setGravity(Gravity.CENTER_VERTICAL);

        ImageButton back = Ui.iconButton(this, R.drawable.ic_back, getString(R.string.navigate_back));
        back.setOnClickListener(v -> finish());
        header.addView(back, new LinearLayout.LayoutParams(Ui.dp(this, 48), Ui.dp(this, 54)));

        TextView title = Ui.text(this, getString(R.string.add_members), 23, true);
        header.addView(title, new LinearLayout.LayoutParams(0, Ui.dp(this, 56), 1f));

        TextView done = Ui.text(this, getString(R.string.done), 15, true);
        done.setTextColor(getColor(R.color.lemenzo_blue));
        done.setGravity(Gravity.CENTER);
        done.setPadding(Ui.dp(this, 12), 0, Ui.dp(this, 8), 0);
        done.setOnClickListener(v -> finishSelection());
        header.addView(done, new LinearLayout.LayoutParams(-2, Ui.dp(this, 54)));
        root.addView(header);

        LinearLayout searchShell = new LinearLayout(this);
        searchShell.setGravity(Gravity.CENTER_VERTICAL);
        searchShell.setBackgroundResource(R.drawable.search_background);
        searchShell.setPadding(Ui.dp(this, 12), 0, Ui.dp(this, 12), 0);

        ImageButton searchIcon = Ui.iconButton(this, R.drawable.ic_search, getString(R.string.search_contacts));
        searchIcon.setClickable(false);
        searchIcon.setFocusable(false);
        searchShell.addView(searchIcon, new LinearLayout.LayoutParams(Ui.dp(this, 42), Ui.dp(this, 50)));

        search = new EditText(this);
        search.setSingleLine(true);
        search.setTextSize(16);
        search.setTextColor(getColor(R.color.lemenzo_text_primary));
        search.setHintTextColor(getColor(R.color.lemenzo_text_muted));
        search.setHint(R.string.search_contacts);
        search.setBackgroundColor(Color.TRANSPARENT);
        search.setPadding(Ui.dp(this, 2), 0, 0, 0);
        searchShell.addView(search, new LinearLayout.LayoutParams(0, Ui.dp(this, 52), 1f));

        LinearLayout.LayoutParams searchLp = new LinearLayout.LayoutParams(-1, Ui.dp(this, 52));
        searchLp.setMargins(0, Ui.dp(this, 4), 0, Ui.dp(this, 8));
        root.addView(searchShell, searchLp);

        selectedCount = Ui.text(this, "", 14, true);
        selectedCount.setTextColor(getColor(R.color.lemenzo_blue));
        selectedCount.setPadding(Ui.dp(this, 6), Ui.dp(this, 4), 0, Ui.dp(this, 8));
        root.addView(selectedCount, new LinearLayout.LayoutParams(-1, -2));
        updateSelectedCount();

        ListView list = new ListView(this);
        list.setDivider(null);
        list.setDividerHeight(0);
        list.setCacheColorHint(Color.TRANSPARENT);
        list.setBackgroundColor(Color.TRANSPARENT);
        list.setClipToPadding(false);
        list.setPadding(0, Ui.dp(this, 2), 0, Ui.dp(this, 12));
        adapter = new ContactAdapter();
        list.setAdapter(adapter);
        list.setOnItemClickListener((p, v, pos, id) -> toggle(shown.get(pos)));
        root.addView(list, new LinearLayout.LayoutParams(-1, 0, 1f));

        empty = Ui.text(this, getString(R.string.no_contacts_found), 15, false);
        empty.setTextColor(getColor(R.color.lemenzo_text_secondary));
        empty.setGravity(Gravity.CENTER);
        empty.setVisibility(View.GONE);
        root.addView(empty, new LinearLayout.LayoutParams(-1, Ui.dp(this, 64)));

        search.addTextChangedListener(new TextWatcher() {
            public void beforeTextChanged(CharSequence s, int st, int c, int a) {}
            public void onTextChanged(CharSequence s, int st, int b, int c) {
                query = s == null ? "" : s.toString();
                filter();
            }
            public void afterTextChanged(Editable e) {}
        });

        setContentView(root);
    }

    private void loadContacts() {
        io.execute(() -> {
            ArrayList<ContactEntry> loaded = new ArrayList<>();
            Set<String> seen = new HashSet<>();
            String[] projection = {
                    ContactsContract.CommonDataKinds.Phone._ID,
                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
                    ContactsContract.CommonDataKinds.Phone.NUMBER
            };

            try (Cursor c = getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    projection,
                    null,
                    null,
                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY
                            + " COLLATE LOCALIZED ASC")) {
                if (c != null) {
                    while (c.moveToNext()) {
                        long dataId = c.getLong(0);
                        String name = c.getString(1);
                        String number = GroupStore.normalize(c.getString(2));
                        if (number.isEmpty() || !seen.add(number)) continue;
                        if (name == null || name.trim().isEmpty()) {
                            name = getString(R.string.unknown_contact);
                        }
                        loaded.add(new ContactEntry(dataId, name, number));
                    }
                }
            } catch (RuntimeException ignored) {}

            runOnUiThread(() -> {
                if (isFinishing() || isDestroyed()) return;
                all.clear();
                all.addAll(loaded);
                filter();
            });
        });
    }

    private void filter() {
        String q = query == null ? "" : query.trim().toLowerCase(Locale.getDefault());
        String normalizedQuery = GroupStore.normalize(q);
        shown.clear();

        for (ContactEntry e : all) {
            boolean nameMatch = q.isEmpty()
                    || e.name.toLowerCase(Locale.getDefault()).contains(q);
            boolean numberMatch = !normalizedQuery.isEmpty()
                    && e.number.contains(normalizedQuery);
            if (nameMatch || numberMatch) shown.add(e);
        }

        adapter.notifyDataSetChanged();
        empty.setVisibility(shown.isEmpty() ? View.VISIBLE : View.GONE);
    }

    private void toggle(ContactEntry e) {
        if (selected.containsKey(e.number)) selected.remove(e.number);
        else selected.put(e.number, e);
        updateSelectedCount();
        adapter.notifyDataSetChanged();
    }

    private void updateSelectedCount() {
        selectedCount.setText(getString(R.string.selected_count, selected.size()));
    }

    private void finishSelection() {
        int size = selected.size();
        String[] names = new String[size];
        String[] numbers = new String[size];
        long[] ids = new long[size];
        int i = 0;
        for (ContactEntry e : selected.values()) {
            names[i] = e.name;
            numbers[i] = e.number;
            ids[i] = e.dataId;
            i++;
        }

        Intent result = new Intent();
        result.putExtra(EXTRA_SELECTED_NAMES, names);
        result.putExtra(EXTRA_SELECTED_NUMBERS, numbers);
        result.putExtra(EXTRA_SELECTED_DATA_IDS, ids);
        setResult(RESULT_OK, result);
        finish();
    }

    private final class ContactAdapter extends BaseAdapter {
        @Override public int getCount() { return shown.size(); }
        @Override public Object getItem(int p) { return shown.get(p); }
        @Override public long getItemId(int p) { return shown.get(p).dataId; }

        @Override
        public View getView(int p, View convert, ViewGroup parent) {
            LinearLayout row;
            TextView avatar, name, number, check;

            if (convert == null) {
                row = new LinearLayout(MultiContactPickerActivity.this);
                row.setGravity(Gravity.CENTER_VERTICAL);
                row.setPadding(Ui.dp(MultiContactPickerActivity.this, 6),
                        Ui.dp(MultiContactPickerActivity.this, 8),
                        Ui.dp(MultiContactPickerActivity.this, 6),
                        Ui.dp(MultiContactPickerActivity.this, 8));

                avatar = Ui.text(MultiContactPickerActivity.this, "", 15, true);
                avatar.setGravity(Gravity.CENTER);
                avatar.setTextColor(getColor(R.color.lemenzo_text_primary));
                avatar.setBackgroundResource(R.drawable.avatar_background);
                row.addView(avatar, new LinearLayout.LayoutParams(
                        Ui.dp(MultiContactPickerActivity.this, 46),
                        Ui.dp(MultiContactPickerActivity.this, 46)));

                LinearLayout texts = new LinearLayout(MultiContactPickerActivity.this);
                texts.setOrientation(LinearLayout.VERTICAL);
                texts.setGravity(Gravity.CENTER_VERTICAL);
                texts.setPadding(Ui.dp(MultiContactPickerActivity.this, 14), 0,
                        Ui.dp(MultiContactPickerActivity.this, 8), 0);

                name = Ui.text(MultiContactPickerActivity.this, "", 17, false);
                texts.addView(name, new LinearLayout.LayoutParams(-1, -2));

                number = Ui.text(MultiContactPickerActivity.this, "", 13, false);
                number.setTextColor(getColor(R.color.lemenzo_text_secondary));
                texts.addView(number, new LinearLayout.LayoutParams(-1, -2));

                row.addView(texts, new LinearLayout.LayoutParams(0,
                        Ui.dp(MultiContactPickerActivity.this, 58), 1f));

                check = Ui.text(MultiContactPickerActivity.this, "", 15, true);
                check.setGravity(Gravity.CENTER);
                row.addView(check, new LinearLayout.LayoutParams(
                        Ui.dp(MultiContactPickerActivity.this, 28),
                        Ui.dp(MultiContactPickerActivity.this, 28)));

                row.setTag(new TextView[]{avatar, name, number, check});
            } else {
                row = (LinearLayout) convert;
                TextView[] tags = (TextView[]) row.getTag();
                avatar = tags[0];
                name = tags[1];
                number = tags[2];
                check = tags[3];
            }

            ContactEntry e = shown.get(p);
            name.setText(e.name);
            number.setText(e.number);

            String trimmed = e.name.trim();
            avatar.setText(trimmed.isEmpty()
                    ? "?"
                    : trimmed.substring(0, 1).toUpperCase(Locale.getDefault()));

            boolean isSelected = selected.containsKey(e.number);
            check.setText(isSelected ? "✓" : "");
            check.setTextColor(Color.WHITE);
            check.setBackgroundResource(isSelected
                    ? R.drawable.selection_selected
                    : R.drawable.selection_unselected);

            return row;
        }
    }
}
