// Shared primitives for the portal UI.
// Theme-aware: every component accepts an implicit theme via the BrandTheme context.
// Tokens live in ../colors_and_type.css for typography; colours come from BrandTheme.

const { useState, useContext, createContext } = React;

// ------- Theme -------
// Two themes, same geometry. Unordinary teal is default; Elysium EPL is navy + gold.
const UNORDINARY_THEME = {
  key: 'unordinary',
  name: 'The Unordinary',
  sublabel: 'by The Unordinary',
  productName: 'The write stuff',
  primary: '#2AB59E',     // teal (print-safe)
  primaryScreen: '#3CDBC0',
  primaryLight: '#F5F9F8',
  primaryMid: '#D4F5EE',
  primaryDark: '#0f6b5b',
  secondary: '#E8198B',   // pink CTA
  secondaryLight: '#FFF0F7',
  secondaryDark: '#9a1060',
  tertiary: '#FFCC00',
  tertiaryDark: '#b08a00',
  ink: '#1A1A1A',
  body: '#555555',
  muted: '#888888',
  rule: '#E8E8E8',
  surface: '#FFFFFF',
  soft: '#F5F9F8',
  gradient: 'linear-gradient(90deg, #FF00C7 0%, #E8198B 18%, #B455A8 38%, #7F91B0 55%, #54C3B2 72%, #3CDBC0 85%, #FFCC00 100%)',
  logoSrc: '../assets/logos/unordinary-pinwheel.png',
};

// Elysium EPL — colour-matched to the supplied logo.
// Deep navy primary, bright sky blue accent (the "EPL" type), grey mid.
const ELYSIUM_THEME = {
  key: 'elysium',
  name: 'Elysium EPL',
  sublabel: 'Comprehensive, enduring value',
  productName: 'The write stuff',
  primary: '#14345D',       // Elysium navy
  primaryScreen: '#1C4680',
  primaryLight: '#F2F6FB',
  primaryMid: '#D6E4F2',
  primaryDark: '#0C2140',
  secondary: '#2BB7EA',     // Elysium sky blue (EPL type colour)
  secondaryLight: '#E3F4FC',
  secondaryDark: '#0E7AB0',
  tertiary: '#8A97A8',      // neutral steel grey (third Venn circle)
  tertiaryDark: '#5A6778',
  ink: '#0E1C30',
  body: '#445065',
  muted: '#8592A6',
  rule: '#DEE4EC',
  surface: '#FFFFFF',
  soft: '#F2F6FB',
  gradient: 'linear-gradient(90deg, #14345D 0%, #1C4680 30%, #2BB7EA 70%, #8FD4F0 100%)',
  logoSrc: 'assets/elysium-logo.png',
};

const BrandTheme = createContext(UNORDINARY_THEME);
const useBrand = () => useContext(BrandTheme);

// ------- Primitives -------
function Button({ kind = 'primary', children, onClick, style }) {
  const t = useBrand();
  const base = {
    display: 'inline-flex', alignItems: 'center', gap: 8,
    font: "600 14px/1 'Space Grotesk', Arial",
    padding: '11px 18px', borderRadius: 8, cursor: 'pointer',
    border: '1px solid transparent', transition: 'background .18s, color .18s, transform .12s',
    whiteSpace: 'nowrap',
  };
  const kinds = {
    primary: { background: t.primary, color: '#fff' },
    cta: { background: t.secondary, color: '#fff' },
    secondary: { background: '#fff', color: t.ink, borderColor: t.ink },
    ghost: { background: 'transparent', color: t.primary, padding: '11px 4px' },
  };
  return <button style={{ ...base, ...kinds[kind], ...style }} onClick={onClick}>{children}</button>;
}

function Badge({ tone = 'primary', children }) {
  const t = useBrand();
  const map = {
    primary: { bg: t.primaryMid, fg: t.primaryDark },
    secondary: { bg: t.secondaryLight, fg: t.secondaryDark },
    tertiary: { bg: '#FFF4B8', fg: '#7a5a00' },
    ink: { bg: t.ink, fg: '#fff' },
    outline: { bg: '#fff', fg: t.ink, border: `1px solid ${t.rule}` },
    // legacy tone aliases used by existing pack data
    teal: { bg: t.primaryMid, fg: t.primaryDark },
    pink: { bg: t.secondaryLight, fg: t.secondaryDark },
    yellow: { bg: '#FFF4B8', fg: '#7a5a00' },
  };
  const s = map[tone] || map.primary;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      font: "600 12px/1 'Space Grotesk', Arial",
      padding: '5px 10px', borderRadius: 999,
      background: s.bg, color: s.fg, border: s.border || 'none',
    }}>
      {children}
    </span>
  );
}

