// DSNav2.jsx — Navigation 2.0 shell primitives (Meridian DS)
//
// One bar, five fixed slots:
//   [ Personal ][ Prebuilt A ][ Today·center ][ Prebuilt B ][ Prebuilt C ]
// Today (index 2) is the only static tab — permanently centre, raised. Slot 1
// is the user's personal system; slots 1/3/4 (array idx 1/3/4) hold up to three
// activated prebuilt systems. Chat is a lower-right FAB; You is a top-right
// avatar. Neither is a tab.
//
// Slot labels + glyphs here are ABSTRACT placeholders ("Personal", "Prebuilt A",
// "Prebuilt B", "Prebuilt C") — hosts pass real labels/icons per system. Do not
// hardcode real system names in the DS layer.
//
// Exports (all window globals, DS-prefixed; the old flat bar keeps `DSTabBar`):
//   DSTabBarNav2      — the five-slot bottom bar (state machine per slot).
//   DSChatFab         — lower-right circular chat FAB (+ emphasis ring, + label).
//   DSYouAvatar       — top-right ink avatar, the single "You" entry.
//   DSSlotExplainer   — non-modal popover anchored above a slot (locked / add).
//   DSNav2_slotCenterPct, DSNav2_defaultSlots, DSNav2_placeholders — helpers.
//
// Slot state machine (per non-Today slot):
//   selected → current screen · axis tint icon + label + dot
//   active   → unlocked & navigable, not current · muted glyph + label
//   locked   → gated by onboarding · muted glyph + small lock affordance
//   empty    → open prebuilt slot · dashed "add"/plus glyph
// Today mirrors selected / active / locked on the raised circular button.

// Self-contained glyphs — so this ONE file is a drop-in for every bundle with
// no external window.MIcons dependency. The bar renders byte-identically
// everywhere it is reused (owner: "reuse the same component, every screen").
function N2TodayGlyph({ size = 23, strokeWidth = 2.2, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="3" y="5" width="18" height="16" rx="2" />
      <path d="M3 10h18M8 3v4M16 3v4" />
    </svg>
  );
}
function N2PlusGlyph({ size = 14, strokeWidth = 2.4, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M12 5v14M5 12h14" />
    </svg>
  );
}
function N2ChatGlyph({ size = 24, strokeWidth = 2.2, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M21 15a2 2 0 0 1-2 2H8l-5 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
    </svg>
  );
}

// ── Lock glyph — MIcons has no Lock; inline it here (matches AXIS-6 LockGlyph).
function DSNav2Lock({ size = 12, color = M.inkMuted, strokeWidth = 2.2 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="5" y="11" width="14" height="9" rx="2" />
      <path d="M8 11V8a4 4 0 0 1 8 0v3" />
    </svg>
  );
}

// ── Abstract placeholder glyphs (NOT real system names) ──────────
// Deliberately geometric so the DS layer never implies Sleep / Calm / etc.
const Glyph = (children) => (p = {}) => {
  const { size = 22, strokeWidth = 2.1 } = p;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      {children}
    </svg>
  );
};
const DSNav2_glyphs = {
  // slot 1 — personal system: a single anchored ring (the "you" system)
  personal: Glyph(<><circle cx="12" cy="12" r="7.5" /><circle cx="12" cy="12" r="2.4" fill="currentColor" stroke="none" /></>),
  // prebuilt A / B / C — neutral geometric marks, abstract by design
  prebuiltA: Glyph(<><rect x="4.5" y="4.5" width="15" height="15" rx="4.5" /><path d="M9 12h6" /></>),
  prebuiltB: Glyph(<><path d="M12 3.5l8 4.8v7.4l-8 4.8-8-4.8V8.3z" /></>),
  prebuiltC: Glyph(<><path d="M12 4l2.4 5 5.6.6-4.2 3.7 1.3 5.7L12 16l-5.1 3 1.3-5.7L4 9.6l5.6-.6z" /></>),
};

// 5-slot geometry — centre of slot `index` as a % of bar width (idx 0..4).
function DSNav2_slotCenterPct(index) {
  return (index + 0.5) * 20; // 10, 30, 50, 70, 90
}

