// shared.jsx — reusable visual primitives
// Exports to window: Wordmark, Mark, ScoreRing, ScoreBar, RiskPill, MetaLabel,
// IconArrow, IconCheck, IconClose, IconExt, IconSpark, IconRefresh, IconShield,
// IconScan, FindingCard, CategoryRow, useInView

const { useEffect, useRef, useState } = React;

/* ────────────────────────── Brand mark + wordmark ─────────────────────── */

function Mark({ size = 18, color = "currentColor", title = "CrestIron" }) {
  // Stacked chevron "crest" over a vertical iron bar.
  const w = size;
  const h = Math.round(size * 1.25);
  return (
    <svg width={w} height={h} viewBox="0 0 16 20" role="img" aria-label={title}
         fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="square" strokeLinejoin="miter">
      <path d="M2 6 L8 1 L14 6" />
      <path d="M3 10 L8 6 L13 10" />
      <line x1="8" y1="10" x2="8" y2="19" />
    </svg>
  );
}

function Wordmark({ size = 14, gap = 9, color = "currentColor" }) {
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap, color }}>
      <Mark size={size + 4} color={color} />
      <span style={{
        fontFamily: "var(--font-sans)",
        fontSize: size,
        fontWeight: 500,
        letterSpacing: "0.14em",
        textTransform: "uppercase",
      }}>CrestIron</span>
    </div>
  );
}

/* ────────────────────────── Score ring (SVG) ──────────────────────────── */

