/* =============================================================================
   portal/ui.jsx, shared primitives + theme helpers for the portal.
   Exposes window.UI = { Button, Eyebrow, Display, Card, Tag, Rule, Toast, ... }
   ============================================================================= */

const C = {
  carbon: 'var(--kh-carbon)',
  carbon90: 'var(--kh-carbon-90)',
  carbon70: 'var(--kh-carbon-70)',
  carbon50: 'var(--kh-carbon-50)',
  carbon30: 'var(--kh-carbon-30)',
  carbon15: 'var(--kh-carbon-15)',
  white: '#fff',
  porcelain: 'var(--kh-porcelain)',
  clay: 'var(--kh-clay)',
  claySoft: 'var(--kh-clay-soft)',
  clayDeep: 'var(--kh-clay-deep)',
  mahogany: 'var(--kh-mahogany)',
  hair: 'var(--border-hairline)',
  rule: 'var(--border-rule)',
  sans: 'var(--font-sans)',
  serif: 'var(--font-serif)',
  display: 'var(--font-display)',
};

// ---- Button ----------------------------------------------------------------
function Button({ children, onClick, variant = 'primary', size = 'md', icon, iconRight, full, type, disabled, style }) {
  const [hover, setHover] = React.useState(false);
  const [press, setPress] = React.useState(false);
  const pad = size === 'sm' ? '9px 16px' : size === 'lg' ? '16px 30px' : '13px 24px';
  const fs = size === 'sm' ? 10.5 : 11.5;

  const variants = {
    primary: {
      background: disabled ? C.carbon30 : (hover ? C.carbon90 : C.carbon),
      color: '#fff', border: 'none',
    },
    light: {
      background: hover ? '#f0f0f0' : '#fff',
      color: C.carbon, border: 'none',
    },
    outline: {
      background: hover ? C.carbon : 'transparent',
      color: hover ? '#fff' : C.carbon,
      border: `1px solid ${C.carbon}`,
    },
    ghost: {
      background: hover ? 'rgba(29,29,29,0.05)' : 'transparent',
      color: C.carbon, border: '1px solid transparent',
    },
    onDark: {
      background: hover ? 'rgba(255,255,255,0.12)' : 'transparent',
      color: '#fff', border: '1px solid rgba(255,255,255,0.3)',
    },
  };

  return (
    <button
      type={type || 'button'}
      onClick={disabled ? undefined : onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => { setHover(false); setPress(false); }}
      onMouseDown={() => setPress(true)}
      onMouseUp={() => setPress(false)}
      disabled={disabled}
      style={{
        fontFamily: C.sans, fontWeight: 500, fontSize: fs,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        padding: pad, borderRadius: 999, cursor: disabled ? 'not-allowed' : 'pointer',
        display: full ? 'flex' : 'inline-flex', width: full ? '100%' : undefined,
        alignItems: 'center', justifyContent: 'center', gap: 9,
        transform: press ? 'translateY(1px)' : 'none',
        transition: 'background 160ms var(--ease-out), color 160ms var(--ease-out), transform 160ms var(--ease-out)',
        ...variants[variant], ...style,
      }}>
      {icon && <Icon name={icon} size={size === 'sm' ? 14 : 16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size === 'sm' ? 14 : 16} />}
    </button>
  );
}

// ---- Eyebrow / Display -----------------------------------------------------
function Eyebrow({ children, onDark, style }) {
  return <div className="kh-eyebrow" style={{ color: onDark ? 'rgba(255,255,255,0.66)' : 'var(--fg-2)', ...style }}>{children}</div>;
}
function Display({ children, size = 44, onDark, style }) {
  return <h1 className="kh-display" style={{ fontSize: size, color: onDark ? '#fff' : C.carbon, ...style }}>{children}</h1>;
}

// ---- Card ------------------------------------------------------------------
function Card({ children, pad = 28, hover, onClick, style }) {
  const [h, setH] = React.useState(false);
  return (
    <div
      onClick={onClick}
      onMouseEnter={() => setH(true)}
      onMouseLeave={() => setH(false)}
      style={{
        background: '#fff',
        border: `1px solid ${hover && h ? C.carbon30 : C.hair}`,
        padding: pad,
        cursor: onClick ? 'pointer' : 'default',
        transition: 'border-color 200ms var(--ease-out), transform 200ms var(--ease-out)',
        transform: hover && h ? 'translateY(-2px)' : 'none',
        ...style,
      }}>
      {children}
    </div>
  );
}

