// 공통 컴포넌트

const { useState, useEffect, useMemo, useRef } = React;

// ---- Icons (line icons, 16/20px, currentColor) ----
const Icon = ({ name, size=16 }) => {
  const paths = {
    dashboard: <><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></>,
    timeline: <><path d="M3 12h18"/><circle cx="6" cy="12" r="2"/><circle cx="13" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></>,
    scenario: <><path d="M4 6h6l2 3h8v9H4z"/><path d="M8 13h8"/></>,
    analytics: <><path d="M4 20V10"/><path d="M10 20V4"/><path d="M16 20v-7"/><path d="M22 20H2"/></>,
    kb: <><path d="M4 4h10l4 4v12H4z"/><path d="M14 4v4h4"/><path d="M8 12h6M8 16h6"/></>,
    pipe: <><rect x="3" y="4" width="18" height="6" rx="1.5"/><rect x="3" y="14" width="18" height="6" rx="1.5"/><path d="M8 10v4M16 10v4"/></>,
    xai: <><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/><circle cx="12" cy="12" r="3.5"/></>,
    search: <><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></>,
    filter: <><path d="M4 5h16l-6 8v6l-4-2v-4z"/></>,
    x: <><path d="M6 6l12 12M18 6L6 18"/></>,
    chevron: <><path d="M9 6l6 6-6 6"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.2 4.2l2.1 2.1M17.7 17.7l2.1 2.1M2 12h3M19 12h3M4.2 19.8l2.1-2.1M17.7 6.3l2.1-2.1"/></>,
    alert: <><path d="M12 3l10 18H2z"/><path d="M12 10v5M12 18v.5"/></>,
    check: <><path d="M5 12l5 5L20 6"/></>,
    user: <><circle cx="12" cy="8" r="4"/><path d="M4 20c2-4 5-6 8-6s6 2 8 6"/></>,
    link: <><path d="M10 14a4 4 0 0 0 5.66 0l3-3a4 4 0 1 0-5.66-5.66L12 6"/><path d="M14 10a4 4 0 0 0-5.66 0l-3 3a4 4 0 1 0 5.66 5.66L12 18"/></>,
    shield: <><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z"/></>,
    db: <><ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"/><path d="M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></>,
    clock: <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
    flow: <><path d="M4 6h4l4 12h4M16 6h4"/></>,
  };
  return (
    <svg className="i" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
      {paths[name] || null}
    </svg>
  );
};

const Badge = ({ children, tone="ghost" }) => (
  <span className={"badge " + tone}>{children}</span>
);

const Severity = ({ level }) => (
  <span className="nowrap"><span className={"sev-dot "+level}/>{
    {critical:"Critical", high:"High", medium:"Medium", low:"Low", info:"Info"}[level]
  }</span>
);

const Grade = ({ g }) => {
  if (!g || g === "-") return <span className="muted">—</span>;
  const label = { C: "Common · 공통·일반 업무 데이터", S: "Sensitive · 민감·규제 대상", O: "Open · 외부 공개 가능" }[g];
  return <span className={"grade "+g} title={label}><span className="g-dot"/>{g}</span>;
};

const Source = ({ k }) => {
  const labelMap = { NAC:"NAC", SDP:"SDP", NDR:"AI-NDR", AIGW:"AI GW", DBMS:"DBMS", WORM:"WORM" };
  return <span className={"src "+k}><span className="s-dot"/>{labelMap[k]||k}</span>;
};

// ---- Sparkline SVG ----
const Spark = ({ data, w=120, h=32, color }) => {
  const max = Math.max(...data), min = Math.min(...data);
  const step = w / (data.length-1);
  const pts = data.map((v,i) => [i*step, h - ((v-min)/(max-min||1))*(h-4) - 2]);
  const d = pts.map((p,i) => (i?"L":"M")+p[0].toFixed(1)+" "+p[1].toFixed(1)).join(" ");
  const area = d + ` L ${w} ${h} L 0 ${h} Z`;
  const c = color || "var(--accent)";
  return (
    <svg width={w} height={h} style={{display:"block"}}>
      <path d={area} fill={c} opacity="0.15"/>
      <path d={d} fill="none" stroke={c} strokeWidth="1.5"/>
    </svg>
  );
};

