/* =============================================================================
   분석 뷰 (문서 §8.3 · §6.1)
   -----------------------------------------------------------------------------
   §8.3 "사용자·세션·데이터 중심 뷰" — 4개 탭으로 구성:
     user     사용자/단말 뷰: 사용자별 최근 활동, 인증 실패 추이, 단말 무결성,
                             정책 위반 이력
     session  세션 뷰:        특정 세션의 NAC→SDP→NDR→DB→AI GW→Storage 타임라인
     grade    데이터 등급 뷰: C/S/O별 접근 추이, 외부 전송 시도, 차단·반복 패턴
     service  서비스 뷰:      생성형 AI 서비스별 호출량, 차단 유형, 부서별 이용

   탭 전환은 §6.1 "상관분석 관점" 5개 축 중 네 축(사용자/단말/세션, 데이터,
     정책, 서비스)과 대응. 네트워크·저장/무결성 축은 대시보드·시나리오 뷰와
     타임라인에서 교차 확인.
============================================================================= */

const AnalyticsView = () => {
  const M = window.MOCK;
  const [tab, setTab] = useState("user");

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1>분석 뷰</h1>
          <div className="sub">사용자·세션·데이터·서비스 관점의 상관분석 · 기간: 최근 7일</div>
        </div>
      </div>

      <div className="tabs">
        {[
          {k:"user", l:"사용자 · 단말"},
          {k:"session", l:"세션"},
          {k:"data", l:"데이터 등급"},
          {k:"service", l:"서비스"},
        ].map(t => (
          <button key={t.k} className={"tab "+(tab===t.k?"active":"")} onClick={()=>setTab(t.k)}>{t.l}</button>
        ))}
      </div>

      {tab==="user" && <UserTab users={M.users}/>}
      {tab==="session" && <SessionTab/>}
      {tab==="data" && <DataTab grades={M.grades}/>}
      {tab==="service" && <ServiceTab ai={M.aiCalls}/>}
    </div>
  );
};

