/**
 * Generic "Show More" progressive-loading component.
 *
 * Loads an initial batch server-side (rendered by PHP on first page load),
 * then fetches subsequent batches from a JSON endpoint on click and appends
 * the returned HTML to a container — until every matching row has been
 * loaded. Deliberately framework-free and endpoint-agnostic (the endpoint
 * decides what "a row" means and returns pre-rendered HTML for it) so this
 * one file can back any long, filterable list in TraderAlign — Journal
 * Trades today, Reports or elsewhere later — without copying this logic
 * per page.
 *
 * Usage:
 *   <div id="my-list">...server-rendered first batch...</div>
 *   <div id="my-load-more-wrap"><button id="my-load-more-btn" data-loaded="10" data-total="137">Show More</button></div>
 *   <script src="/traderalign/assets/js/progressive-list.js"></script>
 *   <script>
 *     initProgressiveList({
 *       containerId: 'my-list',
 *       buttonId: 'my-load-more-btn',
 *       wrapId: 'my-load-more-wrap',
 *       endpoint: '/traderalign/api/journal/trades-more',
 *       perPage: 10,
 *       params: { instrument: 'eurusd' },   // optional, merged into every request
 *       countLabelId: 'my-count-label',      // optional — updated to "Showing X of Y"
 *       countNoun: 'trade'                   // optional, singular noun for the count label
 *     });
 *   </script>
 */
function initProgressiveList(opts) {
    var container = document.getElementById(opts.containerId);
    var btn = document.getElementById(opts.buttonId);
    var wrap = document.getElementById(opts.wrapId);
    if (!container || !btn || !wrap) return;

    var perPage = opts.perPage || 10;
    var params = opts.params || {};
    var countLabel = opts.countLabelId ? document.getElementById(opts.countLabelId) : null;
    var countNoun = opts.countNoun || 'item';

    function updateCountLabel(loaded, total) {
        if (!countLabel) return;
        var noun = total === 1 ? countNoun : countNoun + 's';
        countLabel.textContent = 'Showing ' + loaded + ' of ' + total + ' ' + noun;
    }

    btn.addEventListener('click', function () {
        var loaded = parseInt(btn.getAttribute('data-loaded') || '0', 10);
        var total = parseInt(btn.getAttribute('data-total') || '0', 10);

        btn.disabled = true;
        var originalLabel = btn.textContent;
        btn.textContent = 'Loading…';

        var url = new URL(opts.endpoint, window.location.origin);
        Object.keys(params).forEach(function (key) {
            var value = params[key];
            if (value !== null && value !== undefined && value !== '') {
                url.searchParams.set(key, value);
            }
        });
        url.searchParams.set('offset', loaded);
        url.searchParams.set('limit', perPage);

        fetch(url.toString(), { credentials: 'same-origin' })
            .then(function (r) {
                if (!r.ok) throw new Error('Request failed');
                return r.json();
            })
            .then(function (data) {
                if (data.html) container.insertAdjacentHTML('beforeend', data.html);
                var newLoaded = typeof data.loaded === 'number' ? data.loaded : (loaded + (data.count || 0));
                var newTotal = typeof data.total === 'number' ? data.total : total;
                btn.setAttribute('data-loaded', newLoaded);
                btn.setAttribute('data-total', newTotal);
                updateCountLabel(newLoaded, newTotal);
                btn.disabled = false;
                btn.textContent = originalLabel;
                if (!data.hasMore || newLoaded >= newTotal) {
                    wrap.style.display = 'none';
                }
            })
            .catch(function () {
                btn.disabled = false;
                btn.textContent = 'Show More - Try Again';
            });
    });
}