// ── Abstract placeholder catalog (host overrides label/icon per system) ──
const DSNav2_placeholders = {
  personal:  { id: 'personal',  kind: 'personal', label: 'Personal',   icon: DSNav2_glyphs.personal },
  prebuiltA: { id: 'prebuiltA', kind: 'prebuilt', label: 'Prebuilt A',  icon: DSNav2_glyphs.prebuiltA },
  today:     { id: 'today',     kind: 'today',    label: 'Today',       icon: (p) => N2TodayGlyph(p) },
  prebuiltB: { id: 'prebuiltB', kind: 'prebuilt', label: 'Prebuilt B',  icon: DSNav2_glyphs.prebuiltB },
  prebuiltC: { id: 'prebuiltC', kind: 'prebuilt', label: 'Prebuilt C',  icon: DSNav2_glyphs.prebuiltC },
};

// A sensible 5-slot example: personal + Today active, two prebuilts active,
// one open. Index 2 is always Today.
function DSNav2_defaultSlots() {
  return [
    { ...DSNav2_placeholders.personal,  state: 'active'   },
    { ...DSNav2_placeholders.prebuiltA, state: 'active'   },
    { ...DSNav2_placeholders.today,     state: 'selected' },
    { ...DSNav2_placeholders.prebuiltB, state: 'active'   },
    { ...DSNav2_placeholders.prebuiltC, state: 'empty'    },
  ];
}