function Card({ accent, children, style, onClick }) {
  const t = useBrand();
  return (
    <div onClick={onClick} style={{
      background: '#fff', border: `1px solid ${t.rule}`, borderRadius: 8,
      padding: 20, position: 'relative', overflow: 'hidden',
      boxShadow: '0 1px 2px rgba(26,26,26,0.04)',
      cursor: onClick ? 'pointer' : 'default',
      transition: 'box-shadow .18s, transform .18s',
      ...style,
    }}
    onMouseEnter={e => { if (onClick) e.currentTarget.style.boxShadow = '0 10px 24px rgba(26,26,26,0.08)'; }}
    onMouseLeave={e => { if (onClick) e.currentTarget.style.boxShadow = '0 1px 2px rgba(26,26,26,0.04)'; }}
    >
      {accent && <span style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 4, background: accent }} />}
      {children}
    </div>
  );
}

function Field({ label, children }) {
  const t = useBrand();
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{ font: "600 12px/1 'Space Grotesk', Arial", color: t.ink }}>{label}</span>
      {children}
    </label>
  );
}

function TextInput({ value, onChange, placeholder }) {
  const t = useBrand();
  const [focus, setFocus] = useState(false);
  return (
    <input
      value={value || ''}
      placeholder={placeholder}
      onChange={e => onChange && onChange(e.target.value)}
      onFocus={() => setFocus(true)}
      onBlur={() => setFocus(false)}
      style={{
        font: "400 14px/1.2 Inter, Arial",
        padding: '10px 12px', border: `1px solid ${focus ? t.primary : t.rule}`,
        borderRadius: 4, background: '#fff', color: t.ink,
        outline: 'none', boxShadow: focus ? `0 0 0 3px ${t.primaryMid}` : 'none',
      }}
    />
  );
}

function Textarea({ value, onChange, placeholder, rows = 4 }) {
  const t = useBrand();
  const [focus, setFocus] = useState(false);
  return (
    <textarea
      rows={rows}
      value={value || ''}
      placeholder={placeholder}
      onChange={e => onChange && onChange(e.target.value)}
      onFocus={() => setFocus(true)}
      onBlur={() => setFocus(false)}
      style={{
        font: "400 14px/1.5 Inter, Arial",
        padding: '10px 12px', border: `1px solid ${focus ? t.primary : t.rule}`,
        borderRadius: 4, background: '#fff', color: t.ink,
        outline: 'none', boxShadow: focus ? `0 0 0 3px ${t.primaryMid}` : 'none',
        resize: 'vertical', fontFamily: 'Inter, Arial',
      }}
    />
  );
}

function ChipGroup({ options, value, onChange, multi }) {
  const t = useBrand();
  const sel = multi ? value || [] : [value].filter(Boolean);
  const toggle = (v) => {
    if (multi) {
      const next = sel.includes(v) ? sel.filter(x => x !== v) : [...sel, v];
      onChange(next);
    } else onChange(v);
  };
  return (
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      {options.map(o => {
        const on = sel.includes(o);
        return (
          <span key={o} onClick={() => toggle(o)} style={{
            font: "500 13px/1 Inter, Arial",
            padding: '8px 12px', borderRadius: 999, cursor: 'pointer',
            background: on ? t.primary : t.soft,
            color: on ? '#fff' : t.body,
            border: `1px solid ${on ? t.primary : t.rule}`,
            transition: '.18s',
          }}>{o}</span>
        );
      })}
    </div>
  );
}

