/* =====================================================================
   widgets.jsx — shared presentational components
   ===================================================================== */
const { useState, useEffect, useRef, useMemo } = React;

/* active brand-theme accent (set by App on every render) */
function themeAccent() { return (window.__ffpTheme && window.__ffpTheme.accent) || "#6e8e77"; }
function themeDark() { return (window.__ffpTheme && window.__ffpTheme.dark) || "#1e3735"; }

/* ---------- Icons (inline, stroke=currentColor, Lucide-style) ---------- */
function Icon({ name, size = 16, 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:       <><line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" /></>,
    arrowLeft:   <><line x1="19" y1="12" x2="5" y2="12" /><polyline points="12 19 5 12 12 5" /></>,
    check:       <polyline points="20 6 9 17 4 12" />,
    chevDown:    <polyline points="6 9 12 15 18 9" />,
    lock:        <><rect x="3" y="11" width="18" height="11" rx="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" /></>,
    download:    <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" /></>,
    print:       <><polyline points="6 9 6 2 18 2 18 9" /><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" /><rect x="6" y="14" width="12" height="8" /></>,
    compass:     <><circle cx="12" cy="12" r="10" /><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" /></>,
    alert:       <><circle cx="12" cy="12" r="10" /><line x1="12" y1="8" x2="12" y2="12" /><line x1="12" y1="16" x2="12.01" y2="16" /></>,
    droplet:     <path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />,
    search:      <><circle cx="11" cy="11" r="8" /><line x1="21" y1="21" x2="16.65" y2="16.65" /></>,
    layers:      <><polygon points="12 2 2 7 12 12 22 7 12 2" /><polyline points="2 17 12 22 22 17" /><polyline points="2 12 12 17 22 12" /></>,
    mail:        <><rect x="2" y="4" width="20" height="16" rx="2" /><path d="m22 7-10 5L2 7" /></>,
    clock:       <><circle cx="12" cy="12" r="10" /><polyline points="12 6 12 12 16 14" /></>,
    refresh:     <><polyline points="23 4 23 10 17 10" /><polyline points="1 20 1 14 7 14" /><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" /></>,
    x:           <><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></>,
    eye:         <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" /></>,
    file:        <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /></>,
    spark:       <path d="M12 3l1.9 5.6L19.5 10l-5.6 1.9L12 17.5l-1.9-5.6L4.5 10l5.6-1.4z" />,
    grid:        <><rect x="3" y="3" width="7" height="7" /><rect x="14" y="3" width="7" height="7" /><rect x="14" y="14" width="7" height="7" /><rect x="3" y="14" width="7" height="7" /></>,
    star:        <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />,
  };
  return <svg {...p}>{paths[name]}</svg>;
}

/* ---------- Tracy "T." brandmark ---------- */
function Brandmark({ height = 22, className = "", color }) {
  return (
    <span className={"brandmark " + className} style={{ height, color }}>
      <svg viewBox="0 0 263.98 382.72" style={{ height }}>
        <path d="M0,94.76V12.84L76.42,0v94.76h72.75l-2.45,10.39h-70.3v182.19c0,34.24,14.67,51.97,45.24,51.97,17.73,0,31.18-12.23,36.68-21.4l9.17,5.5c-12.23,28.73-49.52,59.3-90.48,59.3-48.3,0-77.03-19.56-77.03-93.54V94.76Z" />
        <circle cx="233.68" cy="352.41" r="30.31" />
      </svg>
    </span>
  );
}

/* ---------- App top bar ---------- */
function TopBar({ step, right, onHome }) {
  return (
    <header className="topbar">
      <div className="topbar__inner">
        <a className="topbar__id" href="#" onClick={(e) => { e.preventDefault(); onHome && onHome(); }}>
          <Brandmark height={28} />
          <span className="topbar__name">The Freedom Filled<span className="reg">&reg;</span> <b>Pathway Audit</b></span>
        </a>
        <div className="topbar__step">
          {step && <span className="topbar__meta">{step}</span>}
          {right}
        </div>
      </div>
    </header>
  );
}

/* ---------- Button ---------- */
function Btn({ as = "button", variant = "", icon, iconLeft, children, className = "", ...rest }) {
  const Tag = as;
  const cls = "btn " + (variant ? variant.split(" ").map(v => "btn--" + v).join(" ") : "") + " " + className;
  return (
    <Tag className={cls} {...rest}>
      {iconLeft && <Icon name={iconLeft} size={15} />}
      {children}
      {icon && <Icon name={icon} size={15} />}
    </Tag>
  );
}

/* =====================================================================
   RADAR CHART — the dimension map
   ===================================================================== */
