/* ============================================================
   Lectual CRM — shared atoms, theme tokens, icons, helpers
   Exports to window for cross-file (Babel) use.
   ============================================================ */
const { useState, useEffect, useMemo, useRef, useCallback } = React;

/* ---------------- firm-theme token system ----------------
   Proves the tokenization: every client-facing + chrome accent
   reads --firm-* which derives from --accent. Switching theme
   re-skins the whole CRM with no hardcoded brand color. */
const THEMES = {
  lectual: {
    name: 'Lectual', tier: 'Platform · default', logo: 'L', display: "'Bricolage Grotesque'",
    light: {
      '--accent': '#2F5BE6', '--accent-press': '#2348BE', '--on-accent': '#FFFFFF',
      '--paper': '#F7F2E9', '--paper-2': '#FBF7EF', '--surface': '#FFFFFF',
      '--ink': '#1B1815', '--ink-2': '#57514A', '--ink-3': '#8B8275',
      '--border': '#E7DFCF', '--border-2': '#DAD0BC',
      '--protected': '#1B6B4C', '--protected-bg': '#E1F0E6', '--warning': '#9C6209', '--warning-bg': '#F7EAD0', '--danger': '#B23B2E',
      '--rail-bg': '#161310', '--rail-ink': '#B6AD9C', '--rail-ink-strong': '#F4EEE2', '--rail-seg': '#857a68', '--rail-hover': 'rgba(255,255,255,.06)',
    },
    dark: {
      '--accent': '#6E8DF6', '--accent-press': '#5877E0', '--on-accent': '#0E1530',
      '--paper': '#14110D', '--paper-2': '#1B1711', '--surface': '#221D15',
      '--ink': '#F4EEE2', '--ink-2': '#B8B0A0', '--ink-3': '#837A6B',
      '--border': '#2F291F', '--border-2': '#423A2C',
      '--protected': '#62CD98', '--protected-bg': '#143329', '--warning': '#E0A23C', '--warning-bg': '#372B14', '--danger': '#E5705F',
      '--rail-bg': '#0E0C09', '--rail-ink': '#9A9182', '--rail-ink-strong': '#F4EEE2', '--rail-seg': '#6b6354', '--rail-hover': 'rgba(255,255,255,.05)',
    },
  },
  rpb: {
    name: 'Rivera Park · Boutique IP', tier: 'Growth · co-brand', logo: 'R', display: "'Instrument Serif'",
    light: {
      '--accent': '#B8430E', '--accent-press': '#8F340B', '--on-accent': '#FFF6EE',
      '--paper': '#FBF4E7', '--paper-2': '#FDF9F0', '--surface': '#FFFDF8',
      '--ink': '#2A1C12', '--ink-2': '#6B5848', '--ink-3': '#A08C78',
      '--border': '#EDE0CB', '--border-2': '#E0CFB2',
      '--protected': '#3E6B3A', '--protected-bg': '#E7EFDF', '--warning': '#A8650C', '--warning-bg': '#F8EAD0', '--danger': '#A8362A',
      '--rail-bg': '#241008', '--rail-ink': '#C4A88F', '--rail-ink-strong': '#F8ECDD', '--rail-seg': '#8a6b53', '--rail-hover': 'rgba(255,255,255,.07)',
    },
    dark: {
      '--accent': '#E87645', '--accent-press': '#D2602F', '--on-accent': '#2A1206',
      '--paper': '#1A0F08', '--paper-2': '#22150C', '--surface': '#2A1B10',
      '--ink': '#F8ECDD', '--ink-2': '#C9B49E', '--ink-3': '#94806B',
      '--border': '#3A2616', '--border-2': '#4E3621',
      '--protected': '#7FB173', '--protected-bg': '#1F3019', '--warning': '#DDA04A', '--warning-bg': '#382814', '--danger': '#E5806F',
      '--rail-bg': '#160B05', '--rail-ink': '#B0937A', '--rail-ink-strong': '#F8ECDD', '--rail-seg': '#7a5d46', '--rail-hover': 'rgba(255,255,255,.06)',
    },
  },
  meridian: {
    name: 'Meridian IP Group', tier: 'Enterprise · white-label', logo: 'M', display: "'Space Grotesk'",
    light: {
      '--accent': '#2563EB', '--accent-press': '#1D4FC4', '--on-accent': '#FFFFFF',
      '--paper': '#EEF1F6', '--paper-2': '#F6F8FB', '--surface': '#FFFFFF',
      '--ink': '#0F1B2D', '--ink-2': '#46546B', '--ink-3': '#8190A6',
      '--border': '#DCE2EB', '--border-2': '#C6CFDC',
      '--protected': '#0E7C5A', '--protected-bg': '#DBF0E7', '--warning': '#B0700C', '--warning-bg': '#F6EAD2', '--danger': '#C8392C',
      '--rail-bg': '#0C1A2E', '--rail-ink': '#93A4BC', '--rail-ink-strong': '#EAF0F8', '--rail-seg': '#5e718c', '--rail-hover': 'rgba(255,255,255,.07)',
    },
    dark: {
      '--accent': '#5B8DEF', '--accent-press': '#4576DC', '--on-accent': '#08152B',
      '--paper': '#0A1320', '--paper-2': '#0F1B2C', '--surface': '#152538',
      '--ink': '#EAF0F8', '--ink-2': '#A7B6CC', '--ink-3': '#6F8098',
      '--border': '#1E3047', '--border-2': '#2C415C',
      '--protected': '#4DBE93', '--protected-bg': '#0F2E25', '--warning': '#D9A046', '--warning-bg': '#33280F', '--danger': '#E0705F',
      '--rail-bg': '#060E1A', '--rail-ink': '#8497B0', '--rail-ink-strong': '#EAF0F8', '--rail-seg': '#566980', '--rail-hover': 'rgba(255,255,255,.05)',
    },
  },
};

