// Shared components: header, badges, icons, tabs, modal.
// Exposes to window so other Babel scripts can pick them up.

const { useState, useEffect, useMemo, useRef } = React;

// ---------- Icons (small inline SVG set) ----------
function Icon({ name, size = 18, color = 'currentColor', stroke = 1.5 }) {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'arrow-right': return <svg {...p}><path d="M5 12h14M13 5l7 7-7 7"/></svg>;
    case 'arrow-up-right': return <svg {...p}><path d="M7 17 17 7M8 7h9v9"/></svg>;
    case 'check': return <svg {...p}><path d="M5 12l5 5L20 7"/></svg>;
    case 'plus': return <svg {...p}><path d="M12 5v14M5 12h14"/></svg>;
    case 'x': return <svg {...p}><path d="M6 6l12 12M6 18 18 6"/></svg>;
    case 'trash': return <svg {...p}><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/></svg>;
    case 'send': return <svg {...p}><path d="M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>;
    case 'download': return <svg {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>;
    case 'loader': return <svg {...p}><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>;
    case 'edit': return <svg {...p}><path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/></svg>;
    case 'shield': return <svg {...p}><path d="M12 2 4 6v6c0 5 3.5 9 8 10 4.5-1 8-5 8-10V6l-8-4z"/></svg>;
    case 'users': return <svg {...p}><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8m14 10v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg>;
    case 'globe': return <svg {...p}><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/></svg>;
    case 'plug': return <svg {...p}><path d="M9 2v6m6-6v6M5 8h14v3a7 7 0 0 1-14 0V8zm7 14v-4"/></svg>;
    case 'pillar': return <svg {...p}><path d="M3 21h18M5 21V8m4 13V8m6 13V8m4 13V8M3 8l9-5 9 5M3 8h18"/></svg>;
    case 'heart': return <svg {...p}><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg>;
    case 'repost': return <svg {...p}><path d="M17 1l4 4-4 4M3 11V9a4 4 0 0 1 4-4h14M7 23l-4-4 4-4M21 13v2a4 4 0 0 1-4 4H3"/></svg>;
    case 'comment': return <svg {...p}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>;
    case 'eye': return <svg {...p}><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg>;
    case 'chevron-down': return <svg {...p}><path d="m6 9 6 6 6-6"/></svg>;
    case 'sun': return <svg {...p}><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>;
    default: return null;
  }
}

// ---------- Bloom mark — plumeria (5-petal pinwheel) in deep purple ----------
function BloomMark({ size = 28, ink = '#240063', showWord = true }) {
  const r = size / 2;
  // five overlapping teardrop petals rotating around center
  const petal = (rot, key) => (
    <path
      key={key}
      d="M0 0 C -2.6 -2.6 -3.4 -6.6 -1.6 -9.6 C 0.2 -12.4 3.2 -12 4.6 -9.4 C 6 -6.6 4 -3.2 1.2 -1.2 C 0.6 -0.7 0.2 -0.3 0 0 Z"
      transform={`rotate(${rot}) translate(0 0)`}
      fill="#A88FE0"
      stroke="#3C00A6"
      strokeWidth="1.6"
      strokeLinejoin="round"
    />
  );
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
      <svg width={size} height={size} viewBox={`-${r} -${r} ${size} ${size}`} fill="none" aria-hidden="true">
        <defs>
          <radialGradient id="bloomBg" cx="0.4" cy="0.35" r="0.7">
            <stop offset="0%" stopColor="#FFFFFF"/>
            <stop offset="100%" stopColor="#E6DAF6"/>
          </radialGradient>
        </defs>
        <circle cx="0" cy="0" r={r - 0.6} fill="url(#bloomBg)" stroke="none"/>
        <g transform={`scale(${size / 30})`}>
          {[0, 72, 144, 216, 288].map((rot) => petal(rot, rot))}
          <circle cx="0" cy="0" r="1.4" fill="#3C00A6"/>
        </g>
      </svg>
      {showWord && (
        <span style={{ fontFamily: 'var(--sans)', fontSize: size * 0.7, fontWeight: 700, color: ink, letterSpacing: '-0.02em' }}>
          bloom<span style={{ color: '#3C00A6' }}>.</span>
        </span>
      )}
    </span>
  );
}

