/**
 * core/logical-children.js — wrapper-piercing light-DOM child access.
 *
 * The template engine wraps EVERY interpolated value — a single result OR a
 * `.map()` / `repeat()` array — in a `display:contents` / `role="presentation"`
 * span (core/template.js `wrap()` + the Array branch). So a `:scope > [slot="X"]`
 * direct-child query (or a `for (… of this.children)` loop) MISSES interpolated
 * slotted children: they arrive as grand-children of a wrapper span, not direct
 * children of the host. This is the recurring "wrapper trap" (FB-92 menu #show,
 * FB-96 tree #stamp, FB-98 select #parseOptions, agent-artifact actions).
 * `scripts/dev/audit-wrapper-trap.mjs` flags the un-pierced reads.
 *
 * `logicalChildren(host)` returns the host's LOGICAL direct children — its
 * direct element children, but recursing THROUGH (and dropping) the transparent
 * wrapper spans — so interpolated and static children read identically.
 * `logicalSlotted(host, name)` filters those to `slot="<name>"`.
 *
 * Consolidates the per-component hand-rolled walks (select `#logicalOptionChildren`,
 * tree `#logicalSlotChildren`) into one tested helper.
 */

/** A transparent template-engine wrapper span (never authored by a consumer). */
const isWrapper = (el) =>
  el.getAttribute?.('role') === 'presentation' || el.style?.display === 'contents';

/**
 * The host's logical direct element children, piercing display:contents /
 * role="presentation" wrapper spans (depth-first, wrappers flattened away).
 * @param {Element} host
 * @returns {Element[]}
 */
export function logicalChildren(host) {
  const out = [];
  const walk = (nodes) => {
    for (const n of nodes) {
      if (n.nodeType !== 1) continue;        // elements only (slotted children are elements)
      if (isWrapper(n)) { walk(n.children); continue; } // pierce + drop the wrapper
      out.push(n);
    }
  };
  if (host) walk(host.children);
  return out;
}

/**
 * Logical direct children carrying `slot="<slotName>"`, wrapper-pierced.
 * Use `.length` for a stamp-if-absent guard, `[0]` for the single case, or the
 * array for a collection grab — all safe against interpolated content.
 * @param {Element} host
 * @param {string} slotName
 * @returns {Element[]}
 */
export function logicalSlotted(host, slotName) {
  return logicalChildren(host).filter((el) => el.getAttribute('slot') === slotName);
}