function applyTheme(key, dark) {
  const th = THEMES[key] || THEMES.lectual;
  const map = dark ? th.dark : th.light;
  const s = document.documentElement.style;
  Object.entries(map).forEach(([k, v]) => s.setProperty(k, v));
  // Set the firm-* token contract directly (no var() indirection) so every
  // client-facing + chrome surface re-skins reliably.
  s.setProperty('--firm-primary', map['--accent']);
  s.setProperty('--firm-primary-hover', map['--accent-press']);
  s.setProperty('--firm-on-primary', map['--on-accent']);
  s.setProperty('--firm-accent', map['--accent']);
  s.setProperty('--firm-font-display', th.display);
  s.setProperty('--accent-soft', `color-mix(in srgb, ${map['--accent']} 13%, ${map['--surface']})`);
}

/* ---------------- score helpers ---------------- */
const bandColor = (v) => (v >= 70 ? 'var(--protected)' : v >= 45 ? 'var(--firm-primary)' : 'var(--warning)');
const bandName = (v) => (v >= 85 ? 'Filing-ready' : v >= 70 ? 'Strong' : v >= 45 ? 'Building' : 'Early');

/* ---------------- brand atoms ---------------- */
function Echo({ size = 18 }) {
  return (
    <span className="echo" style={{ fontSize: size, fontFamily: 'var(--firm-font-display)' }}>
      Lectua<span className="gl"><span className="sh" aria-hidden="true">l</span><span className="fg" style={{ color: 'var(--firm-primary)' }}>l</span></span>
    </span>
  );
}

