// Row-click → row-lock + tooltip-portal for the My Buds list.
//
// Bud landing page sprint 2026-05-27 ([[project-bud-landing-page-sprint]]).
// Mirrors apps/applets/row-lock.js's lock/unlock state machine, but binds
// to `.bud-entry` rows (which are NOT `.row-3col`) AND populates the
// shared `#id_tooltip_portal` from the row's data-tt-* attrs.
//
// Click target semantics:
//   • Click on the inner `<a>` (the `@<handle>` anchor) — let it navigate
//     to the bud's landing page. NO lock fires.
//   • Click anywhere else inside `.bud-entry` — lock the row + open the
//     tooltip portal w. its data-tt-* fields populated.
//   • Click outside any `.bud-entry` (and outside the portal) — clear.
//
// `.tt-milestone` is REMOVED from the DOM (vs. emptied) when the row's
// `data-tt-milestone` attr is absent so the FT can distinguish "never
// edited" (slot absent) from "cleared after edit" (slot empty).

(function () {
    'use strict';

    var _lockedRow = null;
    var _portal = null;
    var _milestoneTemplate = null;

    function _clearLock() {
        if (_lockedRow) {
            _lockedRow.classList.remove('row-locked');
            _lockedRow = null;
        }
        if (_portal) {
            _portal.classList.remove('active');
            // Reset positional props so the next show measures fresh.
            _portal.style.top = '';
            _portal.style.bottom = '';
            _portal.style.left = '';
        }
    }

    // Clamp the position:fixed portal to the viewport — same 1rem-inset
    // shape as game-kit.js / sky-wheel.js / wallet.js. Called AFTER .active
    // makes the portal display:block so offsetWidth/Height are real: clamp
    // the left edge into [rem, viewport-ttW-rem], then prefer ABOVE the row
    // (flip BELOW when the tooltip is too tall to fit above).
    function _positionPortal(row) {
        if (!_portal) return;
        var rect = row.getBoundingClientRect();
        var rem = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
        var ttW = _portal.offsetWidth;
        var ttH = _portal.offsetHeight;

        var minLeft = rem;
        var maxLeft = window.innerWidth - ttW - rem;
        var clampedLeft = Math.max(minLeft, Math.min(rect.left, maxLeft));
        _portal.style.left = clampedLeft + 'px';

        var spaceAbove = rect.top - rem;
        if (ttH <= spaceAbove) {
            _portal.style.bottom = (window.innerHeight - rect.top + 8) + 'px';
            _portal.style.top = '';
        } else {
            _portal.style.top = (rect.bottom + 8) + 'px';
            _portal.style.bottom = '';
        }
    }

    function _findSlot(name) {
        if (!_portal) return null;
        return _portal.querySelector('.tt-' + name);
    }

    function _populatePortal(row) {
        if (!_portal) return;
        var fields = ['title', 'description', 'email', 'shoptalk'];
        fields.forEach(function (f) {
            var slot = _findSlot(f);
            if (slot) slot.textContent = row.dataset['tt' + f.charAt(0).toUpperCase() + f.slice(1)] || '';
        });
        // .tt-milestone — absent when never-edited; present (+ populated)
        // when the row carries data-tt-milestone.
        var ms = row.dataset.ttMilestone;
        var existing = _findSlot('milestone');
        if (ms) {
            if (!existing) {
                var span = _milestoneTemplate.cloneNode(true);
                span.textContent = ms;
                _portal.appendChild(span);
            } else {
                existing.textContent = ms;
            }
        } else {
            if (existing) existing.remove();
        }
    }

    function _onClick(e) {
        // Anchor click — let navigation proceed; no lock/portal.
        if (e.target.closest('.bud-entry .bud-name a')) {
            _clearLock();
            return;
        }
        var row = e.target.closest('.bud-entry');
        if (row) {
            if (row === _lockedRow) {
                _clearLock();
            } else {
                _clearLock();
                row.classList.add('row-locked');
                _lockedRow = row;
                _populatePortal(row);
                if (_portal) {
                    _portal.classList.add('active');
                    _positionPortal(row);
                }
            }
            return;
        }
        // Click inside the portal itself — preserve lock.
        if (_portal && _portal.contains(e.target)) return;
        _clearLock();
    }

    function _init() {
        _portal = document.getElementById('id_tooltip_portal');
        if (_portal) {
            // Snapshot the milestone element shape so we can restore it
            // after a never-edited row removes it.
            var ms = _portal.querySelector('.tt-milestone');
            if (ms) _milestoneTemplate = ms.cloneNode(false);
        }
        document.addEventListener('click', _onClick);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', _init);
    } else {
        _init();
    }
}());