function ScoreRing({ value = 57, size = 160, stroke = 8, label = "OrgScore", animated = true }) {
  const [shown, setShown] = useState(animated ? 0 : value);
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  useEffect(() => {
    if (!animated) return setShown(value);
    let raf, start;
    const dur = 1400;
    const tick = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setShown(Math.round(value * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value, animated]);

  const status = value >= 75 ? "ok" : value >= 60 ? "warn" : "risk";
  const colorVar = `var(--${status})`;

  return (
    <div style={{ position: "relative", width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none"
                stroke="var(--surface-2)" strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none"
                stroke={colorVar} strokeWidth={stroke}
                strokeDasharray={c}
                strokeDashoffset={c - (c * shown / 100)}
                strokeLinecap="round"
                style={{ transition: animated ? "none" : "stroke-dashoffset 600ms ease" }} />
      </svg>
      <div style={{
        position: "absolute", inset: 0, display: "flex",
        flexDirection: "column", alignItems: "center", justifyContent: "center",
      }}>
        <div style={{
          fontFamily: "var(--font-sans)",
          fontSize: Math.round(size * 0.32),
          fontWeight: 300,
          letterSpacing: "-0.02em",
          color: "var(--text-primary)",
          lineHeight: 1,
        }}>{shown}</div>
        <div className="mono-sm muted" style={{ marginTop: 6, letterSpacing: "0.1em", textTransform: "uppercase" }}>
          {label}
        </div>
      </div>
    </div>
  );
}

/* ────────────────────────── Score bar row ─────────────────────────────── */

function ScoreBar({ label, value, status, delay = 0 }) {
  const [v, setV] = useState(0);
  useEffect(() => {
    const t = setTimeout(() => setV(value), delay);
    return () => clearTimeout(t);
  }, [value, delay]);
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: 8 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gridColumn: "1 / -1" }}>
        <span style={{ fontSize: 13, color: "var(--text-secondary)" }}>{label}</span>
        <span className="mono" style={{ color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>{v}</span>
      </div>
      <div className={`bar bar-${status}`} style={{ gridColumn: "1 / -1" }}>
        <div style={{ width: `${v}%` }} />
      </div>
    </div>
  );
}


/* ────────────────────────── Cost of inaction panel ────────────────────── */

function InactionPanel({ kicker = "// Cost of inaction", title, body, risks = [], cta, onCta }) {
  return (
    <div className="card" style={{
      padding: 0,
      overflow: "hidden",
      borderColor: "rgba(217,99,112,0.34)",
      background: "linear-gradient(135deg, rgba(217,99,112,0.12), var(--surface-0) 42%)",
      boxShadow: "0 24px 80px rgba(217,99,112,0.08)",
    }}>
      <div style={{
        padding: "18px 24px",
        borderBottom: "1px solid rgba(217,99,112,0.24)",
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        gap: 16,
        flexWrap: "wrap",
      }}>
        <span className="pill pill-risk">DO NOT IGNORE</span>
        <span className="mono-sm muted">Unknown risk compounds quietly</span>
      </div>
      <div style={{ padding: 28 }}>
        <div className="eyebrow" style={{ color: "var(--risk)" }}>{kicker}</div>
        <h3 className="h2" style={{ marginTop: 10, maxWidth: 24 + "ch" }}>{title}</h3>
        <p className="body" style={{ marginTop: 14, color: "var(--text-secondary)", maxWidth: 62 + "ch" }}>{body}</p>
        <div className="grid grid-3" style={{ gap: 12, marginTop: 24 }}>
          {risks.map((risk, i) => (
            <div key={i} style={{
              border: "1px solid rgba(217,99,112,0.22)",
              background: "rgba(217,99,112,0.07)",
              borderRadius: "var(--r-2)",
              padding: 16,
            }}>
              <div className="mono-sm" style={{ color: "var(--risk)", letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 8 }}>{risk.label}</div>
              <div style={{ fontSize: 14, color: "var(--text-primary)", lineHeight: 1.45 }}>{risk.text}</div>
            </div>
          ))}
        </div>
        {cta && (
          <button className="btn btn-primary" style={{ marginTop: 24 }} onClick={onCta}>
            {cta} <IconArrow />
          </button>
        )}
      </div>
    </div>
  );
}

/* ────────────────────────── Risk pill ──────────────────────────────────── */

function RiskPill({ level = "P2", style = {} }) {
  const map = {
    P0: { cls: "pill-risk", label: "P0 · CRITICAL" },
    P1: { cls: "pill-risk", label: "P1 · HIGH" },
    P2: { cls: "pill-warn", label: "P2 · MEDIUM" },
    P3: { cls: "pill-dim", label: "P3 · LOW" },
    P4: { cls: "pill-dim", label: "P4 · INFO" },
  };
  const m = map[level] || map.P2;
  return <span className={`pill ${m.cls}`} style={style}>{m.label}</span>;
}

/* ────────────────────────── Meta label ────────────────────────────────── */

function MetaLabel({ k, v, mono = true }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
      <span className="mono-sm muted" style={{ textTransform: "uppercase", letterSpacing: "0.08em" }}>{k}</span>
      <span style={{ fontFamily: mono ? "var(--font-mono)" : "var(--font-sans)", fontSize: 13, color: "var(--text-primary)" }}>{v}</span>
    </div>
  );
}

/* ────────────────────────── Icons (line, 16px) ────────────────────────── */

const _icon = (size, paths) => ({ s = size, c = "currentColor", style = {} } = {}) => (
  <svg width={s} height={s} viewBox="0 0 16 16" fill="none" stroke={c}
       strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" style={style} aria-hidden="true">
    {paths}
  </svg>
);
const IconArrow = (p) => _icon(16, <><path d="M3 8h10" /><path d="M9 4l4 4-4 4" /></>)(p);
const IconCheck = (p) => _icon(16, <path d="M3 8.5l3.2 3 6.8-7" />)(p);
const IconClose = (p) => _icon(16, <><path d="M4 4l8 8" /><path d="M12 4l-8 8" /></>)(p);
const IconExt = (p) => _icon(16, <><path d="M9 3h4v4" /><path d="M13 3l-7 7" /><path d="M11 9v3H4V5h3" /></>)(p);
const IconSpark = (p) => _icon(16, <><path d="M8 2v3" /><path d="M8 11v3" /><path d="M2 8h3" /><path d="M11 8h3" /><path d="M4 4l1.6 1.6" /><path d="M10.4 10.4L12 12" /><path d="M4 12l1.6-1.6" /><path d="M10.4 5.6L12 4" /></>)(p);
const IconRefresh = (p) => _icon(16, <><path d="M13 8a5 5 0 1 1-1.7-3.8" /><path d="M13 3v2.5h-2.5" /></>)(p);
const IconShield = (p) => _icon(16, <><path d="M8 2l5 2v4c0 3-2.2 5-5 6-2.8-1-5-3-5-6V4l5-2z" /><path d="M6 8l1.5 1.5L10.5 6.5" /></>)(p);
const IconScan = (p) => _icon(16, <><path d="M3 5V3h2" /><path d="M11 3h2v2" /><path d="M13 11v2h-2" /><path d="M5 13H3v-2" /><path d="M3 8h10" /></>)(p);

/* ────────────────────────── Finding card ──────────────────────────────── */

function FindingCard({ priority, title, where, why, action, effort, owner, confidence, compact = false }) {
  return (
    <div className="card" style={{ padding: compact ? 16 : 20 }}>
      <div className="row between" style={{ marginBottom: 12 }}>
        <RiskPill level={priority} />
        {confidence && <span className="mono-sm muted">{confidence}% CONFIDENCE</span>}
      </div>
      <h4 className="h4" style={{ marginBottom: 6 }}>{title}</h4>
      {where && <div className="mono-sm muted" style={{ marginBottom: 14 }}>{where}</div>}
      {why && <p className="body-sm" style={{ margin: "0 0 14px" }}>{why}</p>}
      {action && (
        <div style={{
          background: "var(--bg-elevated)",
          border: "1px solid var(--border-subtle)",
          borderLeft: "2px solid var(--accent)",
          padding: "10px 14px",
          borderRadius: "var(--r-2)",
          fontSize: 13,
          color: "var(--text-secondary)",
          marginBottom: 14,
        }}>
          <span className="mono-sm" style={{ color: "var(--accent)", letterSpacing: "0.08em", textTransform: "uppercase", marginRight: 8 }}>Recommended</span>
          {action}
        </div>
      )}
      <div className="row" style={{ gap: 20, flexWrap: "wrap" }}>
        {effort && <span className="mono-sm muted"><span style={{ color: "var(--text-dim)" }}>EFFORT</span> &nbsp;{effort}</span>}
        {owner && <span className="mono-sm muted"><span style={{ color: "var(--text-dim)" }}>OWNER</span> &nbsp;{owner}</span>}
      </div>
    </div>
  );
}

/* ────────────────────────── Category row (with score) ─────────────────── */

function CategoryRow({ label, value, status, note }) {
  return (
    <div style={{ padding: "16px 0", borderBottom: "1px solid var(--border-subtle)", display: "grid", gridTemplateColumns: "1fr auto auto", alignItems: "center", gap: 24 }}>
      <div>
        <div style={{ fontSize: 14, color: "var(--text-primary)", marginBottom: 2 }}>{label}</div>
        {note && <div className="mono-sm muted">{note}</div>}
      </div>
      <div style={{ width: 180 }} className={`bar bar-${status}`}>
        <div style={{ width: `${value}%` }} />
      </div>
      <div className="mono" style={{ width: 32, textAlign: "right", color: "var(--text-primary)" }}>{value}</div>
    </div>
  );
}

/* ────────────────────────── useInView (one-shot trigger) ──────────────── */

function useInView(opts = {}) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current || seen) return;
    const io = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
        setSeen(true);
        io.disconnect();
      }
    }, { threshold: 0.2, ...opts });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [seen]);
  return [ref, seen];
}