function Stepper({ steps, current }) {
  const t = useBrand();
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
      {steps.map((s, i) => {
        const done = i < current, active = i === current;
        return (
          <React.Fragment key={s}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <div style={{
                width: 28, height: 28, borderRadius: 999,
                background: done ? t.primary : '#fff',
                border: `1px solid ${done || active ? t.primary : t.rule}`,
                color: done ? '#fff' : active ? t.primary : t.muted,
                font: "600 12px/1 'Space Grotesk', Arial",
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>{done ? '✓' : i + 1}</div>
              <div style={{
                font: "600 13px/1 'Space Grotesk', Arial",
                color: active ? t.ink : done ? t.body : t.muted,
              }}>{s}</div>
            </div>
            {i < steps.length - 1 && (
              <div style={{ flex: 1, height: 1, background: t.rule, margin: '0 14px' }} />
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}

function GradientBar({ height = 3 }) {
  const t = useBrand();
  return <div style={{ height, width: '100%', background: t.gradient }} />;
}

// Classified — wraps sensitive text (clearances, codenames) in a blur overlay.
// Hovering shows a tooltip saying the viewer needs an approved account. Used
// across TWS and EPL to demonstrate the access gate without rebuilding auth.
function Classified({ children, tooltip = 'Please log in with an approved account', inline = false }) {
  const [hovering, setHovering] = useState(false);
  const wrap = inline ? 'inline-block' : 'inline-block';
  return (
    <span
      onMouseEnter={() => setHovering(true)}
      onMouseLeave={() => setHovering(false)}
      style={{ position: 'relative', display: wrap, cursor: 'help' }}
    >
      <span style={{
        display: 'inline-block',
        filter: 'blur(5px)',
        userSelect: 'none',
        WebkitUserSelect: 'none',
        color: 'inherit',
        transition: 'filter .18s',
        opacity: 0.75,
      }}>{children}</span>
      {/* Subtle lock glyph sitting on top of the blur */}
      <span aria-hidden style={{
        position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
        pointerEvents: 'none', opacity: 0.55,
      }}>
        <svg width="11" height="13" viewBox="0 0 11 13" fill="none">
          <rect x="1" y="5.5" width="9" height="7" rx="1" stroke="currentColor" strokeWidth="1.2" fill="rgba(255,255,255,0.5)" />
          <path d="M3 5.5 V3.5 a2.5 2.5 0 0 1 5 0 V5.5" stroke="currentColor" strokeWidth="1.2" fill="none" />
        </svg>
      </span>
      {hovering && (
        <span role="tooltip" style={{
          position: 'absolute', bottom: 'calc(100% + 8px)', left: '50%', transform: 'translateX(-50%)',
          background: '#1A1A1A', color: '#fff',
          font: "500 12px/1.35 Inter, Arial",
          padding: '8px 10px', borderRadius: 6,
          whiteSpace: 'nowrap', zIndex: 100,
          boxShadow: '0 8px 20px rgba(0,0,0,0.18)',
          pointerEvents: 'none',
        }}>
          🔒 {tooltip}
          <span style={{
            position: 'absolute', top: '100%', left: '50%', transform: 'translateX(-50%)',
            width: 0, height: 0,
            borderLeft: '5px solid transparent', borderRight: '5px solid transparent',
            borderTop: '5px solid #1A1A1A',
          }} />
        </span>
      )}
    </span>
  );
}

// redactClassified — given a string, wraps any occurrences of sensitive keywords
// (ASD, REDSPICE, and ASD + trailing context like "ASD OSA" or "ASD, Defence")
// in <Classified>. Returns a React fragment suitable for rendering in place of
// the original string. Keywords are case-insensitive.
const CLASSIFIED_PATTERN = /(REDSPICE(?:\s*\/\s*ASD)?|ASD\s+OSA|ASD,\s*Defence|ASD|REDSPICE)/gi;
function redactClassified(text) {
  if (!text) return text;
  const parts = [];
  let lastIndex = 0;
  let m; let i = 0;
  const re = new RegExp(CLASSIFIED_PATTERN.source, 'gi');
  while ((m = re.exec(text)) !== null) {
    if (m.index > lastIndex) parts.push(text.slice(lastIndex, m.index));
    parts.push(<Classified key={'c' + i++}>{m[0]}</Classified>);
    lastIndex = m.index + m[0].length;
  }
  if (lastIndex < text.length) parts.push(text.slice(lastIndex));
  return parts.length ? <>{parts}</> : text;
}

Object.assign(window, {
  Button, Badge, Card, Field, TextInput, Textarea, ChipGroup, Stepper, GradientBar, Classified, redactClassified,
  BrandTheme, useBrand, UNORDINARY_THEME, ELYSIUM_THEME,
});