function RadarChart({ scores, size = 380, accent, ink, labels = true, animate = true }) {
  accent = accent || themeAccent();
  ink = ink || themeDark();
  const dims = window.FFP.DIMENSIONS;
  const n = dims.length;
  const cx = size / 2, cy = size / 2;
  const PAD = labels ? 56 : 8;
  const R = size / 2 - (labels ? 50 : 16);
  const [grown, setGrown] = useState(!animate);
  useEffect(() => { if (animate) { const t = setTimeout(() => setGrown(true), 120); return () => clearTimeout(t); } }, [animate]);

  const angle = (i) => (Math.PI * 2 * i) / n - Math.PI / 2;
  const pt = (i, r) => [cx + Math.cos(angle(i)) * r, cy + Math.sin(angle(i)) * r];
  const rings = [0.25, 0.5, 0.75, 1];

  const valuePts = dims.map((d, i) => {
    const v = (scores[d.key] || 0) / 100;
    const r = grown ? R * v : 0;
    return pt(i, r);
  });
  const poly = valuePts.map(p => p.join(",")).join(" ");

  return (
    <svg viewBox={`${-PAD} -8 ${size + PAD * 2} ${size + 16}`} width="100%" style={{ maxWidth: size + PAD * 2 }} role="img" aria-label="Dimension map radar chart">
      {/* grid rings */}
      {rings.map((rr, ri) => (
        <polygon key={ri}
          points={dims.map((_, i) => pt(i, R * rr).join(",")).join(" ")}
          fill="none" stroke={ink} strokeOpacity={ri === rings.length - 1 ? 0.22 : 0.1} strokeWidth="1" />
      ))}
      {/* spokes */}
      {dims.map((_, i) => {
        const [x, y] = pt(i, R);
        return <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke={ink} strokeOpacity="0.1" strokeWidth="1" />;
      })}
      {/* value polygon */}
      <polygon points={poly} fill={accent} fillOpacity="0.18" stroke={accent} strokeWidth="2"
        style={{ transition: "all 1s cubic-bezier(.22,1,.36,1)" }} />
      {/* value dots */}
      {valuePts.map((p, i) => {
        const sev = window.FFP.severityFor(scores[dims[i].key]);
        const col = sev.key === "active" ? "#b4493b" : sev.key === "watch" ? "#c9a46c" : accent;
        return <circle key={i} cx={p[0]} cy={p[1]} r="4.5" fill={col} stroke="#fff" strokeWidth="1.5"
          style={{ transition: "all 1s cubic-bezier(.22,1,.36,1)" }} />;
      })}
      {/* labels */}
      {labels && dims.map((d, i) => {
        const [lx, ly] = pt(i, R + 26);
        const a = Math.cos(angle(i));
        const anchor = Math.abs(a) < 0.3 ? "middle" : a > 0 ? "start" : "end";
        const sev = window.FFP.severityFor(scores[d.key]);
        const col = sev.key === "active" ? "#b4493b" : ink;
        return (
          <g key={i}>
            <text x={lx} y={ly - 4} textAnchor={anchor} fontFamily="Poppins, sans-serif" fontSize="11" fontWeight="500"
              letterSpacing="0.04em" fill={col}>{d.short}</text>
            <text x={lx} y={ly + 11} textAnchor={anchor} fontFamily="'Editors Note', Georgia, serif" fontSize="15" fill={ink}>{scores[d.key]}</text>
          </g>
        );
      })}
    </svg>
  );
}

/* =====================================================================
   SCORE DIAL — circular gauge for overall score
   ===================================================================== */
function ScoreDial({ score, size = 220, stroke = 14, accent, track = "rgba(16,16,16,0.08)", ink, animate = true, band }) {
  accent = accent || themeAccent();
  ink = ink || themeDark();
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const [val, setVal] = useState(animate ? 0 : score);
  useEffect(() => { if (animate) { const t = setTimeout(() => setVal(score), 150); return () => clearTimeout(t); } }, [score, animate]);
  const off = c - (val / 100) * c;
  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={track} strokeWidth={stroke} />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={accent} strokeWidth={stroke}
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={off}
          style={{ transition: "stroke-dashoffset 1.1s cubic-bezier(.22,1,.36,1)" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        <div>
          <div style={{ fontFamily: "'Editors Note', Georgia, serif", fontSize: size * 0.34, lineHeight: 1, color: ink }}>{Math.round(val)}</div>
          <div style={{ fontFamily: "Poppins, sans-serif", fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--ink-mute)", marginTop: 4 }}>out of 100</div>
        </div>
      </div>
    </div>
  );
}

/* ---------- Dimension bars ---------- */
function DimensionBars({ scores, accent = "#1e3735", animate = true }) {
  const ranked = window.FFP.rankedDims(scores);
  const [grown, setGrown] = useState(!animate);
  useEffect(() => { if (animate) { const t = setTimeout(() => setGrown(true), 150); return () => clearTimeout(t); } }, [animate]);
  return (
    <div className="dim-list">
      {ranked.map((d) => {
        const sev = window.FFP.severityFor(d.score);
        const col = sev.key === "active" ? "#b4493b" : sev.key === "watch" ? "#c9a46c" : themeAccent();
        return (
          <div className="dim-row" key={d.key}>
            <div className="dim-row__name"><span className={"severity-dot " + sev.cls}></span>{d.leak}</div>
            <div className="dim-row__score">{d.score}</div>
            <div className="dim-row__track"><div className="dim-row__fill" style={{ width: (grown ? d.score : 0) + "%", background: col }} /></div>
          </div>
        );
      })}
    </div>
  );
}

/* ---------- Band scale (visual position of score across 4 bands) ---------- */
function BandScale({ score, compact }) {
  const bands = window.FFP.BANDS;
  return (
    <div>
      <div style={{ display: "flex", height: compact ? 8 : 10, borderRadius: 999, overflow: "hidden", position: "relative" }}>
        {bands.map((b, i) => {
          const active = score >= b.min && score <= b.max;
          return <div key={b.key} style={{ flex: b.max - b.min + (i===0?1:0), background: active ? themeDark() : "rgba(30,55,53,0.16)" }} />;
        })}
        <div style={{ position: "absolute", top: -3, bottom: -3, left: `calc(${score}% - 1px)`, width: 2, background: themeDark() }} />
      </div>
      {!compact && (
        <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8, fontFamily: "Poppins, sans-serif", fontSize: 10, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-mute)" }}>
          {bands.map(b => <span key={b.key}>{b.min}</span>)}<span>100</span>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Icon, Brandmark, TopBar, Btn, RadarChart, ScoreDial, DimensionBars, BandScale });