// ---------- Status badge ----------
// Resolution order:
//   1. role superadmin / admin → show that
//   2. lifecycle pending / waiting / rejected → show that
//   3. approved → show the tier (apex / ranger / scout)
//   4. fallback → show whatever string came in
function StatusBadge({ status, tier, role }) {
  let key = status;
  if (role === 'superadmin') key = 'superadmin';
  else if (role === 'admin') key = 'admin';
  else if (status === 'approved' && tier) key = tier;

  const map = {
    superadmin: { cls: 'badge apex',    label: 'Superadmin',  icon: null      },
    admin:      { cls: 'badge apex',    label: 'Admin',       icon: null      },
    pending:    { cls: 'badge waiting', label: 'Pending',     icon: 'shield'  },
    waiting:    { cls: 'badge waiting', label: 'Waiting Room',icon: 'shield'  },
    rejected:   { cls: 'badge waiting', label: 'Rejected',    icon: 'shield'  },
    approved:   { cls: 'badge scout',   label: 'Approved',    icon: 'shield'  },
    scout:      { cls: 'badge scout',   label: 'Scout',       icon: 'shield'  },
    ranger:     { cls: 'badge ranger',  label: 'Ranger',      icon: 'shield'  },
    apex:       { cls: 'badge apex',    label: 'Apex',        icon: null      },
  };
  const m = map[key] || { cls: 'badge waiting', label: key || 'Unknown', icon: 'shield' };
  return (
    <span className={m.cls}>
      {m.icon && <Icon name={m.icon} size={12}/>}
      <span>{m.label}</span>
    </span>
  );
}

// ---------- Application status pill ----------
function AppStatusPill({ status }) {
  const map = {
    pending:  { cls: 'pill warn',   label: 'Pending'      },
    approved: { cls: 'pill ok',     label: 'Approved'     },
    rejected: { cls: 'pill bad',    label: 'Rejected'     },
    waiting:  { cls: 'pill purple', label: 'Waiting Room' }
  };
  const m = map[status] || map.pending;
  return <span className={m.cls}>{m.label}</span>;
}

// ---------- App header ----------
function AppHeader({ user, route, onNav, onLogout }) {
  const isLoggedIn = !!user;
  return (
    <header className="app-header">
      <div className="inner">
        <a className="brand" href="#/program" onClick={(e) => { e.preventDefault(); onNav('program'); }}>
          <BloomMark size={22}/>
        </a>
        <nav style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          {isLoggedIn ? (
            <>
              {(user.role === 'admin' || user.role === 'superadmin') && (
                <a className={`nav-link ${route === 'admin' ? 'active' : ''}`} href="#/admin" onClick={(e) => { e.preventDefault(); onNav('admin'); }}>Admin</a>
              )}
              {/* Application link for any non-approved, non-staff user (waiting/pending/rejected). */}
              {!(user.status === 'approved' || user.role === 'admin' || user.role === 'superadmin') && (
                <a className={`nav-link ${route === 'application' ? 'active' : ''}`} href="#/application" onClick={(e) => { e.preventDefault(); onNav('application'); }}>Application</a>
              )}
              {/* Dashboard for approved, pending, and staff. */}
              {(user.status === 'approved' || user.status === 'pending' || user.role === 'admin' || user.role === 'superadmin') && (
                <a className={`nav-link ${route === 'dashboard' ? 'active' : ''}`} href="#/dashboard" onClick={(e) => { e.preventDefault(); onNav('dashboard'); }}>Dashboard</a>
              )}
              <a className={`nav-link ${route === 'program' ? 'active' : ''}`} href="#/program" onClick={(e) => { e.preventDefault(); onNav('program'); }}>The Field</a>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10, marginLeft: 12, paddingLeft: 16, borderLeft: '1px solid var(--rule)' }}>
                <img src={user.avatar} alt="" style={{ width: 28, height: 28, borderRadius: '50%' }}/>
                <span style={{ fontSize: 13, color: 'var(--ink-700)' }}>{user.handle}</span>
                <button className="btn-ghost" style={{ fontSize: 12, padding: '4px 8px' }} onClick={onLogout}>Sign out</button>
              </span>
            </>
          ) : (
            <a className="btn btn-secondary btn-sm" href="#/login" onClick={(e) => { e.preventDefault(); onNav('login'); }}>Sign in</a>
          )}
        </nav>
      </div>
    </header>
  );
}

// ---------- Tabs ----------
function Tabs({ items, value, onChange }) {
  return (
    <div className="tabs">
      {items.map(it => (
        <button
          key={it.value}
          className={`tab ${value === it.value ? 'active' : ''}`}
          onClick={() => onChange(it.value)}
        >
          {it.label}
          {it.count != null && <span className="count">{it.count}</span>}
        </button>
      ))}
    </div>
  );
}

// ---------- Modal ----------
function Modal({ open, onClose, children }) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

