/* The Upper Room — icon + avatar helpers.
   Icons render from Lucide (loaded via UMD before this script). We
   serialize Lucide's real icon paths to an SVG string and inject via
   dangerouslySetInnerHTML so React owns a stable wrapper (avoids the
   classic lucide+React replaceChild bug). */

function _toPascal(name) {
  return name.split('-').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('');
}

function _iconSvg(name) {
  const L = window.lucide;
  if (!L) return '';
  const node = (L.icons && (L.icons[_toPascal(name)] || L.icons[name])) || L[_toPascal(name)];
  if (!node || !Array.isArray(node)) return '';
  // Lucide node = ["svg", svgAttrs, [ [tag, attrs], ... ]]; older builds = just the child array.
  const children = (node[0] === 'svg' && Array.isArray(node[2])) ? node[2] : node;
  const kids = children.map((part) => {
    if (!Array.isArray(part)) return '';
    const tag = part[0];
    const attrs = part[1] || {};
    const a = Object.keys(attrs).map((k) => `${k}="${attrs[k]}"`).join(' ');
    return `<${tag} ${a}></${tag}>`;
  }).join('');
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${kids}</svg>`;
}

function Icon({ name, size = 20, strokeWidth, fill }) {
  const html = React.useMemo(() => {
    let s = _iconSvg(name);
    if (!s) return '';
    if (strokeWidth) s = s.replace('stroke-width="2"', 'stroke-width="' + strokeWidth + '"');
    if (fill) s = s.replace('fill="none"', 'fill="' + fill + '"');
    return s;
  }, [name, strokeWidth, fill]);
  return (
    <span className="ic" style={{ display: 'inline-flex', width: size, height: size }}
      dangerouslySetInnerHTML={{ __html: html.replace('<svg ', `<svg width="${size}" height="${size}" `) }} />
  );
}

/* deterministic warm avatar color from a name */
const _AV_COLORS = ['#c8714a', '#a85a38', '#8a5a3c', '#6b4a2f', '#2c1f0f', '#b06a44', '#9c5d3a'];
function avatarColor(name) {
  let h = 0;
  for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) % 997;
  return _AV_COLORS[h % _AV_COLORS.length];
}
function initials(name) {
  const p = name.trim().split(/\s+/);
  return ((p[0] ? p[0][0] : '') + (p[1] ? p[1][0] : '')).toUpperCase();
}

/* If a `photo` is given (or the name matches a known member with a photo),
   render the image; otherwise fall back to deterministic initials.
   Looks up CURRENT_USER so any Avatar for the signed-in user shows their
   picture without every call site having to pass it. */
function Avatar({ name, photo, className, style, onClick }) {
  let src = photo;
  if (!src && typeof CURRENT_USER !== 'undefined' && name === CURRENT_USER.name && CURRENT_USER.photo) {
    src = CURRENT_USER.photo;
  }
  return (
    <div className={'avatar ' + (className || '')} style={{ background: avatarColor(name), ...(style || {}) }} onClick={onClick}>
      {src ? <img src={src} alt={name} /> : initials(name)}
    </div>
  );
}

function RoomBrand() {
  return <span className="ur-brand-lockup"><span className="ur-brand-glyph">✝</span><span className="ur-brand-wm">The Upper <span>Room</span></span></span>;
}

/* Shared engagement gate: guests (skipped profile) can read but not act.
   canEngage=false → engagement controls call promptComplete(). */
window.RoomContext = React.createContext({ canEngage: true, promptComplete: function () {}, resumeSetup: function () {}, openPost: function () {}, openProfile: function () {}, openCompose: function () {}, goView: function () {}, search: function () {}, share: function () {}, signOut: function () {}, flash: 0 });

Object.assign(window, { Icon, Avatar, avatarColor, initials, RoomBrand });