// ---- Tag / pill ------------------------------------------------------------
function Tag({ children, tone = 'neutral', style }) {
  const tones = {
    neutral: { background: C.porcelain, color: C.carbon70, border: `1px solid ${C.hair}` },
    clay: { background: C.claySoft, color: C.carbon, border: `1px solid ${C.clayDeep}` },
    dark: { background: C.carbon, color: '#fff', border: 'none' },
    done: { background: C.carbon, color: '#fff', border: 'none' },
    active: { background: C.claySoft, color: C.carbon, border: `1px solid ${C.clayDeep}` },
    todo: { background: 'transparent', color: C.carbon50, border: `1px solid ${C.rule}` },
  };
  return (
    <span style={{
      fontFamily: C.sans, fontWeight: 500, fontSize: 9.5, letterSpacing: '0.16em',
      textTransform: 'uppercase', padding: '5px 10px', borderRadius: 999,
      display: 'inline-flex', alignItems: 'center', gap: 6, whiteSpace: 'nowrap',
      ...tones[tone], ...style,
    }}>{children}</span>
  );
}

// ---- Rule ------------------------------------------------------------------
function Rule({ onDark, style }) {
  return <div style={{ height: 1, background: onDark ? 'rgba(255,255,255,0.16)' : C.hair, ...style }} />;
}

// ---- Section heading (UI sans) ---------------------------------------------
function SectionLabel({ children, style }) {
  return (
    <div style={{
      fontFamily: C.sans, fontWeight: 500, fontSize: 12, letterSpacing: '0.18em',
      textTransform: 'uppercase', color: C.carbon, ...style,
    }}>{children}</div>
  );
}

// ---- Lede (serif intro paragraph) ------------------------------------------
function Lede({ children, style }) {
  return <p style={{ fontFamily: C.serif, fontSize: 19, lineHeight: 1.55, color: C.carbon, margin: 0, ...style }}>{children}</p>;
}

// ---- Body paragraph --------------------------------------------------------
function Body({ children, dim, style }) {
  return <p style={{ fontFamily: C.serif, fontSize: 16, lineHeight: 1.6, color: dim ? C.carbon70 : C.carbon, margin: 0, ...style }}>{children}</p>;
}

// ---- Toast (transient) -----------------------------------------------------
function Toast({ message, onDone }) {
  React.useEffect(() => {
    if (!message) return;
    const t = setTimeout(onDone, 2600);
    return () => clearTimeout(t);
  }, [message]);
  if (!message) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 28, left: '50%', transform: 'translateX(-50%)',
      background: C.carbon, color: '#fff', padding: '14px 22px',
      fontFamily: C.sans, fontSize: 12, letterSpacing: '0.1em',
      display: 'flex', alignItems: 'center', gap: 10, zIndex: 200,
      animation: 'kh-fade-in 200ms var(--ease-out)', boxShadow: 'var(--shadow-3)',
    }}>
      <Icon name="check" size={16} color="#fff" />{message}
    </div>
  );
}

// ---- Bulleted list with brand marker ---------------------------------------
function BulletList({ items, style }) {
  return (
    <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 14, ...style }}>
      {items.map((it, i) => (
        <li key={i} style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
          <span style={{ marginTop: 11, width: 6, height: 6, background: C.clayDeep, flexShrink: 0 }} />
          <span style={{ fontFamily: C.serif, fontSize: 16, lineHeight: 1.55, color: C.carbon }}>{it}</span>
        </li>
      ))}
    </ul>
  );
}

// ---- SchoolMark: official logo with graceful fallback to initials ----------
function SchoolMark({ slug, short, size = 34, variant = 'solid', logo: logoOverride }) {
  const entry = (window.REGISTRY && REGISTRY.schoolModules || []).find(s => s.id === 's/' + slug);
  // An explicit logo prop (e.g. for a school not yet in REGISTRY.schoolModules)
  // takes precedence over the registry lookup.
  const logo = logoOverride || (entry && entry.logo);
  const [errored, setErrored] = React.useState(false);
  const showLogo = logo && !errored;

  if (showLogo) {
    return (
      <div style={{ width: size, height: size, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, padding: Math.round(size * 0.16), border: `1px solid ${C.hair}` }}>
        <img src={logo} alt={short} onError={() => setErrored(true)}
          style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain', display: 'block' }} />
      </div>
    );
  }
  const solid = variant === 'solid';
  return (
    <div style={{
      width: size, height: size, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: solid ? C.carbon : 'rgba(255,255,255,0.08)',
      border: solid ? 'none' : '1px solid rgba(255,255,255,0.2)',
      color: '#fff', fontFamily: C.display, fontSize: size * 0.34, letterSpacing: '0.04em',
    }}>{short}</div>
  );
}