// ── Today (raised, centre) ───────────────────────────────────────
function DSNav2Today({ slot, onTap }) {
  const state = slot.state || 'active';
  const locked = state === 'locked';
  const selected = state === 'selected';
  const active = !locked; // selected or active are both "lit"
  const Ico = slot.icon || ((p) => N2TodayGlyph(p));
  return (
    <button
      type="button"
      aria-label="Today"
      onClick={() => onTap && onTap()}
      style={{
        flex: 1, minWidth: 0, background: 'transparent', border: 'none',
        cursor: locked ? 'default' : 'pointer', padding: 0,
        display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
      }}
    >
      <div style={{ position: 'relative' }}>
        <div style={{
          width: 48, height: 48, borderRadius: 999, marginTop: -22,
          background: active ? M.axis : M.surfaceAlt,
          color: active ? '#fff' : M.inkFaint,
          border: `3px solid ${M.surface}`,
          boxShadow: active
            ? '0 6px 16px rgba(30,58,237,0.32), 0 2px 5px rgba(14,18,32,0.12)'
            : '0 2px 6px rgba(14,18,32,0.10)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Ico size={23} strokeWidth={selected ? 2.5 : 2.2} />
        </div>
        {locked && (
          <span style={{
            position: 'absolute', right: -3, bottom: -1,
            width: 17, height: 17, borderRadius: 999, background: M.surface,
            border: `1px solid ${M.rule}`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}><DSNav2Lock size={10} color={M.inkMuted} /></span>
        )}
      </div>
      <span style={{
        font: `${selected ? 600 : 500} 10px/1 ${M.sans}`, letterSpacing: '0.01em',
        color: selected ? M.axis : locked ? M.inkFaint : M.inkMuted,
      }}>{slot.label || 'Today'}</span>
    </button>
  );
}

// ── A single non-Today slot ──────────────────────────────────────
function DSNav2Slot({ slot, index, onSlot }) {
  const state = slot.state || 'active';
  const Ico = slot.icon || DSNav2_glyphs.prebuiltA;

  const fire = () => onSlot && onSlot(slot.id, state, index);

  // empty (closed slot, no system yet) — dashed "+" + generic "System".
  // A closed slot NEVER shows a specific icon or name (owner rule 2026-06-20).
  if (state === 'empty') {
    return (
      <button type="button" aria-label="Add a system" onClick={fire}
        style={slotBtn}>
        <div style={{
          width: 26, height: 26, borderRadius: 8,
          border: `1.5px dashed ${M.inkFaint}`, color: M.inkFaint,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}><N2PlusGlyph size={14} strokeWidth={2.4} /></div>
        <span style={{ font: `400 10px/1 ${M.sans}`, letterSpacing: '0.01em', color: M.inkFaint }}>
          System
        </span>
      </button>
    );
  }

  // locked (closed + onboarding-gated) — same "+" + "System", with a lock badge.
  if (state === 'locked') {
    return (
      <button type="button" aria-label="System — locked" onClick={fire}
        style={{ ...slotBtn, cursor: 'pointer' }}>
        <div style={{
          position: 'relative', width: 26, height: 26, borderRadius: 8,
          border: `1.5px dashed ${M.rule}`, color: M.inkFaint, opacity: 0.75,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <N2PlusGlyph size={14} strokeWidth={2.4} />
          <span style={{
            position: 'absolute', right: -5, bottom: -4,
            width: 14, height: 14, borderRadius: 999, background: M.surface,
            border: `1px solid ${M.rule}`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}><DSNav2Lock size={9} color={M.inkMuted} /></span>
        </div>
        <span style={{ font: `400 10px/1 ${M.sans}`, letterSpacing: '0.01em', color: M.inkFaint }}>
          System
        </span>
      </button>
    );
  }

  // selected (axis tint + dot) or active (muted, navigable)
  const selected = state === 'selected';
  const col = selected ? M.axis : M.inkMuted;
  return (
    <button type="button" aria-label={slot.label} onClick={fire}
      style={slotBtn} aria-current={selected ? 'page' : undefined}>
      <span style={{ display: 'flex', color: col }}>
        <Ico size={22} strokeWidth={selected ? 2.4 : 2.1} />
      </span>
      <span style={{
        font: `${selected ? 600 : 500} 10px/1 ${M.sans}`, letterSpacing: '0.01em', color: col,
        maxWidth: 64, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
      }}>{slot.label}</span>
      {selected && <span style={{ width: 4, height: 4, borderRadius: 999, background: M.axis }} />}
    </button>
  );
}

const slotBtn = {
  flex: 1, minWidth: 0, background: 'transparent', border: 'none', cursor: 'pointer',
  padding: '2px 0', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
};

// ── DSTabBarNav2 — the five-slot bar ─────────────────────────────
// props:
//   slots    — length-5 array; index 2 is Today. Each: { id, kind, state, label, icon }
//   selected — optional id of the selected slot (sugar; per-slot `state:'selected'`
//              also works). When given, that slot renders selected.
//   onSlot   — (id, state, index) on tap; host decides what locked/empty taps do.
//   dimmed   — soften the whole bar (used in the fully-locked interrupted state).
function DSTabBarNav2({ slots = DSNav2_defaultSlots(), selected, onSlot, dimmed = false, style }) {
  const resolved = slots.map((s, i) => {
    if (selected != null && s.id === selected) return { ...s, state: 'selected' };
    return s;
  });
  return (
    <nav style={{
      display: 'flex', alignItems: 'flex-end',
      background: M.surface, borderTop: `1px solid ${M.rule}`,
      padding: '8px 6px 10px', boxShadow: '0 -1px 2px rgba(14,18,32,0.03)',
      opacity: dimmed ? 0.94 : 1, ...style,
    }}>
      {resolved.map((s, i) => (
        i === 2
          ? <DSNav2Today key={s.id || i} slot={s} onTap={() => onSlot && onSlot(s.id, s.state, i)} />
          : <DSNav2Slot key={s.id || i} slot={s} index={i} onSlot={onSlot} />
      ))}
    </nav>
  );
}

// ── DSChatFab — lower-right circular chat entry ──────────────────
// emphasis adds the blue glow ring used when the whole bar is locked.
function DSChatFab({ emphasis = false, label, bottom = 84, right = 18, onClick, style }) {
  return (
    <button
      type="button"
      aria-label="Chat with Axis"
      onClick={onClick}
      style={{
        position: 'absolute', right, bottom, zIndex: 45,
        height: 56, borderRadius: 999, padding: label ? '0 18px 0 13px' : 0,
        width: label ? 'auto' : 56,
        background: M.axis, color: '#fff', border: `2px solid ${M.surface}`,
        boxShadow: emphasis
          ? '0 0 0 5px rgba(30,58,237,0.16), 0 10px 26px rgba(30,58,237,0.30), 0 2px 6px rgba(14,18,32,0.12)'
          : '0 8px 24px rgba(30,58,237,0.32), 0 2px 6px rgba(14,18,32,0.12)',
        cursor: 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
        ...style,
      }}
    >
      <span style={{ display: 'flex' }}><N2ChatGlyph size={24} strokeWidth={2.2} /></span>
      {label && <span style={{ font: `500 14px/1 ${M.sans}`, color: '#fff' }}>{label}</span>}
    </button>
  );
}

// ── DSYouAvatar — top-right ink rounded avatar (single "You" entry) ──
function DSYouAvatar({ initials = 'EH', active = false, dimmed = false, size = 38, onClick, style }) {
  return (
    <button
      type="button"
      aria-label="You"
      onClick={onClick}
      style={{
        width: size, height: size, borderRadius: 11, padding: 0, flexShrink: 0,
        background: M.ink, color: '#fff', cursor: 'pointer',
        border: `2px solid ${M.surface}`,
        boxShadow: active
          ? `0 0 0 2px ${M.axis}, 0 1px 2px rgba(14,18,32,0.12)`
          : `0 0 0 1.5px ${M.rule}, 0 1px 2px rgba(14,18,32,0.12)`,
        font: `500 ${Math.round(size * 0.37)}px/1 ${M.sans}`, letterSpacing: '-0.01em',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        opacity: dimmed ? 0.5 : 1, ...style,
      }}
    >{initials}</button>
  );
}

// ── DSSlotExplainer — non-modal popover anchored above slot `index` ──
// variant 'locked' (lock icon) explains a gated slot; 'add' (plus icon)
// explains an open prebuilt slot. Arrow points down at the slot. Tap-away
// dismissal is the host's job.
function DSSlotExplainer({ index = 2, variant = 'locked', title, body, icon }) {
  const Ico = icon || (variant === 'add' ? N2PlusGlyph : DSNav2Lock);
  const defaults = variant === 'add'
    ? { title: 'Add a system', body: 'Prebuilt systems are gifted weekly through your Today recap — this slot fills the moment you activate one.' }
    : { title: 'Locked for now', body: 'This opens once you finish onboarding or build your first system. Until then, chat is the way forward.' };
  return (
    <div style={{
      position: 'absolute', bottom: 'calc(100% + 6px)',
      left: `${DSNav2_slotCenterPct(index)}%`, transform: 'translateX(-50%)',
      zIndex: 60, width: 224, maxWidth: 224,
    }}>
      <div style={{
        background: M.surface, border: `1px solid ${M.rule}`, borderRadius: 14,
        padding: '13px 14px', boxShadow: '0 14px 34px rgba(14,18,32,0.18)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{
            width: 24, height: 24, borderRadius: 999, flexShrink: 0,
            background: M.surfaceAlt, border: `1px solid ${M.rule}`, color: M.inkMuted,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <Ico size={13} strokeWidth={2.1} />
          </span>
          <div style={{ font: `500 14px/1.2 ${M.sans}`, color: M.ink, letterSpacing: '-0.01em' }}>
            {title || defaults.title}
          </div>
        </div>
        <div style={{ font: `400 12.5px/1.5 ${M.sans}`, color: M.inkSoft, marginTop: 9 }}>
          {body || defaults.body}
        </div>
      </div>
      {/* down arrow */}
      <div style={{
        position: 'absolute', top: '100%', left: '50%',
        transform: 'translateX(-50%) translateY(-1px) rotate(45deg)',
        width: 11, height: 11, background: M.surface,
        borderRight: `1px solid ${M.rule}`, borderBottom: `1px solid ${M.rule}`,
      }} />
    </div>
  );
}

Object.assign(window, {
  DSTabBarNav2, DSChatFab, DSYouAvatar, DSSlotExplainer,
  DSNav2Lock,
  DSNav2_glyphs, DSNav2_placeholders, DSNav2_defaultSlots, DSNav2_slotCenterPct,
});