// ---- Donut ----
const Donut = ({ segments, size=120, thickness=16 }) => {
  const r = (size - thickness) / 2;
  const cx = size/2, cy = size/2;
  const total = segments.reduce((a,s)=>a+s.value,0);
  let acc = 0;
  const circ = 2 * Math.PI * r;
  return (
    <svg width={size} height={size}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--surface-2)" strokeWidth={thickness}/>
      {segments.map((s,i) => {
        const frac = s.value / total;
        const dash = circ * frac;
        const offset = circ * (acc / total);
        acc += s.value;
        return (
          <circle key={i} cx={cx} cy={cy} r={r} fill="none" stroke={s.color}
            strokeWidth={thickness}
            strokeDasharray={`${dash} ${circ-dash}`}
            strokeDashoffset={-offset}
            transform={`rotate(-90 ${cx} ${cy})`}
          />
        );
      })}
    </svg>
  );
};

// ---- Stacked hourly bars ----
const StackedBars = ({ data, h=120 }) => {
  const max = Math.max(...data.map(d => d.a+d.m+d.b));
  return (
    <div style={{display:"flex", alignItems:"flex-end", gap:3, height:h}}>
      {data.map((d,i) => {
        const total = d.a+d.m+d.b;
        const H = Math.max(2, (total/max)*h);
        return (
          <div key={i} style={{flex:1, display:"flex", flexDirection:"column", gap:0, height:H, justifyContent:"flex-end"}}>
            <div style={{height: (d.b/total)*H, background:"var(--critical)"}}/>
            <div style={{height: (d.m/total)*H, background:"var(--medium)"}}/>
            <div style={{height: (d.a/total)*H, background:"color-mix(in oklch, var(--low) 70%, transparent)"}}/>
          </div>
        );
      })}
    </div>
  );
};

// ---- KPI Card ----
// 구조: LABEL → VALUE(+unit, nowrap) → DELTA(nowrap) → SPARK
// 카드 폭이 좁아져도 각 줄이 개별적으로 nowrap 처리되어 깨지지 않음.
const KpiCard = ({ kpi }) => (
  <div className="card kpi">
    <div className="label">{kpi.label}</div>
    <div className="value-row">
      <span className="value-num">{kpi.value}</span>
      <span className="value-unit">{kpi.unit}</span>
    </div>
    <div className={"delta " + kpi.dir}>
      <span className="delta-arrow">{kpi.dir==="up"?"▲":"▼"}</span>
      <span className="delta-num">{kpi.delta}</span>
    </div>
    <div className="spark-wrap">
      <Spark data={kpi.spark} w={220} h={32} color={kpi.dir==="up" ? "var(--accent)" : "var(--low)"} />
    </div>
  </div>
);

// ---- Section header ----
const Section = ({ title, meta, right, children, style, bodyStyle, className }) => (
  <div className={"card " + (className||"")} style={style}>
    <div className="card-head">
      <h3>{title} {meta && <span className="meta" style={{marginLeft:6}}>{meta}</span>}</h3>
      {right}
    </div>
    <div style={bodyStyle}>{children}</div>
  </div>
);

// ---- Chain node ----
const ChainNode = ({ n, onClick, active }) => (
  <div className={"chain-node sev-"+n.sev} onClick={onClick} style={active?{outline:"1.5px solid var(--accent)"}:{}}>
    <div className="n-head">
      <Source k={n.src}/>
      <span className="n-time">{n.t}</span>
    </div>
    <div className="n-title">{n.title}</div>
    <div className="n-sub">{n.sub}</div>
  </div>
);

const ChainArrow = () => (
  <div className="chain-arrow">
    <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.5">
      <path d="M4 10h12M12 6l4 4-4 4"/>
    </svg>
  </div>
);

Object.assign(window, { Icon, Badge, Severity, Grade, Source, Spark, Donut, StackedBars, KpiCard, Section, ChainNode, ChainArrow });