// ---- School application status (shared 8-state vocabulary) -----------------
const SCHOOL_STATUS = {
  'not-started': { label: 'Not started',             menu: 'Not started',                     c: 'var(--sch-notstarted)' },
  'in-progress': { label: 'Application in progress',  menu: 'Application in progress',          c: 'var(--sch-inprogress)' },
  'completed':   { label: 'Completed application',    menu: 'Completed application',            c: 'var(--sch-completed)' },
  'interview':   { label: 'Interview invite',         menu: 'Interview invite',                c: 'var(--sch-interview)' },
  'waitlisted':  { label: 'Waitlisted',               menu: 'Waitlisted',                      c: 'var(--sch-waitlisted)', solid: true },
  'admitted':    { label: 'Admitted',                 menu: 'Admitted',                        c: 'var(--sch-admitted)', solid: true },
  'denied-pre':  { label: 'Not admitted',             menu: 'Denied — without interview',      c: 'var(--sch-denied-pre)' },
  'denied-post': { label: 'Not admitted',             menu: 'Denied — after interview',        c: 'var(--sch-denied-post)' },
};
const SCHOOL_STATUS_ORDER = ['not-started', 'in-progress', 'completed', 'interview', 'waitlisted', 'admitted', 'denied-pre', 'denied-post'];

function schoolTagStyle(status) {
  const s = SCHOOL_STATUS[status] || SCHOOL_STATUS['not-started'];
  return s.solid
    ? { color: '#fff', background: s.c, border: `1px solid ${s.c}` }
    : { color: `color-mix(in oklab, ${s.c}, #1D1D1D 26%)`, background: `color-mix(in oklab, ${s.c} 13%, #fff)`, border: `1px solid color-mix(in oklab, ${s.c} 34%, #fff)` };
}
function SchoolStatusTag({ status, size = 'md', style }) {
  const s = SCHOOL_STATUS[status] || SCHOOL_STATUS['not-started'];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: C.sans, fontWeight: 600,
      fontSize: size === 'sm' ? 9 : 9.5, letterSpacing: '0.14em', textTransform: 'uppercase', whiteSpace: 'nowrap',
      padding: size === 'sm' ? '4px 9px' : '5px 11px', borderRadius: 999, ...schoolTagStyle(status), ...style,
    }}>
      {!s.solid && <span style={{ width: 5, height: 5, borderRadius: 999, background: s.c }} />}
      {s.label}
    </span>
  );
}