const UserTab = ({ users }) => {
  // 각 요약 카드에 "구성 preview"를 함께 보여 — 단순 숫자가 아니라 실제 구성원/항목이 무엇인지 즉시 인지 가능.
  const highRisk = users.filter(u => u.risk >= 60).sort((a,b)=>b.risk-a.risk);
  return (
  <>
    <div className="grid grid-3 dash-gap">
      <AnalyticsPreviewCard
        label="고위험 사용자(상위)"
        value={highRisk.length}
        hint="위험 스코어 60 이상"
      >
        <div className="preview-list">
          {highRisk.slice(0,3).map(u => (
            <div key={u.id} className="preview-row">
              <span className="preview-avatar" style={{background: u.risk>=70?"var(--critical)":"var(--medium)"}}>
                {u.name.slice(0,1)}
              </span>
              <div className="preview-body">
                <div className="preview-name">{u.name}<span className="mono small muted"> · {u.id}</span></div>
                <div className="preview-sub">{u.dept}</div>
              </div>
              <span className="mono small preview-score" style={{color: u.risk>=70?"var(--critical)":"var(--medium)"}}>{u.risk}</span>
            </div>
          ))}
        </div>
      </AnalyticsPreviewCard>

      <AnalyticsPreviewCard
        label="단말 무결성 이상"
        value={3}
        hint="패치 누락 / EDR 미설치"
      >
        <div className="preview-list">
          {[
            {dev:"WKS-0C41", issue:"EDR 에이전트 미설치", sev:"critical"},
            {dev:"WKS-2F17", issue:"OS 패치 30일 경과", sev:"high"},
            {dev:"MBP-KM09", issue:"디스크 암호화 비활성", sev:"high"},
          ].map(d => (
            <div key={d.dev} className="preview-row">
              <span className={"preview-icon sev-"+d.sev}><Icon name="shield" size={12}/></span>
              <div className="preview-body">
                <div className="preview-name mono">{d.dev}</div>
                <div className="preview-sub">{d.issue}</div>
              </div>
            </div>
          ))}
        </div>
      </AnalyticsPreviewCard>

      <AnalyticsPreviewCard
        label="반복 정책 위반 사용자"
        value={2}
        hint="7일 누적 3회 이상"
      >
        <div className="preview-list">
          {[
            {n:"정민재", id:"jm.jung", pattern:"AIGW S등급 차단", count:7},
            {n:"서원호", id:"wh.seo", pattern:"WORM 대량 쓰기", count:4},
          ].map(p => (
            <div key={p.id} className="preview-row">
              <span className="preview-avatar" style={{background:"var(--medium)"}}>{p.n.slice(0,1)}</span>
              <div className="preview-body">
                <div className="preview-name">{p.n}<span className="mono small muted"> · {p.id}</span></div>
                <div className="preview-sub">{p.pattern}</div>
              </div>
              <span className="mono small preview-score" style={{color:"var(--high)"}}>×{p.count}</span>
            </div>
          ))}
        </div>
      </AnalyticsPreviewCard>
    </div>

    <Section title="사용자 위험도 랭킹" meta="행동 기반 스코어(0~100)">
      <table className="tbl">
        <thead>
          <tr><th>사용자</th><th>소속</th><th style={{width:200}}>위험 스코어</th><th>이벤트</th><th>최근 활동</th><th>플래그</th></tr>
        </thead>
        <tbody>
          {users.sort((a,b)=>b.risk-a.risk).map(u => (
            <tr key={u.id}>
              <td>
                <div>{u.name}</div>
                <div className="mono small muted">{u.id}</div>
              </td>
              <td className="text-2">{u.dept}</td>
              <td>
                <div className="row gap-8">
                  <div className="hbar" style={{flex:1}}>
                    <span style={{width:u.risk+"%", background: u.risk>=70?"var(--critical)":u.risk>=40?"var(--medium)":"var(--low)"}}/>
                  </div>
                  <span className="mono small" style={{width:28, textAlign:"right"}}>{u.risk}</span>
                </div>
              </td>
              <td className="mono">{u.events}</td>
              <td className="mono small">{u.last}</td>
              <td>
                <div className="row gap-4" style={{flexWrap:"wrap"}}>
                  {u.flags.length===0 ? <span className="muted">—</span> :
                    u.flags.map(f => <span key={f} className="badge high">{f}</span>)}
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </Section>
  </>
  );
};

// ============================================================================
// 세션 탭 — 좌측 세션 목록에서 선택, 우측 상세 표시
// 기존 구조(특정 세션 타임라인을 바로 노출)는 "왜 이 세션을 보고 있는지, 다른 세션은 어떻게 고르는지"
// 가 불명확하다는 피드백을 반영. 최근/진행 중 세션 목록 → 드릴다운 2단계 패턴으로 변경.
// ============================================================================
const SESSIONS = [
  {
    id: "SES-4192",
    user: {name:"정민재", id:"jm.jung"},
    device: "WKS-0C41",
    dept: "여신심사본부",
    start: "14:20", end: "14:36",
    duration: "16분",
    status: "격리됨",
    statusSev: "critical",
    risk: 82,
    events: 7,
    trust: 0.24,
    summary: "S등급 조회 후 외부 LLM 프롬프트 차단 · NDR 비정상 통신 감지",
  },
  {
    id: "SES-4188",
    user: {name:"박서진", id:"sj.park"},
    device: "WKS-18E2",
    dept: "디지털사업본부",
    start: "13:52", end: "14:11",
    duration: "19분",
    status: "진행 중",
    statusSev: "medium",
    risk: 54,
    events: 4,
    trust: 0.58,
    summary: "사내 LLM 이용 중 · 차단 1건 (S등급 포함 쿼리)",
  },
  {
    id: "SES-4183",
    user: {name:"이하늘", id:"hn.lee"},
    device: "MBP-KM09",
    dept: "마케팅본부",
    start: "13:40", end: "14:02",
    duration: "22분",
    status: "정상 종료",
    statusSev: "low",
    risk: 18,
    events: 2,
    trust: 0.86,
    summary: "정책 매칭 정상 · 차단 없음",
  },
  {
    id: "SES-4176",
    user: {name:"서원호", id:"wh.seo"},
    device: "WKS-2F17",
    dept: "개인금융본부",
    start: "13:18", end: "13:45",
    duration: "27분",
    status: "경고 후 종료",
    statusSev: "high",
    risk: 71,
    events: 5,
    trust: 0.41,
    summary: "WORM 대량 쓰기 시도 · 단말 무결성 경고",
  },
  {
    id: "SES-4168",
    user: {name:"공용.분석A", id:"svc.analyst-a"},
    device: "SRV-0431",
    dept: "공용계정",
    start: "12:55", end: "13:10",
    duration: "15분",
    status: "정상 종료",
    statusSev: "low",
    risk: 32,
    events: 3,
    trust: 0.72,
    summary: "배치 분석 · DBMS 조회 다수, 정책 매칭 정상",
  },
];

const SESSION_TIMELINES = {
  "SES-4192": [
    {t:"14:21:08", src:"NAC", title:"인증 성공 · 단말 무결성 OK", sev:"info"},
    {t:"14:21:14", src:"SDP", title:"내부 DB망 세션 생성", sev:"info"},
    {t:"14:22:41", src:"DBMS", title:"S등급 고객정보 7,421건 조회", sev:"medium"},
    {t:"14:26:02", src:"AIGW", title:"외부 LLM 프롬프트 차단", sev:"critical"},
    {t:"14:27:33", src:"NDR", title:"비정상 외부 도메인 통신", sev:"high"},
    {t:"14:28:10", src:"WORM", title:"WORM 저장 시도 차단", sev:"medium"},
    {t:"14:35:41", src:"SDP", title:"세션 자동 격리", sev:"info"},
  ],
  "SES-4188": [
    {t:"13:52:04", src:"NAC", title:"인증 성공", sev:"info"},
    {t:"13:53:12", src:"SDP", title:"사내 LLM 세션 생성", sev:"info"},
    {t:"13:58:40", src:"AIGW", title:"S등급 포함 쿼리 차단", sev:"medium"},
    {t:"14:05:22", src:"AIGW", title:"재시도 허용 (마스킹)", sev:"info"},
  ],
  "SES-4183": [
    {t:"13:40:55", src:"NAC", title:"인증 성공", sev:"info"},
    {t:"13:52:14", src:"AIGW", title:"캠페인 초안 생성 · 정상", sev:"info"},
  ],
  "SES-4176": [
    {t:"13:18:02", src:"NAC", title:"인증 성공 (무결성 경고)", sev:"medium"},
    {t:"13:19:44", src:"SDP", title:"파일공유망 세션 생성", sev:"info"},
    {t:"13:32:08", src:"WORM", title:"대량 쓰기 시도 (2.1GB)", sev:"high"},
    {t:"13:41:17", src:"WORM", title:"패턴 임계치 초과 · 차단", sev:"high"},
    {t:"13:44:51", src:"SDP", title:"경고 후 세션 종료", sev:"medium"},
  ],
  "SES-4168": [
    {t:"12:55:30", src:"NAC", title:"서비스계정 인증 성공", sev:"info"},
    {t:"12:56:08", src:"DBMS", title:"배치 조회 시작", sev:"info"},
    {t:"13:09:44", src:"SDP", title:"세션 정상 종료", sev:"info"},
  ],
};

const SessionTab = () => {
  const [selId, setSelId] = useState(SESSIONS[0].id);
  const sel = SESSIONS.find(s => s.id === selId);
  const timeline = SESSION_TIMELINES[selId] || [];
  return (
    <div className="grid dash-gap" style={{gridTemplateColumns:"minmax(260px, 320px) minmax(0, 1fr)", alignItems:"start"}}>
      {/* 좌: 세션 목록 */}
      <Section title="최근 세션" meta={`${SESSIONS.length}건 · 최근 2시간`}>
        <div style={{margin:"-4px -4px 0"}}>
          {SESSIONS.map(s => {
            const active = s.id === selId;
            return (
              <button key={s.id} onClick={()=>setSelId(s.id)}
                style={{
                  display:"block", width:"100%", textAlign:"left", padding:"10px 10px", borderRadius:"var(--r-md)", marginBottom:4,
                  background: active ? "color-mix(in oklch, var(--accent) 14%, transparent)" : "transparent",
                  border:"1px solid " + (active ? "color-mix(in oklch, var(--accent) 40%, transparent)" : "transparent"),
                  cursor:"pointer", color:"inherit"
                }}
                onMouseEnter={e=>{ if(!active) e.currentTarget.style.background="var(--surface-2)"; }}
                onMouseLeave={e=>{ if(!active) e.currentTarget.style.background="transparent"; }}
              >
                <div className="row between" style={{marginBottom:4}}>
                  <span className="mono small" style={{color: active?"var(--text)":"var(--text-3)"}}>{s.id}</span>
                  <span className={"badge "+s.statusSev} style={{fontSize:11}}>{s.status}</span>
                </div>
                <div style={{fontSize:13.5, fontWeight:500, marginBottom:3}}>{s.user.name} <span className="mono small muted">· {s.user.id}</span></div>
                <div className="small muted" style={{marginBottom:6}}>{s.dept} · {s.device}</div>
                <div className="row between small">
                  <span className="mono" style={{color:"var(--text-3)"}}>{s.start}~{s.end}</span>
                  <span className="row gap-8">
                    <span style={{color: s.risk>=70?"var(--critical)":s.risk>=50?"var(--high)":"var(--text-3)"}}>위험 {s.risk}</span>
                    <span className="muted">· {s.events}건</span>
                  </span>
                </div>
              </button>
            );
          })}
        </div>
      </Section>

      {/* 우: 선택 세션 상세 */}
      <div>
        <Section
          title={<span>세션 타임라인 <span className="mono small muted" style={{marginLeft:8}}>{sel.id}</span></span>}
          meta={`${sel.user.name} (${sel.user.id}) / ${sel.device} · ${sel.start}~${sel.end} (${sel.duration})`}
          right={<span className={"badge "+sel.statusSev}>{sel.status}</span>}
          style={{marginBottom:12}}
        >
          <div className="small" style={{marginBottom:12, padding:"8px 10px", background:"var(--surface-2)", borderRadius:"var(--r-sm)", color:"var(--text-2)"}}>{sel.summary}</div>
          <div style={{position:"relative", paddingLeft:140}}>
            {timeline.map((e,i) => (
              <div key={i} style={{position:"relative", padding:"10px 0 10px 30px", borderLeft:"1px dashed var(--border-2)", marginLeft:1}}>
                <span style={{position:"absolute", left:-125, top:12, fontFamily:"var(--font-mono)", fontSize:12, color:"var(--text-3)", width:100, textAlign:"right"}}>{e.t}</span>
                <span style={{position:"absolute", left:-5, top:14, width:10, height:10, borderRadius:"50%", background:`var(--${e.sev})`, border:"2px solid var(--bg)"}}/>
                <div className="row gap-8" style={{marginBottom:4}}>
                  <Source k={e.src}/>
                  <Severity level={e.sev}/>
                </div>
                <div style={{fontSize:13.5}}>{e.title}</div>
              </div>
            ))}
          </div>
        </Section>

        <div className="grid grid-2">
          <Section title="세션 신뢰도 추이" meta="SDP 지속 평가">
            <div className="row between mb-12">
              <span className="small muted">현재 신뢰 스코어</span>
              <span className="mono" style={{fontSize:22, fontWeight:600, color: sel.trust<0.4?"var(--critical)":sel.trust<0.7?"var(--medium)":"var(--low)"}}>{sel.trust.toFixed(2)}</span>
            </div>
            <div className="hbar" style={{height:8, marginBottom:14}}>
              <span style={{width:(sel.trust*100)+"%", background: sel.trust<0.4?"var(--critical)":sel.trust<0.7?"var(--medium)":"var(--low)"}}/>
            </div>
            <svg viewBox="0 0 300 90" width="100%" height="90" style={{display:"block"}}>
              <line x1="0" y1="60" x2="300" y2="60" stroke="var(--border-2)" strokeDasharray="2 3"/>
              <polyline fill="none" stroke="var(--info)" strokeWidth="1.6" vectorEffect="non-scaling-stroke"
                points={timeline.map((e,i) => {
                  const x = (i / Math.max(1, timeline.length-1)) * 300;
                  const drop = {info:0, low:-4, medium:-14, high:-22, critical:-34}[e.sev] || 0;
                  const y = 20 - drop;
                  return `${x},${y}`;
                }).join(" ")}/>
              {timeline.map((e,i) => {
                const x = (i / Math.max(1, timeline.length-1)) * 300;
                const drop = {info:0, low:-4, medium:-14, high:-22, critical:-34}[e.sev] || 0;
                const y = 20 - drop;
                return <circle key={i} cx={x} cy={y} r="3" fill={`var(--${e.sev})`}/>;
              })}
            </svg>
            <div className="row between small muted" style={{marginTop:4}}>
              <span className="mono">{sel.start}</span>
              <span className="mono">{sel.end}</span>
            </div>
          </Section>

          <Section title="정책 매칭 현황" meta="해당 세션 기준">
            {[
              {p:"P-INT-DB-03", m:812, b:3},
              {p:"P-GAI-S-01", m:214, b:184},
              {p:"P-EXT-WEB-02", m:602, b:12},
              {p:"EX-PATH-02", m:8, b:6},
              {p:"STG-WORM-01", m:128, b:128},
            ].map(r => (
              <div key={r.p} className="row between" style={{padding:"6px 0", borderBottom:"1px solid var(--border)"}}>
                <span className="mono small">{r.p}</span>
                <div className="row gap-12">
                  <span className="small"><span className="muted">매칭</span> <b className="mono">{r.m}</b></span>
                  <span className="badge critical">차단 {r.b}</span>
                </div>
              </div>
            ))}
          </Section>
        </div>
      </div>
    </div>
  );
};

// ============================================================================
// 데이터 등급 탭 — C/S/O selector로 선택 후 해당 등급의 상세 포커스
// 기존: 세 등급 요약 + S등급 흐름 고정 노출 → 어느 등급을 분석할지 선택 불가.
// 개선: 상단 selector(전체 / C / S / O)로 "보고 싶은 등급"을 명시. 각 등급별로
//       흐름(chain)·추이·반복 패턴을 다르게 보여줌.
// ============================================================================
const GRADE_META = {
  all: {label:"전체 등급", desc:"C·S·O 등급 종합 흐름", color:"var(--text-2)"},
  C:   {label:"Common",    desc:"공통·일반 업무 데이터", color:"var(--grade-c)"},
  S:   {label:"Sensitive", desc:"민감·규제 대상 데이터", color:"var(--grade-s)"},
  O:   {label:"Open",      desc:"외부 공개 허용 데이터", color:"var(--grade-o)"},
};

const GRADE_FLOWS = {
  all: [
    {src:"DBMS", title:"전체 조회",     sub:"C 142K / S 7.4K / O 3.1K", sev:"info",    t:"관측"},
    {src:"SDP",  title:"세션 교차",     sub:"내부 ↔ 경계 이동 4.2K건", sev:"info",    t:"이동"},
    {src:"AIGW", title:"AI 전송 판정",  sub:"허용 4.26M · 마스킹 1.1K · 차단 48",  sev:"medium",  t:"판정"},
    {src:"WORM", title:"저장 · 무결성", sub:"격리 18건 · 차단 12건",   sev:"high",    t:"격리"},
  ],
  C: [
    {src:"DBMS", title:"일반 조회",   sub:"142,308건 / 세션 812개",    sev:"info", t:"관측"},
    {src:"SDP",  title:"내부 이동",   sub:"세션 교차 정상 범위",       sev:"info", t:"이동"},
    {src:"AIGW", title:"AI 전송 허용",sub:"4,256,120건 허용 · 차단 0", sev:"info", t:"판정"},
  ],
  S: [
    {src:"DBMS", title:"S등급 조회",     sub:"7,421건 / 12건의 세션",  sev:"medium",   t:"관측"},
    {src:"SDP",  title:"내부 → 경계",    sub:"세션 교차 12건",         sev:"info",     t:"이동"},
    {src:"AIGW", title:"외부 전송 시도", sub:"18건 중 18건 차단",      sev:"critical", t:"판정"},
    {src:"WORM", title:"로컬 저장 시도", sub:"6건 중 6건 차단",        sev:"high",     t:"격리"},
  ],
  O: [
    {src:"DBMS", title:"공개 데이터 조회", sub:"3,128건",              sev:"info", t:"관측"},
    {src:"AIGW", title:"외부 전송 허용",   sub:"정책 매칭 정상",       sev:"info", t:"판정"},
  ],
};

const GRADE_PATTERNS = {
  all: [
    {p:"여신심사본부 → 외부 LLM 프롬프트",  n:7, trend:"증가"},
    {p:"공용계정 야간 인증 실패",           n:5, trend:"유지"},
    {p:"S등급 조회 후 파일 다운로드",       n:3, trend:"증가"},
    {p:"단말 무결성 경고 반복",             n:3, trend:"감소"},
  ],
  C: [
    {p:"영업일 업무시간 외 일반 조회 증가", n:12, trend:"증가"},
    {p:"재직자 이탈 부서 집중 접근",        n:6,  trend:"유지"},
  ],
  S: [
    {p:"여신심사본부 → 외부 LLM 프롬프트",  n:7, trend:"증가"},
    {p:"S등급 조회 후 파일 다운로드",       n:3, trend:"증가"},
    {p:"S등급 대량 조회 후 WORM 쓰기",      n:2, trend:"유지"},
  ],
  O: [
    {p:"외부 공개 API 비정상 호출 패턴", n:2, trend:"감소"},
  ],
};

const DataTab = ({ grades }) => {
  const [sel, setSel] = useState("S");
  const meta = GRADE_META[sel];
  const flow = GRADE_FLOWS[sel];
  const patterns = GRADE_PATTERNS[sel];

  return (
  <>
    {/* 등급 selector — 상단 뱃지 토글. 선택된 등급을 명확히 표시. */}
    <div className="card" style={{marginBottom:12, padding:"14px 16px"}}>
      <div className="row between" style={{flexWrap:"wrap", gap:12}}>
        <div className="row gap-8" style={{alignItems:"center"}}>
          <span className="small muted" style={{marginRight:4}}>등급 필터</span>
          {["all","C","S","O"].map(g => {
            const m = GRADE_META[g];
            const active = g === sel;
            return (
              <button key={g} onClick={()=>setSel(g)}
                style={{
                  padding:"6px 12px", borderRadius:"var(--r-sm)", cursor:"pointer",
                  background: active ? "color-mix(in oklch, "+m.color+" 18%, var(--surface-2))" : "var(--surface-2)",
                  border:"1px solid " + (active ? m.color : "var(--border)"),
                  color: active ? "var(--text)" : "var(--text-3)",
                  fontSize:12.5, fontWeight: active?600:500, display:"inline-flex", alignItems:"center", gap:6,
                }}
              >
                {g !== "all" && <span style={{width:8, height:8, borderRadius:"50%", background:m.color, display:"inline-block"}}/>}
                {g === "all" ? <span>전체</span> : <><span>{g}</span> <span className="small muted" style={{fontWeight:400}}>{m.label}</span></>}
              </button>
            );
          })}
        </div>
        <div className="small muted">{meta.desc}</div>
      </div>
    </div>

    {/* 등급별 요약 3카드는 "전체" 선택 시만 표시. 특정 등급 선택 시엔 해당 등급 한 장으로 확대. */}
    {sel === "all" ? (
      <div className="grid grid-3 dash-gap">
        {["C","S","O"].map(g => {
          const v = grades[g];
          const m = GRADE_META[g];
          return (
            <div key={g} className="card" style={{cursor:"pointer"}} onClick={()=>setSel(g)}>
              <div className="row between mb-8">
                <Grade g={g}/>
                <span className="small muted">{m.label}</span>
              </div>
              <div className="mono" style={{fontSize:26, fontWeight:600}}>{v}%</div>
              <div className="small muted" style={{marginTop:4}}>{m.desc}</div>
              <div className="hbar" style={{marginTop:10}}>
                <span style={{width:v+"%", background:m.color}}/>
              </div>
            </div>
          );
        })}
      </div>
    ) : (
      <div className="card" style={{marginBottom:0}}>
        <div className="row between mb-12">
          <div className="row gap-12" style={{alignItems:"center"}}>
            <Grade g={sel}/>
            <div>
              <div style={{fontSize:15, fontWeight:600}}>{meta.label}</div>
              <div className="small muted">{meta.desc}</div>
            </div>
          </div>
          <div style={{textAlign:"right"}}>
            <div className="mono" style={{fontSize:28, fontWeight:600, color:meta.color}}>{grades[sel]}%</div>
            <div className="small muted">전체 데이터 흐름 중 비중</div>
          </div>
        </div>
        <div className="hbar" style={{height:8}}>
          <span style={{width:grades[sel]+"%", background:meta.color}}/>
        </div>
      </div>
    )}

    <Section title={(sel==="all"?"":meta.label+" · ") + "데이터 흐름"} meta="최근 24시간" style={{marginTop:12, marginBottom:12}}>
      <div className="chain">
        {flow.map((n,i) => (
          <React.Fragment key={i}>
            <div className={"chain-node sev-"+n.sev}>
              <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>
            {i<flow.length-1 && <ChainArrow/>}
          </React.Fragment>
        ))}
      </div>
    </Section>

    <div className="grid grid-2">
      <Section title={(sel==="all"?"등급별":(meta.label+" 등급"))+" 접근 · 차단 추이"}>
        <div style={{height:180, display:"flex", alignItems:"flex-end", gap:6}}>
          {Array.from({length:24}).map((_,i) => {
            // 선택된 등급에 맞게 막대 구성이 달라지도록.
            const seed = (i+1) * (sel==="C"?1.1:sel==="S"?0.6:sel==="O"?0.3:1);
            const c = sel==="all" || sel==="C" ? 40 + ((seed*7)%40) : 0;
            const s = sel==="all" || sel==="S" ? 10 + ((seed*5)%20) : 0;
            const o = sel==="all" || sel==="O" ? 6 + ((seed*3)%12) : 0;
            const b = sel==="O" ? 0 : ((seed*2)%(sel==="S"?6:3));
            return (
              <div key={i} style={{flex:1, display:"flex", flexDirection:"column", justifyContent:"flex-end", gap:1}}>
                {b>0 && <div style={{height:b*4, background:"var(--critical)"}}/>}
                {s>0 && <div style={{height:s*2, background:"var(--grade-s)"}}/>}
                {o>0 && <div style={{height:o*2, background:"var(--grade-o)", opacity:0.7}}/>}
                {c>0 && <div style={{height:c, background:"var(--grade-c)", opacity:0.6}}/>}
              </div>
            );
          })}
        </div>
        <div className="row gap-12 small" style={{marginTop:8}}>
          {(sel==="all" || sel==="C") && <span><span className="sev-dot" style={{background:"var(--grade-c)"}}/>C 접근</span>}
          {(sel==="all" || sel==="S") && <span><span className="sev-dot" style={{background:"var(--grade-s)"}}/>S 접근</span>}
          {(sel==="all" || sel==="O") && <span><span className="sev-dot" style={{background:"var(--grade-o)"}}/>O 접근</span>}
          {sel !== "O" && <span><span className="sev-dot critical"/>차단</span>}
        </div>
      </Section>

      <Section title={(sel==="all"?"":meta.label+" · ") + "반복 발생 패턴"} meta={`${patterns.length}건`}>
        {patterns.length === 0 ? (
          <div className="small muted" style={{padding:"20px 0", textAlign:"center"}}>해당 등급의 반복 패턴이 감지되지 않았습니다.</div>
        ) : patterns.map((r,i) => (
          <div key={i} className="row between" style={{padding:"10px 0", borderBottom:i<patterns.length-1?"1px solid var(--border)":"none"}}>
            <div>
              <div style={{fontSize:13.5}}>{r.p}</div>
              <div className="small muted">7일 누적 {r.n}회</div>
            </div>
            <span className={"badge "+(r.trend==="증가"?"critical":r.trend==="감소"?"low":"ghost")}>{r.trend}</span>
          </div>
        ))}
      </Section>
    </div>
  </>
  );
};

const ServiceTab = ({ ai }) => (
  <>
    <Section title="생성형 AI 서비스별 이용 · 차단" style={{marginBottom:12}}>
      <table className="tbl">
        <thead>
          <tr><th>서비스</th><th style={{width:120}}>호출</th><th style={{width:120}}>차단</th><th>차단 비율</th><th style={{width:160}}>주요 차단 사유</th></tr>
        </thead>
        <tbody>
          {ai.services.map(s => {
            const rate = (s.block/s.calls*100);
            const reason = ["S등급 포함","개인정보 감지","외부 전송 금지","민감 키워드"][Math.floor(Math.random()*4)];
            return (
              <tr key={s.name}>
                <td style={{fontWeight:500}}>{s.name}</td>
                <td className="mono">{s.calls.toLocaleString()}</td>
                <td className="mono" style={{color:"var(--critical)"}}>{s.block}</td>
                <td>
                  <div className="row gap-8">
                    <div className="hbar" style={{flex:1}}>
                      <span style={{width:(rate*5)+"%", background:"var(--critical)"}}/>
                    </div>
                    <span className="mono small" style={{width:36, textAlign:"right"}}>{rate.toFixed(2)}%</span>
                  </div>
                </td>
                <td className="small text-2">{reason}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </Section>

    <div className="grid grid-2">
      <Section title="부서별 생성형 AI 이용 패턴">
        {[
          {d:"여신심사본부", c:2410, b:64, r:"심사보고서 요약"},
          {d:"개인금융본부", c:1820, b:22, r:"상담 스크립트"},
          {d:"디지털사업본부", c:3240, b:48, r:"코드 리뷰·문서화"},
          {d:"마케팅본부", c:1680, b:14, r:"캠페인 초안"},
          {d:"감사본부", c:460, b:2, r:"규정 질의"},
        ].map((r,i) => (
          <div key={i} style={{padding:"10px 0", borderBottom:i<4?"1px solid var(--border)":"none"}}>
            <div className="row between mb-8">
              <span style={{fontSize:13.5, fontWeight:500}}>{r.d}</span>
              <span className="small muted">{r.r}</span>
            </div>
            <div className="row gap-8">
              <div className="hbar" style={{flex:1}}>
                <span style={{width:(r.c/35)+"%"}}/>
              </div>
              <span className="mono small nowrap">{r.c.toLocaleString()}</span>
              <span className="badge critical">{r.b}</span>
            </div>
          </div>
        ))}
      </Section>

      <Section title="차단 사유 분류">
        <div style={{display:"flex", alignItems:"center", gap:20}}>
          <Donut segments={[
            {value:62, color:"var(--critical)"},
            {value:22, color:"var(--high)"},
            {value:10, color:"var(--medium)"},
            {value:6, color:"var(--info)"},
          ]} size={140} thickness={20}/>
          <div style={{flex:1}}>
            {[
              {l:"S등급 민감정보 포함", v:62, c:"var(--critical)"},
              {l:"개인정보(PII) 감지", v:22, c:"var(--high)"},
              {l:"외부 전송 금지 키워드", v:10, c:"var(--medium)"},
              {l:"기타 정책 위반", v:6, c:"var(--info)"},
            ].map(r => (
              <div key={r.l} className="row between" style={{padding:"5px 0"}}>
                <span className="row gap-8"><span className="sev-dot" style={{background:r.c}}/>{r.l}</span>
                <span className="mono small">{r.v}%</span>
              </div>
            ))}
          </div>
        </div>
      </Section>
    </div>
  </>
);

window.AnalyticsView = AnalyticsView;

// ----- 분석 뷰 프리뷰 카드 -----
// 단순 "숫자 + 설명" 카드는 무엇으로 구성되어 있는지 알 수 없다는 피드백을 반영.
// 카드 내부에 실제 구성원·항목의 축약 리스트를 함께 노출해 "이 숫자가 누구를/무엇을 의미하는지" 즉시 파악 가능.
const AnalyticsPreviewCard = ({ label, value, hint, children }) => (
  <div className="card preview-card">
    <div className="preview-card__head">
      <div>
        <div className="small muted mb-8">{label}</div>
        <div className="mono" style={{fontSize:26, fontWeight:600, lineHeight:1}}>{value}</div>
        <div className="small muted" style={{marginTop:4}}>{hint}</div>
      </div>
    </div>
    <div className="preview-card__body">{children}</div>
  </div>
);
window.AnalyticsPreviewCard = AnalyticsPreviewCard;