/* ─── Trust strip ── Salesforce Native + zero PII/PHI egress ── */

function TrustStrip({ compact = false }) {
  const items = [
    { label: "Salesforce Native", detail: "Managed package · runs inside your org" },
    { label: "Zero data egress",   detail: "No PII or PHI ever leaves your org" },
    { label: "GovCloud-resident",  detail: "US-only · CAC/PIV friendly" },
  ];
  return (
    <div style={{
      border: "1px solid var(--border)",
      borderRadius: "var(--r-2)",
      background: "var(--bg-elevated)",
      padding: compact ? "14px 20px" : "20px 28px",
      display: "grid",
      gridTemplateColumns: "repeat(3, 1fr)",
      gap: 0,
    }} className="trust-strip">
      {items.map((it, i) => (
        <div key={it.label} style={{
          padding: "0 20px",
          borderLeft: i > 0 ? "1px solid var(--border-subtle)" : "none",
          display: "flex", gap: 12, alignItems: "flex-start",
        }}>
          <span style={{
            color: "var(--accent)",
            display: "inline-flex",
            marginTop: 2,
            flexShrink: 0,
          }} aria-hidden="true">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
                 stroke="currentColor" strokeWidth="1.4"
                 strokeLinecap="round" strokeLinejoin="round">
              <path d="M8 2l5 2v4c0 3-2.2 5-5 6-2.8-1-5-3-5-6V4l5-2z" />
              <path d="M6 8l1.5 1.5L10.5 6.5" />
            </svg>
          </span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 13, fontWeight: 500, color: "var(--text-primary)", letterSpacing: "-0.005em" }}>
              {it.label}
            </div>
            <div className="mono-sm muted" style={{ marginTop: 3, letterSpacing: "0.02em" }}>
              {it.detail}
            </div>
          </div>
        </div>
      ))}
      <style>{`
        @media (max-width: 760px) {
          .trust-strip { grid-template-columns: 1fr !important; gap: 14px !important; }
          .trust-strip > div { border-left: 0 !important; padding: 0 !important; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, {
  Wordmark, Mark, ScoreRing, ScoreBar, RiskPill, MetaLabel,
  IconArrow, IconCheck, IconClose, IconExt, IconSpark, IconRefresh, IconShield, IconScan,
  FindingCard, CategoryRow, useInView, TrustStrip,
});
