/* ============================================================
   TechManager — SHARED UI
   ============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---- Subscribe to the mock backend ---- */
function useDB() {
  const [, force] = useState(0);
  useEffect(() => TM.subscribe(() => force((n) => n + 1)), []);
  return TM.get();
}

/* ---- Icons (inline, stroke-based) ---- */
const Icon = ({ name, size = 18, style }) => {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', style };
  const paths = {
    arrow: <path d="M5 12h14M13 6l6 6-6 6" />,
    arrowL: <path d="M19 12H5M11 18l-6-6 6-6" />,
    lock: <><rect x="4" y="11" width="16" height="9" rx="2" /><path d="M8 11V8a4 4 0 0 1 8 0v3" /></>,
    check: <path d="M5 13l4 4L19 7" />,
    checkCircle: <><circle cx="12" cy="12" r="9" /><path d="M8.5 12l2.5 2.5 4.5-5" /></>,
    x: <path d="M6 6l12 12M18 6L6 18" />,
    xCircle: <><circle cx="12" cy="12" r="9" /><path d="M9 9l6 6M15 9l-6 6" /></>,
    play: <path d="M8 5v14l11-7z" fill="currentColor" stroke="none" />,
    share: <><circle cx="18" cy="5" r="3" /><circle cx="6" cy="12" r="3" /><circle cx="18" cy="19" r="3" /><path d="M8.6 13.5l6.8 4M15.4 6.5l-6.8 4" /></>,
    linkedin: <path d="M4.98 3.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM3 9h4v12H3zM9 9h3.8v1.7h.05c.53-1 1.83-2.05 3.77-2.05C20.5 8.65 21 11.2 21 14.3V21h-4v-5.9c0-1.4-.03-3.2-2-3.2-2 0-2.3 1.5-2.3 3.1V21H9z" fill="currentColor" stroke="none" />,
    book: <><path d="M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2z" /><path d="M19 19H6a2 2 0 0 0-2 2" /></>,
    clock: <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
    target: <><circle cx="12" cy="12" r="8" /><circle cx="12" cy="12" r="4" /><circle cx="12" cy="12" r="1" fill="currentColor" /></>,
    image: <><rect x="3" y="4" width="18" height="16" rx="2" /><circle cx="8.5" cy="9.5" r="1.5" /><path d="M21 16l-5-5-7 7" /></>,
    diagram: <><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /><path d="M10 6h4a3 3 0 0 1 3 3v5" /></>,
    plus: <path d="M12 5v14M5 12h14" />,
    trash: <><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13" /></>,
    edit: <><path d="M4 20h4L19 9l-4-4L4 16z" /><path d="M14 6l4 4" /></>,
    up: <path d="M12 19V5M6 11l6-6 6 6" />,
    down: <path d="M12 5v14M6 13l6 6 6-6" />,
    grid: <><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /></>,
    user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4 4-6 8-6s8 2 8 6" /></>,
    shield: <path d="M12 3l8 3v6c0 4.5-3.2 7.8-8 9-4.8-1.2-8-4.5-8-9V6z" />,
    award: <><circle cx="12" cy="9" r="6" /><path d="M9 14.5L8 21l4-2 4 2-1-6.5" /></>,
    sparkle: <path d="M12 3l2 6 6 2-6 2-2 6-2-6-6-2 6-2z" fill="currentColor" stroke="none" />,
    settings: <><circle cx="12" cy="12" r="3" /><path d="M12 2v3M12 19v3M5 5l2 2M17 17l2 2M2 12h3M19 12h3M5 19l2-2M17 7l2-2" /></>,
    chevR: <path d="M9 6l6 6-6 6" />,
    refresh: <><path d="M21 12a9 9 0 1 1-3-6.7" /><path d="M21 4v5h-5" /></>,
  };
  return <svg {...p}>{paths[name] || null}</svg>;
};

/* ---- Status badge ---- */
const StatusBadge = ({ status }) => {
  if (status === 'READY') return <span className="badge badge-ready"><Icon name="check" size={12} /> Ready</span>;
  if (status === 'COMING_SOON') return <span className="badge badge-soon">Coming soon</span>;
  return <span className="badge badge-draft">Not ready</span>;
};

