(function(){
    const PER_PAGE = 50;

    // Per-tab state
    const tabState = {
        location: { items: [], currentPage: 0, totalPages: 1, loaded: false },
        event:    { items: [], currentPage: 0, totalPages: 1, loaded: false },
        particle: { items: [], currentPage: 0, totalPages: 1, loaded: false }
    };

    let activeType = 'location';
    let isLoading = false;
    let focusedIndex = -1;

    const LABELS = {
        location: 'locations',
        event:    'events',
        particle: 'particles'
    };

    const listEl = document.getElementById('items-list');
    const searchInput = document.getElementById('search-input');
    const statusEl = document.getElementById('status');
    const noResultsEl = document.getElementById('no-results');
    const loadMoreBtn = document.getElementById('load-more');
    const loadingMoreEl = document.getElementById('loading-more');
    const tabs = document.querySelectorAll('.tab[data-type]');

    function setStatus(msg) { if (statusEl) statusEl.textContent = msg; }
    function showLoadMore(show) { if (loadMoreBtn) loadMoreBtn.classList.toggle('hidden', !show); }
    function showLoadingMore(show) { if (loadingMoreEl) loadingMoreEl.classList.toggle('hidden', !show); }

    function escapeHtml(unsafe) {
        if (!unsafe) return '';
        return String(unsafe)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }

    function decodeHtmlEntities(html) {
        if (!html) return '';
        try {
            const d = document.createElement('div');
            d.innerHTML = html;
            return d.textContent || d.innerText || '';
        } catch (e) {
            return String(html);
        }
    }

    // --- Rendering ---

    function renderItem(item) {
        const li = document.createElement('li');
        li.setAttribute('role', 'option');
        li.dataset.id = item.id;
        li.tabIndex = -1;
        li.className = 'item-card';

        const rawTitle = (item.title && item.title.rendered) ? item.title.rendered : (item.name || 'Untitled');
        const title = decodeHtmlEntities(rawTitle);
        const rawExcerpt = (item.excerpt && item.excerpt.rendered) ? item.excerpt.rendered : '';
        const excerpt = decodeHtmlEntities(rawExcerpt.replace(/<[^>]+>/g, ''));

        let metaHtml = '';

        // Location-specific fields
        if (activeType === 'location' && item.acf) {
            const parts = [];
            if (item.acf.location_place) parts.push(decodeHtmlEntities(String(item.acf.location_place)));
            if (item.acf.location_province) parts.push(decodeHtmlEntities(String(item.acf.location_province)));
            if (parts.length) {
                metaHtml += `<div class="item-meta">${escapeHtml(parts.join(', '))}</div>`;
            }
        }

        // Event-specific fields
        if (activeType === 'event' && item.acf) {
            const parts = [];
            if (item.acf.event_date) parts.push(decodeHtmlEntities(String(item.acf.event_date)));
            if (item.acf.event_location) parts.push(decodeHtmlEntities(String(item.acf.event_location)));
            if (parts.length) {
                metaHtml += `<div class="item-meta">${escapeHtml(parts.join(' — '))}</div>`;
            }
        }

        // Particle-specific fields
        if (activeType === 'particle') {
            if (item.particle_type) {
                metaHtml += `<span class="tax">Type: ${escapeHtml(decodeHtmlEntities(String(item.particle_type)))}</span>`;
            }
            if (item.particle_tags && Array.isArray(item.particle_tags) && item.particle_tags.length) {
                const decodedTags = item.particle_tags.map(t => decodeHtmlEntities(String(t)));
                metaHtml += `<div class="tax">Tags: ${escapeHtml(decodedTags.join(', '))}</div>`;
            }
        }

        li.innerHTML = `<div class="item-title">${escapeHtml(title)}</div>`
            + (excerpt ? `<div class="item-excerpt">${escapeHtml(excerpt)}</div>` : '')
            + metaHtml;

        li.addEventListener('click', () => {
            if (item.link) {
                chrome.runtime.sendMessage({ openNewTab: true, url: item.link });
            }
        });
        li.addEventListener('mouseenter', () => setFocusOnItem(li));
        return li;
    }

    function renderList(items) {
        if (!listEl) return;
        listEl.innerHTML = '';
        const label = LABELS[activeType] || 'items';
        if (!items || items.length === 0) {
            noResultsEl && noResultsEl.classList.remove('hidden');
            setStatus(`No ${label}`);
            return;
        }
        noResultsEl && noResultsEl.classList.add('hidden');
        items.forEach(item => listEl.appendChild(renderItem(item)));
        const state = tabState[activeType];
        if (state.totalPages > 1) {
            setStatus(`Showing ${items.length} ${label} (page ${state.currentPage}/${state.totalPages})`);
        } else {
            setStatus(`Showing ${items.length} ${label}`);
        }
    }

    function filterItems(q) {
        const t = (q || '').toLowerCase();
        const items = tabState[activeType].items;
        if (!t) return items;
        return items.filter(i => {
            const title = (i.title && i.title.rendered) ? i.title.rendered.toLowerCase() : (i.name || '').toLowerCase();
            const excerpt = (i.excerpt && i.excerpt.rendered) ? i.excerpt.rendered.toLowerCase() : '';
            // Search across ACF fields too
            let acfText = '';
            if (i.acf) {
                acfText = Object.values(i.acf).filter(v => typeof v === 'string').join(' ').toLowerCase();
            }
            const type = i.particle_type ? String(i.particle_type).toLowerCase() : '';
            const tags = (i.particle_tags || []).join(' ').toLowerCase();
            return title.includes(t) || excerpt.includes(t) || acfText.includes(t) || type.includes(t) || tags.includes(t);
        });
    }

    // --- Focus / Keyboard ---

    function setFocusOnItem(li) {
        const prev = listEl.querySelector('.focused');
        if (prev) prev.classList.remove('focused');
        li.classList.add('focused');
        focusedIndex = Array.prototype.indexOf.call(listEl.children, li);
        li.scrollIntoView({ block: 'nearest' });
    }

    function focusByOffset(offset) {
        const children = listEl.children;
        if (!children || children.length === 0) return;
        let next = focusedIndex + offset;
        if (next < 0) next = 0;
        if (next > children.length - 1) next = children.length - 1;
        const li = children[next];
        if (li) setFocusOnItem(li);
    }

    document.addEventListener('keydown', function(e) {
        const activeId = document.activeElement && document.activeElement.id;
        if (activeId === 'search-input') return;
        if (e.key === 'ArrowDown') { e.preventDefault(); focusByOffset(1); }
        if (e.key === 'ArrowUp') { e.preventDefault(); focusByOffset(-1); }
        if (e.key === 'Enter') {
            const children = listEl.children;
            if (focusedIndex >= 0 && focusedIndex < children.length) {
                children[focusedIndex].click();
            }
        }
    });

    // --- Data fetching ---

    function fetchPage(contentType, page) {
        return new Promise((resolve) => {
            let called = false;
            const timer = setTimeout(() => {
                if (!called) {
                    called = true;
                    console.error('Timeout waiting for background response');
                    resolve({ success: false, error: 'timeout' });
                }
            }, 12000);

            try {
                chrome.runtime.sendMessage(
                    { type: 'fetchPage', contentType, page, per_page: PER_PAGE },
                    function(resp) {
                        if (called) return;
                        called = true;
                        clearTimeout(timer);
                        if (!resp) return resolve({ success: false, error: 'no response' });
                        resolve(resp);
                    }
                );
            } catch (e) {
                if (!called) {
                    called = true;
                    clearTimeout(timer);
                    resolve({ success: false, error: e && e.message ? e.message : String(e) });
                }
            }
        });
    }

    function normalizeItem(raw) {
        const item = Object.assign({}, raw);
        try {
            if (item.title && item.title.rendered) {
                item.title = Object.assign({}, item.title, { rendered: decodeHtmlEntities(item.title.rendered) });
            }
            if (item.excerpt && item.excerpt.rendered) {
                const ex = item.excerpt.rendered.replace(/<[^>]+>/g, '');
                item.excerpt = Object.assign({}, item.excerpt, { rendered: decodeHtmlEntities(ex) });
            }
        } catch (e) {}
        if (raw.acf && raw.acf.particle_type) item.particle_type = decodeHtmlEntities(String(raw.acf.particle_type));
        if (raw.acf && raw.acf.particle_tags) item.particle_tags = raw.acf.particle_tags.map(t => decodeHtmlEntities(String(t)));
        if (!item.particle_tags && raw.tags && Array.isArray(raw.tags)) item.particle_tags = raw.tags.map(String).map(t => decodeHtmlEntities(t));
        return item;
    }

    async function loadInitial(contentType) {
        const state = tabState[contentType];
        if (state.loaded) return; // already loaded
        setStatus('Loading…');
        const resp = await fetchPage(contentType, 1);
        if (resp && resp.success) {
            state.currentPage = 1;
            state.totalPages = resp.totalPages || 1;
            state.items = (resp.items || []).map(normalizeItem);
            state.loaded = true;
        } else {
            console.error(`Initial fetch ${contentType} failed`, resp && resp.error);
        }
    }

    async function loadNextPage() {
        if (isLoading) return;
        const state = tabState[activeType];
        if (state.currentPage >= state.totalPages) return;
        isLoading = true;
        const next = state.currentPage + 1;
        if (loadMoreBtn) { loadMoreBtn.disabled = true; loadMoreBtn.classList.add('hidden'); }
        showLoadingMore(true);
        setStatus('Loading more...');
        try {
            const resp = await fetchPage(activeType, next);
            if (resp && resp.success) {
                state.currentPage = next;
                state.totalPages = resp.totalPages || state.totalPages;
                const normalized = (resp.items || []).map(normalizeItem);
                state.items.push(...normalized);
                const q = searchInput ? searchInput.value : '';
                renderList(filterItems(q));
                showLoadMore(state.currentPage < state.totalPages);
            } else {
                console.error('Failed load page', resp && resp.error);
                setStatus('Failed to load page');
                showLoadMore(true);
            }
        } catch (e) {
            console.error('Exception while loading next page', e);
            setStatus('Failed to load page');
            showLoadMore(true);
        } finally {
            isLoading = false;
            showLoadingMore(false);
            if (loadMoreBtn) loadMoreBtn.disabled = false;
        }
    }

    // --- Tab switching ---

    async function switchTab(contentType) {
        activeType = contentType;
        focusedIndex = -1;

        // Update tab UI
        tabs.forEach(t => {
            const isActive = t.dataset.type === contentType;
            t.classList.toggle('active', isActive);
            t.setAttribute('aria-selected', isActive ? 'true' : 'false');
        });

        // Update search placeholder
        if (searchInput) {
            searchInput.placeholder = `Search ${LABELS[contentType] || 'items'}...`;
            searchInput.value = '';
        }

        const state = tabState[contentType];
        if (!state.loaded) {
            listEl.innerHTML = '';
            noResultsEl && noResultsEl.classList.add('hidden');
            showLoadMore(false);
            await loadInitial(contentType);
        }

        if (state.loaded) {
            renderList(state.items);
            showLoadMore(state.currentPage < state.totalPages);
        } else {
            setStatus(`Failed to load ${LABELS[contentType]}`);
            noResultsEl && noResultsEl.classList.remove('hidden');
        }

        const first = listEl && listEl.children && listEl.children[0];
        if (first) setFocusOnItem(first);
    }

    // --- Init ---

    function debounce(fn, wait) {
        let t;
        return function(...args) {
            clearTimeout(t);
            t = setTimeout(() => fn.apply(this, args), wait);
        };
    }

    // Tab click handlers
    tabs.forEach(tab => {
        tab.addEventListener('click', () => switchTab(tab.dataset.type));
    });

    if (loadMoreBtn) loadMoreBtn.addEventListener('click', loadNextPage);

    if (searchInput) searchInput.addEventListener('input', debounce(function(e) {
        const q = e.target.value;
        renderList(filterItems(q));
        const first = listEl && listEl.children && listEl.children[0];
        if (first) setFocusOnItem(first);
    }, 150));

    document.addEventListener('DOMContentLoaded', async function() {
        await switchTab('location');
    });

})();