// Editable status (client picks where the school stands). onChange(key).
function SchoolStatusEditor({ status, onChange, size = 'md', align = 'left' }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h); return () => document.removeEventListener('mousedown', h);
  }, []);
  return (
    <div ref={ref} style={{ position: 'relative', display: 'inline-block' }} onClick={e => e.stopPropagation()}>
      <button onClick={() => setOpen(o => !o)} title="Update this school's status"
        style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
        <SchoolStatusTag status={status} size={size} />
        <Icon name="chevronRight" size={12} color="var(--kh-carbon-50)" style={{ transform: 'rotate(90deg)' }} />
      </button>
      {open && (
        <div style={{ position: 'absolute', top: '130%', [align]: 0, zIndex: 60, background: '#fff', border: `1px solid ${C.rule}`, minWidth: 230, boxShadow: 'var(--shadow-3)', padding: 5 }}>
          <div style={{ fontFamily: C.sans, fontSize: 9, letterSpacing: '0.18em', textTransform: 'uppercase', color: C.carbon50, padding: '6px 9px 8px' }}>Update status</div>
          {SCHOOL_STATUS_ORDER.map(k => {
            const s = SCHOOL_STATUS[k];
            const on = k === status;
            return (
              <button key={k} onClick={() => { onChange(k); setOpen(false); }}
                style={{ display: 'flex', alignItems: 'center', gap: 9, width: '100%', textAlign: 'left', background: on ? C.porcelain : 'none', border: 'none', cursor: 'pointer', padding: '8px 9px', fontFamily: C.sans, fontSize: 12.5, color: C.carbon }}
                onMouseEnter={e => e.currentTarget.style.background = C.porcelain} onMouseLeave={e => e.currentTarget.style.background = on ? C.porcelain : 'none'}>
                <span style={{ width: 8, height: 8, borderRadius: 999, background: s.c, flexShrink: 0 }} />
                {s.menu}
                {on && <Icon name="check" size={13} color="var(--kh-carbon)" style={{ marginLeft: 'auto' }} />}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ---- Coaching module status (3-state) -------------------------------------
const MODULE_STATUS = {
  'not-started': { label: 'Not started', c: 'var(--sch-notstarted)' },
  'in-progress': { label: 'In progress', c: 'var(--sch-inprogress)' },
  'complete':    { label: 'Complete',    c: 'var(--sch-completed)' },
};
const MODULE_STATUS_ORDER = ['not-started', 'in-progress', 'complete'];
function moduleTagStyle(status) {
  const s = MODULE_STATUS[status] || MODULE_STATUS['not-started'];
  return { color: `color-mix(in oklab, ${s.c}, #1D1D1D 26%)`, background: `color-mix(in oklab, ${s.c} 13%, #fff)`, border: `1px solid color-mix(in oklab, ${s.c} 34%, #fff)` };
}
function ModuleStatusTag({ status, style }) {
  const s = MODULE_STATUS[status] || MODULE_STATUS['not-started'];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: C.sans, fontWeight: 600, fontSize: 9.5, letterSpacing: '0.14em', textTransform: 'uppercase', whiteSpace: 'nowrap', padding: '5px 11px', borderRadius: 999, ...moduleTagStyle(status), ...style }}>
      <span style={{ width: 5, height: 5, borderRadius: 999, background: s.c }} />
      {s.label}
    </span>
  );
}
// Editable module status. onChange(key). Stops click propagation so it works
// inside a clickable module card.
function ModuleStatusEditor({ status, onChange, align = 'right' }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h); return () => document.removeEventListener('mousedown', h);
  }, []);
  const cur = status || 'not-started';
  return (
    <div ref={ref} style={{ position: 'relative', display: 'inline-block' }} onClick={e => e.stopPropagation()}>
      <button onClick={() => setOpen(o => !o)} title="Update this module's status"
        style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
        <ModuleStatusTag status={cur} />
        <Icon name="chevronRight" size={12} color="var(--kh-carbon-50)" style={{ transform: 'rotate(90deg)' }} />
      </button>
      {open && (
        <div style={{ position: 'absolute', top: '130%', [align]: 0, zIndex: 60, background: '#fff', border: `1px solid ${C.rule}`, minWidth: 180, boxShadow: 'var(--shadow-3)', padding: 5 }}>
          <div style={{ fontFamily: C.sans, fontSize: 9, letterSpacing: '0.18em', textTransform: 'uppercase', color: C.carbon50, padding: '6px 9px 8px' }}>Update status</div>
          {MODULE_STATUS_ORDER.map(k => {
            const s = MODULE_STATUS[k]; const on = k === cur;
            return (
              <button key={k} onClick={() => { onChange(k); setOpen(false); }}
                style={{ display: 'flex', alignItems: 'center', gap: 9, width: '100%', textAlign: 'left', background: on ? C.porcelain : 'none', border: 'none', cursor: 'pointer', padding: '8px 9px', fontFamily: C.sans, fontSize: 12.5, color: C.carbon }}
                onMouseEnter={e => e.currentTarget.style.background = C.porcelain} onMouseLeave={e => e.currentTarget.style.background = on ? C.porcelain : 'none'}>
                <span style={{ width: 8, height: 8, borderRadius: 999, background: s.c, flexShrink: 0 }} />
                {s.label}
                {on && <Icon name="check" size={13} color="var(--kh-carbon)" style={{ marginLeft: 'auto' }} />}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

window.UI = { C, Button, Eyebrow, Display, Card, Tag, Rule, SectionLabel, Lede, Body, Toast, BulletList, SchoolMark, SchoolStatusTag, SchoolStatusEditor, SCHOOL_STATUS, SCHOOL_STATUS_ORDER, ModuleStatusTag, ModuleStatusEditor, MODULE_STATUS, MODULE_STATUS_ORDER };