function Gauge({ value, size = 116, stroke = 12 }) {
  const r = (size - stroke) / 2, C = 2 * Math.PI * r;
  // Rest at the final value; if rAF runs, the first tick dips to ~0 and counts
  // up. If rAF is throttled (hidden tab), it simply stays correct — never 0.
  const [disp, setDisp] = useState(value);
  useEffect(() => {
    let raf; const start = performance.now(), dur = 850;
    const tick = (t) => { const p = Math.min(1, (t - start) / dur), e = 1 - Math.pow(1 - p, 3); setDisp(Math.round(value * e)); if (p < 1) raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value]);
  return (
    <div className="gauge" style={{ width: size, height: size }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--border-2)" strokeWidth={stroke} />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={bandColor(value)} strokeWidth={stroke} strokeLinecap="round" strokeDasharray={C} strokeDashoffset={C * (1 - disp / 100)} />
      </svg>
      <div className="gv"><b style={{ fontSize: size * 0.30 }}>{disp}</b><span>/100</span></div>
    </div>
  );
}

/* ---------------- icons ---------------- */
const sv = (p, sw = 2) => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">{p}</svg>;
const I = {
  today:    sv(<><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>),
  pipe:     sv(<><rect x="3" y="4" width="18" height="16" rx="2" /><path d="M3 9h18" /></>),
  leads:    sv(<><path d="M3 6h18M3 12h18M3 18h12" /></>),
  copilot:  sv(<><path d="M12 3l1.7 4.5L18 9l-4.3 1.4L12 15l-1.7-4.6L6 9l4.3-1.5z" /></>),
  market:   sv(<><path d="M3 11l18-7-7 18-2.5-7.5z" /></>),
  reports:  sv(<><path d="M4 20V10M10 20V4M16 20v-7M22 20H2" /></>),
  admin:    sv(<><circle cx="12" cy="12" r="3" /><path d="M12 3v2M12 19v2M5 5l1.5 1.5M17.5 17.5L19 19M3 12h2M19 12h2M5 19l1.5-1.5M17.5 6.5L19 5" /></>),
  search:   sv(<><circle cx="11" cy="11" r="7" /><path d="M21 21l-4-4" /></>),
  bell:     sv(<><path d="M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6z" /><path d="M10 19a2 2 0 0 0 4 0" /></>),
  spark:    sv(<><path d="M12 3l1.7 4.5L18 9l-4.3 1.4L12 15l-1.7-4.6L6 9l4.3-1.5z" /></>),
  check:    sv(<><path d="M5 12l4 4 10-10" /></>),
  alert:    sv(<><path d="M12 3l9 16H3z" /><path d="M12 10v4M12 17v.01" /></>),
  flag:     sv(<><path d="M5 21V4M5 4h11l-2 4 2 4H5" /></>),
  clock:    sv(<><circle cx="12" cy="12" r="9" /><path d="M12 8v4l3 2" /></>),
  mail:     sv(<><rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 6 9-6" /></>),
  phone:    sv(<><path d="M5 4h4l2 5-3 2a14 14 0 0 0 6 6l2-3 5 2v4a2 2 0 0 1-2 2A17 17 0 0 1 3 6a2 2 0 0 1 2-2z" /></>),
  building: sv(<><rect x="4" y="3" width="16" height="18" rx="1" /><path d="M9 7h.01M15 7h.01M9 11h.01M15 11h.01M9 15h6v6H9z" /></>),
  doc:      sv(<><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" /><path d="M14 3v6h6" /></>),
  download: sv(<><path d="M12 3v12M7 11l5 4 5-4M5 21h14" /></>),
  arrow:    sv(<><path d="M5 12h14M13 6l6 6-6 6" /></>),
  plus:     sv(<><path d="M12 5v14M5 12h14" /></>),
  move:     sv(<><path d="M5 9l-3 3 3 3M9 5l3-3 3 3M15 19l-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20" /></>),
  tag:      sv(<><path d="M3 11l8-8 9 9-8 8z" /><circle cx="8" cy="8" r="1.5" /></>),
  task:     sv(<><rect x="4" y="4" width="16" height="16" rx="2" /><path d="M9 12l2 2 4-4" /></>),
  drip:     sv(<><path d="M12 3s6 6 6 11a6 6 0 0 1-12 0c0-5 6-11 6-11z" /></>),
  link:     sv(<><path d="M10 13a5 5 0 0 0 7 0l2-2a5 5 0 0 0-7-7l-1 1M14 11a5 5 0 0 0-7 0l-2 2a5 5 0 0 0 7 7l1-1" /></>),
  view:     sv(<><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z" /><circle cx="12" cy="12" r="3" /></>),
  user:     sv(<><circle cx="12" cy="8" r="4" /><path d="M4 20c0-4 4-6 8-6s8 2 8 6" /></>),
  zap:      sv(<><path d="M13 2L4 14h7l-1 8 9-12h-7z" /></>),
  agent:    sv(<><rect x="4" y="9" width="16" height="11" rx="3" /><path d="M12 9V5.5" /><path d="M12 4h.01" strokeWidth="2.4" /><path d="M9 14h.01M15 14h.01" strokeWidth="2.6" /><path d="M2 14v2M22 14v2" /></>),
  shield:   sv(<><path d="M12 3l8 3v6c0 4.5-3.2 7.5-8 9-4.8-1.5-8-4.5-8-9V6z" /><path d="M9 12l2 2 4-4" /></>),
  pause:    sv(<><rect x="6" y="5" width="4" height="14" rx="1" /><rect x="14" y="5" width="4" height="14" rx="1" /></>),
  play:     sv(<><path d="M7 4l13 8-13 8z" /></>),
  sliders:  sv(<><path d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6" /></>),
  route:    sv(<><circle cx="6" cy="6" r="2.5" /><circle cx="6" cy="18" r="2.5" /><path d="M6 8.5v7M8.5 6H14a4 4 0 0 1 0 8H9" /></>),
};

/* timeline / feed icon style by type */
const evMeta = {
  ai:       { ic: I.spark,    bg: 'color-mix(in srgb,var(--firm-primary) 14%,var(--surface))', fg: 'var(--firm-primary)' },
  score:    { ic: I.zap,      bg: 'color-mix(in srgb,var(--firm-primary) 14%,var(--surface))', fg: 'var(--firm-primary)' },
  call:     { ic: I.phone,    bg: 'var(--protected-bg)', fg: 'var(--protected)' },
  proposal: { ic: I.doc,      bg: 'var(--protected-bg)', fg: 'var(--protected)' },
  email:    { ic: I.mail,     bg: 'var(--warning-bg)',   fg: 'var(--warning)' },
  view:     { ic: I.view,     bg: 'var(--paper)',        fg: 'var(--ink-3)' },
  download: { ic: I.download, bg: 'var(--paper)',        fg: 'var(--ink-3)' },
  form:     { ic: I.task,     bg: 'var(--paper)',        fg: 'var(--ink-3)' },
  enter:    { ic: I.arrow,    bg: 'var(--paper)',        fg: 'var(--ink-3)' },
  flag:     { ic: I.flag,     bg: 'var(--warning-bg)',   fg: 'var(--warning)' },
  tag:      { ic: I.tag,      bg: 'var(--paper)',        fg: 'var(--ink-3)' },
  check:    { ic: I.check,    bg: 'var(--protected-bg)', fg: 'var(--protected)' },
};

/* ---------------- toast ---------------- */
function useToasts() {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((t, err) => {
    const id = Math.random();
    setToasts((cur) => [...cur, { id, t, err }]);
    setTimeout(() => setToasts((cur) => cur.filter((x) => x.id !== id)), 3500);
  }, []);
  return [toasts, push];
}
function Toaster({ toasts }) {
  return (
    <div className="toaster">
      {toasts.map((t) => (
        <div key={t.id} className={'toast' + (t.err ? ' err' : '')}>
          <span style={{ color: t.err ? 'var(--danger)' : 'var(--protected)', width: 18, height: 18, display: 'grid', placeItems: 'center' }}>{t.err ? I.alert : I.check}</span>
          <span className="tt">{t.t}</span>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, {
  THEMES, applyTheme, bandColor, bandName, Echo, Gauge, I, evMeta, useToasts, Toaster,
});