// ---------- UIRoot ----------
// Global in-app confirm + toast host. Mounted once at the top of <App>.
// Exposes window.ui.confirm({ title, message, danger?, confirmLabel?, cancelLabel? })
// → Promise<boolean>, and window.ui.toast(message, { kind: 'success'|'error'|'info' }).
function UIRoot() {
  const [confirmState, setConfirmState] = useState(null);
  const [toasts, setToasts] = useState([]);

  useEffect(() => {
    window.ui = window.ui || {};
    window.ui.confirm = (opts = {}) => new Promise((resolve) => {
      setConfirmState({ ...opts, resolve });
    });
    window.ui.toast = (message, opts = {}) => {
      const id = 'tst_' + Math.random().toString(36).slice(2, 8);
      const kind = opts.kind || 'info';
      const duration = opts.duration || (kind === 'error' ? 5500 : 3800);
      setToasts(prev => [...prev, { id, message, kind }]);
      setTimeout(() => setToasts(prev => prev.filter(t => t.id !== id)), duration);
    };
  }, []);

  const resolveConfirm = (ok) => {
    if (confirmState) confirmState.resolve(Boolean(ok));
    setConfirmState(null);
  };

  return (
    <React.Fragment>
      {confirmState && (
        <Modal open onClose={() => resolveConfirm(false)}>
          <div className="confirm-modal">
            <div className={`confirm-modal-mark ${confirmState.danger ? 'danger' : ''}`}>
              <Icon name={confirmState.danger ? 'trash' : 'shield'} size={22}/>
            </div>
            <h3 className="serif-h3">{confirmState.title || 'Are you sure?'}</h3>
            {confirmState.message && <p>{confirmState.message}</p>}
            <div className="confirm-modal-actions">
              <button className="btn btn-ghost" onClick={() => resolveConfirm(false)}>
                {confirmState.cancelLabel || 'Cancel'}
              </button>
              <button
                className={`btn ${confirmState.danger ? 'btn-danger' : 'btn-primary'}`}
                onClick={() => resolveConfirm(true)}
                autoFocus>
                {confirmState.confirmLabel || (confirmState.danger ? 'Delete' : 'Confirm')}
              </button>
            </div>
          </div>
        </Modal>
      )}
      <div className="toast-stack" role="status" aria-live="polite">
        {toasts.map(t => (
          <div key={t.id} className={`toast toast-${t.kind}`}>
            <span className="toast-dot"></span>
            <span className="toast-msg">{t.message}</span>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}
window.UIRoot = UIRoot;

// ---------- Field helpers ----------
function Field({ label, help, children, span2, required, className }) {
  const classes = ['field'];
  if (span2) classes.push('col-span-2');
  if (className) classes.push(className);
  return (
    <div className={classes.join(' ')}>
      <label className="field-label">{label}{required ? <span className="req-mark"> *</span> : null}</label>
      {children}
      {help && <span className="field-help">{help}</span>}
    </div>
  );
}

function RadioGroup({ name, value, onChange, options, columns = 1 }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: '0px 16px' }}>
      {options.map(opt => {
        const v = typeof opt === 'string' ? opt : opt.value;
        const l = typeof opt === 'string' ? opt : opt.label;
        return (
          <label key={v} className="radio">
            <input type="radio" name={name} checked={value === v} onChange={() => onChange(v)} />
            <span className="pip"></span>
            <span className="lbl">{l}</span>
          </label>
        );
      })}
    </div>
  );
}

function CheckChips({ value, onChange, options }) {
  const set = new Set(value || []);
  const toggle = (v) => {
    const n = new Set(set);
    if (n.has(v)) n.delete(v); else n.add(v);
    onChange([...n]);
  };
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
      {options.map(o => (
        <label key={o} className={`chip ${set.has(o) ? 'on' : ''}`}>
          <input type="checkbox" checked={set.has(o)} onChange={() => toggle(o)}/>
          {o}
        </label>
      ))}
    </div>
  );
}

function Likert({ value, onChange, max = 5, capLow = 'Low', capHigh = 'High' }) {
  return (
    <div className="likert">
      <span className="likert-cap">{capLow}</span>
      {Array.from({ length: max }, (_, i) => i + 1).map(n => (
        <button key={n} type="button" className={`likert-dot ${value === n ? 'on' : ''}`} onClick={() => onChange(n)}>{n}</button>
      ))}
      <span className="likert-cap">{capHigh}</span>
    </div>
  );
}

// ---------- Hash router ----------
// Only `#/route` style hashes change the route. Plain `#anchor` hashes
// (in-page section links) are left for the browser to scroll naturally.
function useRoute() {
  const parse = () => {
    const h = window.location.hash || '';
    if (!h.startsWith('#/')) return null; // not a route hash
    const path = h.replace(/^#\//, '').split('?')[0] || 'program';
    const seg = path.split('/');
    return { name: seg[0] || 'program', sub: seg[1] || null };
  };
  const [route, setRoute] = useState(parse() || { name: 'program', sub: null });
  useEffect(() => {
    const onHash = () => {
      const r = parse();
      if (r) setRoute(r);
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const nav = (name, sub) => {
    const target = sub ? `#/${name}/${sub}` : `#/${name}`;
    if (window.location.hash !== target) window.location.hash = target;
  };
  return [route, nav];
}

Object.assign(window, {
  Icon, BloomMark, StatusBadge, AppStatusPill, AppHeader, Tabs, Modal,
  Field, RadioGroup, CheckChips, Likert, useRoute
});