/* ---- Modal ---- */
const Modal = ({ open, onClose, children, width }) => {
  useEffect(() => {
    if (!open) return;
    const h = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-scrim" onMouseDown={onClose}>
      <div className="modal" style={width ? { maxWidth: width } : null} onMouseDown={(e) => e.stopPropagation()}>{children}</div>
    </div>
  );
};

/* ---- Glossy orb (reused at any size) ---- */
const Orb = ({ cert, size = 96, onClick, dim }) => (
  <div
    className="node-orb"
    onClick={onClick}
    style={{
      width: size, height: size, fontSize: size * 0.4,
      background: `radial-gradient(circle at 35% 28%, ${lighten(cert.color)}, ${cert.color} 52%, ${cert.color2} 100%)`,
      boxShadow: `0 14px 34px -10px ${cert.color}88, 0 0 0 1px rgba(255,255,255,0.10) inset, 0 2px 6px rgba(255,255,255,0.4) inset`,
      opacity: dim ? 0.5 : 1,
      cursor: onClick ? 'pointer' : 'default',
    }}
  >
    <span style={{ filter: 'drop-shadow(0 2px 3px rgba(0,0,0,.35))' }}>{cert.emoji}</span>
  </div>
);

function lighten(hex) {
  // quick lighten for the glossy core
  try {
    const c = hex.replace('#', '');
    const r = Math.min(255, parseInt(c.slice(0, 2), 16) + 70);
    const g = Math.min(255, parseInt(c.slice(2, 4), 16) + 70);
    const b = Math.min(255, parseInt(c.slice(4, 6), 16) + 70);
    return `rgb(${r},${g},${b})`;
  } catch (e) { return hex; }
}

/* ---- The signature network node graph ---- */
const NodeGraph = ({ certs, onSelect, orbSize = 92, showLabels = true }) => {
  // dedupe edges
  const edges = [];
  const seen = new Set();
  certs.forEach((c) => (c.connections || []).forEach((tid) => {
    const target = certs.find((x) => x.id === tid);
    if (!target) return;
    const key = [c.id, tid].sort().join('|');
    if (seen.has(key)) return;
    seen.add(key);
    edges.push({ a: c, b: target });
  }));
  return (
    <div className="graph">
      <svg preserveAspectRatio="none">
        <defs>
          <linearGradient id="edgeGrad" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="#2f7df6" stopOpacity="0.9" />
            <stop offset="1" stopColor="#4a9bff" stopOpacity="0.55" />
          </linearGradient>
        </defs>
        {edges.map((e, i) => (
          <g key={i}>
            <line x1={e.a.x + '%'} y1={e.a.y + '%'} x2={e.b.x + '%'} y2={e.b.y + '%'} stroke="url(#edgeGrad)" strokeWidth="2.4" strokeLinecap="round" />
            <circle cx={e.a.x + '%'} cy={e.a.y + '%'} r="4" className="node-pip" />
            <circle cx={e.b.x + '%'} cy={e.b.y + '%'} r="4" className="node-pip" />
          </g>
        ))}
      </svg>
      {certs.map((c) => (
        <div key={c.id} className="node" style={{ left: c.x + '%', top: c.y + '%' }} onClick={() => onSelect && onSelect(c)}>
          <Orb cert={c} size={orbSize} dim={c.status === 'COMING_SOON'} />
          {showLabels && (
            <div className="node-label">
              {c.name.replace(' Manager', '')}
              {c.status === 'COMING_SOON' && <div style={{ fontSize: 10, color: 'var(--amber)', fontWeight: 800, letterSpacing: '.08em', marginTop: 2 }}>SOON</div>}
            </div>
          )}
        </div>
      ))}
    </div>
  );
};

/* ---- Top navigation ---- */
const NAV_ITEMS = [
  { key: 'home', label: 'Home' },
  { key: 'certs', label: 'Certifications' },
  { key: 'roadmap', label: 'Roadmap' },
  { key: 'profile', label: 'Profile' },
];
const Nav = ({ route, go }) => (
  <nav className="nav">
    <div className="wrap nav-inner">
      <div className="brand" onClick={() => go('home')} style={{ cursor: 'pointer' }}>
        <span className="brand-dot" />
        <span>Tech<span style={{ color: 'var(--blue-2)' }}>Manager</span></span>
      </div>
      <div className="nav-links">
        {NAV_ITEMS.map((n) => (
          <button key={n.key} className={'nav-link' + (route.name === n.key ? ' active' : '')} onClick={() => go(n.key)}>{n.label}</button>
        ))}
      </div>
      <div className="nav-spacer" />
      <button className="nav-link" onClick={() => go('admin')} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <Icon name="settings" size={16} /> Admin
      </button>
      <button className="btn btn-primary btn-sm" onClick={() => go('certs')}>Get Started Free</button>
    </div>
  </nav>
);

const Footer = ({ go }) => (
  <footer className="footer">
    <div className="wrap between" style={{ flexWrap: 'wrap', gap: 20 }}>
      <div className="brand" style={{ fontSize: 17 }}>
        <span className="brand-dot" /> <span>Tech<span style={{ color: 'var(--blue-2)' }}>Manager</span></span>
      </div>
      <div className="muted" style={{ fontSize: 13.5 }}>Stackable technical credibility for engineering managers.</div>
      <div className="flex gap-16" style={{ fontSize: 13.5 }}>
        <a className="muted" onClick={() => go('certs')} style={{ cursor: 'pointer' }}>Certifications</a>
        <a className="muted" onClick={() => go('roadmap')} style={{ cursor: 'pointer' }}>Roadmap</a>
        <a className="muted" onClick={() => go('admin')} style={{ cursor: 'pointer' }}>Admin</a>
      </div>
    </div>
  </footer>
);

/* ---- Small reusable bits ---- */
const Field = ({ label, children }) => (
  <label style={{ display: 'block' }}>
    {label && <span className="field-label">{label}</span>}
    {children}
  </label>
);

const ScoreRing = ({ pct, size = 132, pass }) => {
  const r = (size - 16) / 2, C = 2 * Math.PI * r;
  const col = pass ? 'var(--green)' : 'var(--red)';
  return (
    <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="rgba(255,255,255,0.08)" strokeWidth="11" />
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={col} strokeWidth="11" strokeLinecap="round"
        strokeDasharray={C} strokeDashoffset={C * (1 - pct / 100)} style={{ transition: 'stroke-dashoffset 1s ease' }} />
      <text x="50%" y="50%" textAnchor="middle" dominantBaseline="central" transform={`rotate(90 ${size / 2} ${size / 2})`}
        fill="#fff" fontSize={size * 0.26} fontWeight="800" fontFamily="var(--display)">{pct}%</text>
    </svg>
  );
};

Object.assign(window, { useDB, Icon, StatusBadge, Modal, Orb, lighten, NodeGraph, Nav, Footer, Field, ScoreRing,
  useState, useEffect, useRef, useMemo, useCallback });
