/* ============================================================
   바른셈 — 룰셋 거버넌스 (법규 레이어 · 2계층 · 불변 버전 · 감사연결)
   우리 법인 관점 ↔ 플랫폼 표준(admin) 관점
   ============================================================ */
function Ruleset({ ctx }) {
  const { go, toast } = ctx;
  const G = ctx.rsGov;
  const gov = ctx.gov;
  const canEdit = ctx.canEditRuleset;
  const standardRef = gov.standardRef;
  const overrides = gov.overrides;
  const pending = gov.pending;
  const govLog = gov.versions;

  const [persp, setPersp] = useState("firm");          // firm | admin
  const [adoptOpen, setAdoptOpen] = useState(false);
  const [diffOpen, setDiffOpen] = useState(false);
  const [ovItem, setOvItem] = useState(null);
  const [snap, setSnap] = useState(null);              // version | "publish"
  const [runsVer, setRunsVer] = useState(null);        // 역추적 모달 대상 버전

  const guard = (fn) => () => { if (!canEdit) { toast("전사총괄만 룰셋을 편집·채택할 수 있습니다"); return; } fn(); };
  const adopt = (toId) => { ctx.adoptStandard(toId); setAdoptOpen(false); };
  const saveOverride = (key, value, note) => { ctx.saveOverride(key, value, note); setOvItem(null); };
  const removeOverride = (key) => { ctx.removeOverride(key); setOvItem(null); };

  const resolved = ctx.resolveFirmLive();
  const statutory = resolved.filter((r) => r.kind === "statutory");
  const policy = resolved.filter((r) => r.kind === "policy");
  const overrideCount = resolved.filter((r) => r.source === "firm").length;
  const refV = ctx.stdVer(standardRef);
  const applied = ctx.appliedRuleset();
  const frozen = ctx.frozenConfirmed();
  const recalcList = ctx.recalcClients();

  return (
    <div className="page page-wide rise">
      <BackBar go={go} />
      <div className="page-head row-between" style={{ alignItems: "flex-end" }}>
        <div>
          <div className="page-title">룰셋 — 법규 거버넌스</div>
          <div className="page-desc" style={{ marginTop: 4 }}>
            요율·세액표·한도·판례는 코드가 아니라 <b>불변 버전 데이터</b>. 플랫폼 표준을 상속하고, 필요한 항목만 법인이 재정의합니다.
          </div>
        </div>
        <div className="seg">
          <button className={persp === "firm" ? "on" : ""} onClick={() => setPersp("firm")}>우리 법인</button>
          <button className={persp === "admin" ? "on" : ""} onClick={() => setPersp("admin")}>플랫폼 표준</button>
        </div>
      </div>

      {persp === "admin"
        ? (<>
            {/* W2-5 — 법인 대표와 플랫폼 운영자는 다른 사람이다. 모드를 켜야만 발행·테넌트 조작이 열린다(C3). */}
            <div className="card card-pad" style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, background: ctx.platformMode ? "var(--warn-soft)" : "var(--surface-2)", border: "1px solid " + (ctx.platformMode ? "var(--warn-line)" : "var(--line)") }}>
              <Ms name={ctx.platformMode ? "engineering" : "visibility"} style={{ fontSize: 22, color: ctx.platformMode ? "var(--warn)" : "var(--ink-3)", flex: "none" }} />
              <div style={{ flex: 1, fontSize: 12.5, lineHeight: 1.6, color: "var(--ink-2)" }}>
                {ctx.platformMode
                  ? <><b>플랫폼 운영자 모드</b> — 바른셈이 전체 노무법인에 배포하는 표준을 편집합니다. 우리 법인 계정과는 별개 권한입니다.</>
                  : <><b>열람 전용</b> — 우리 법인({ctx.user.name} · {ctx.ROLE_LABEL[ctx.role]})은 표준을 <b>보고 채택</b>할 수 있지만 <b>발행하거나 다른 법인의 채택을 바꿀 수는 없습니다</b>.</>}
              </div>
              <button className={"btn btn-sm " + (ctx.platformMode ? "btn-danger" : "btn-default")} onClick={() => ctx.setPlatformMode(!ctx.platformMode)}>
                <Ms name={ctx.platformMode ? "logout" : "admin_panel_settings"} />{ctx.platformMode ? "법인 계정으로 돌아가기" : "플랫폼 운영자로 전환 (데모)"}
              </button>
            </div>
            <AdminRuleset ctx={ctx} onView={(v) => setSnap(v)} onRuns={(v) => setRunsVer(v)} />
          </>)
        : (
          <>
            {/* 확정 동결 / 재계산 권장 배지 */}
            {(frozen.length > 0 || recalcList.length > 0) && (
              <div style={{ display: "flex", gap: 10, marginBottom: 14, flexWrap: "wrap" }}>
                {frozen.length > 0 && (
                  <div className="card card-pad" style={{ flex: 1, minWidth: 240, display: "flex", gap: 11, alignItems: "center", padding: "11px 15px", background: "var(--surface-2)" }}>
                    <Ms name="ac_unit" style={{ color: "var(--ink-3)", fontSize: 20, flex: "none" }} />
                    <div style={{ fontSize: 12.5, color: "var(--ink-2)", lineHeight: 1.5 }}>
                      <b>확정된 {frozen.length}건은 당시 버전으로 동결</b>됨 — 채택·재정의의 영향을 받지 않습니다. 재계산하려면 해당 건의 확정을 명시적으로 해제해야 합니다.
                    </div>
                  </div>
                )}
                {recalcList.length > 0 && (
                  <div className="card card-pad" style={{ flex: 1, minWidth: 240, display: "flex", gap: 11, alignItems: "center", padding: "11px 15px", background: "var(--warn-soft)", border: "1px solid var(--warn-line)" }}>
                    <Ms name="sync_problem" style={{ color: "color-mix(in oklab, var(--warn) 70%, black)", fontSize: 20, flex: "none" }} />
                    <div style={{ fontSize: 12.5, color: "color-mix(in oklab, var(--warn) 58%, black)", lineHeight: 1.5, flex: 1 }}>
                      <b>미확정 {recalcList.length}곳 재계산 권장</b> — 룰셋 변경분 미반영: {recalcList.map((c) => c.short).join(", ")}
                    </div>
                    <button className="btn btn-default btn-sm" onClick={() => go("calc", { clientId: recalcList[0].id })}><Ms name="calculate" />계산으로</button>
                  </div>
                )}
              </div>
            )}

            {/* 표준 업데이트 알림 */}
            {pending && (() => {
              const p = ctx.stdVer(pending);
              const diffs = ctx.diffStdLive(standardRef, pending);
              return (
                <div className="rs-alert rise" style={{ marginBottom: 18 }}>
                  <Ms name="mark_email_unread" />
                  <div style={{ flex: 1 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
                      <span style={{ fontWeight: 700 }}>새 표준 버전 도착 — {p.label}</span>
                      <span className="kbd num">{p.id}</span>
                      <span className="tag tag-warn">{diffs.length}개 항목 변경</span>
                    </div>
                    <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginTop: 4, lineHeight: 1.5 }}>
                      유효일 {p.effective}부터 · {p.changelog[0]} 외 {Math.max(0, diffs.length - 1)}건. 노무사 검토 후 채택하면 유효일 귀속 급여부터 적용됩니다.
                    </div>
                  </div>
                  <div style={{ display: "flex", gap: 8, flex: "none" }}>
                    <button className="btn btn-default btn-sm" onClick={() => setDiffOpen(true)}><Ms name="difference" />변경 내역</button>
                    <button className="btn btn-primary btn-sm" disabled={!canEdit} title={canEdit ? "" : "전사총괄만 채택 가능"} onClick={guard(() => setAdoptOpen(true))}><Ms name="verified" />검토 후 채택</button>
                  </div>
                </div>
              );
            })()}

            {/* 2계층 설명 */}
            <div className="rs-layers" style={{ marginBottom: 18 }}>
              <div className="rs-layer">
                <div className="rs-layer-ic"><Ms name="public" /></div>
                <div>
                  <div className="rs-layer-t">플랫폼 표준 <span className="muted">· 바른셈이 유지·검증</span></div>
                  <div className="rs-layer-d">법정 요율·세액표·한도·판례 — 전체 노무법인 공통. 추적: <span className="kbd num">{refV.id}</span> {refV.label}</div>
                </div>
              </div>
              <Ms name="add" className="rs-layer-op" />
              <div className="rs-layer rs-layer-firm">
                <div className="rs-layer-ic"><Ms name="tune" /></div>
                <div>
                  <div className="rs-layer-t" style={{ color: "var(--accent-ink)" }}>우리 법인 오버레이 <span style={{ opacity: .8 }}>· {G.FIRM.name}</span></div>
                  <div className="rs-layer-d" style={{ color: "var(--accent-ink)", opacity: .88 }}>표준을 상속하고 {overrideCount}개 정책 항목을 재정의 — 법정 수치는 표준 그대로</div>
                </div>
              </div>
            </div>

            {/* effective_date 분기 — 예약 버전 안내 */}
            {applied.scheduled && (
              <div className="card card-pad rise" style={{ marginBottom: 18, display: "flex", gap: 13, alignItems: "center", background: "linear-gradient(180deg, var(--accent-soft), var(--surface))", border: "1px solid var(--accent-line)" }}>
                <Ms name="event_upcoming" style={{ color: "var(--accent)", fontSize: 24, flex: "none" }} />
                <div style={{ flex: 1 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
                    <span style={{ fontWeight: 700, color: "var(--accent-ink)" }}>{applied.scheduled.label}</span>
                    <span className="kbd num">{applied.scheduled.id}</span>
                    <span className="pill pill-info"><Ms name="schedule" />예약</span>
                  </div>
                  <div style={{ fontSize: 12.5, color: "var(--accent-ink)", opacity: .88, marginTop: 4, lineHeight: 1.5 }}>
                    채택 완료 · <b>유효일 {applied.scheduled.effective}</b> — {applied.scheduled.effective.slice(5, 7)}월 귀속분부터 자동 적용됩니다. 현재 귀속월({ctx.period.label})에는 <b>{applied.stdId}</b>이 적용 중. 상단 귀속월을 7월로 바꿔보세요.
                  </div>
                </div>
              </div>
            )}

            <div className="l-split" style={{ "--rail": "340px" }}>
              {/* 적용 항목 테이블 */}
              <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
                <ItemTable title="법정 수치" icon="gavel" sub="표준 권장 — 변경 시 신고 불일치 위험" items={statutory} onEdit={setOvItem} canEdit={canEdit} />
                <ItemTable title="법인 정책" icon="tune" sub="노무법인 디폴트 — 통상임금 판정·단수처리 등" items={policy} onEdit={setOvItem} canEdit={canEdit} accent />

                {/* 고객사(사업장) 레이어 안내 — 5인 여부·개별 소정근로시간은 법인 정책이 아니라 고객사 사실 */}
                <div className="card card-pad" style={{ display: "flex", gap: 11, alignItems: "center", background: "var(--surface-2)" }}>
                  <Ms name="apartment" style={{ color: "var(--ink-3)", fontSize: 20, flex: "none" }} />
                  <div style={{ fontSize: 12.5, color: "var(--ink-2)", lineHeight: 1.55 }}>
                    <b>5인 이상 여부·개별 소정근로시간</b>은 법인 정책이 아니라 <b>고객사(사업장)의 사실</b>입니다 — 각 고객사 계약에서 판정되어 가산 적용·통상시급 분모에 직접 반영됩니다. 위 소정근로시간은 <b>법인 디폴트</b>이며 계약에서 재정의할 수 있습니다.
                  </div>
                </div>

                {/* 결정성 안내 */}
                <div className="card card-pad" style={{ background: "var(--warn-soft)", border: "1px solid var(--warn-line)", display: "flex", gap: 12 }}>
                  <Ms name="schedule" style={{ color: "color-mix(in oklab, var(--warn) 70%, black)", fontSize: 20, flex: "none" }} />
                  <div style={{ fontSize: 12.5, color: "color-mix(in oklab, var(--warn) 58%, black)", lineHeight: 1.6 }}>
                    모든 급여 계산은 <b>산정 시점에 유효했던 룰 버전을 스냅샷</b>으로 고정합니다. 과거 급여를 재계산해도 <b>당시 버전</b>으로 동일하게 재현되며, 새 표준을 채택해도 이미 확정된 급여는 바뀌지 않습니다.
                  </div>
                </div>
              </div>

              {/* 우측: 적용 버전 + 버전이력 */}
              <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
                <div className="card card-pad" style={{ background: "linear-gradient(180deg, var(--accent-soft), var(--surface))" }}>
                  <div style={{ fontSize: 12, fontWeight: 700, color: "var(--accent-ink)", letterSpacing: ".03em" }}>우리 법인 적용 룰셋</div>
                  <div style={{ display: "flex", alignItems: "center", gap: 8, margin: "8px 0 4px", flexWrap: "wrap" }}>
                    <span className="kbd num">{govLog[0].id}</span>
                    <span className="pill pill-ok"><Ms name="check_circle" />활성</span>
                  </div>
                  <div className="dl" style={{ marginTop: 10 }}>
                    <dt>추적 표준</dt><dd className="num">{refV ? refV.id : standardRef}</dd>
                    <dt>현재월 적용</dt><dd className="num">{applied.stdId}{applied.scheduled ? " (7월~ " + applied.scheduled.id + ")" : ""}</dd>
                    <dt>재정의 항목</dt><dd>{overrideCount}개</dd>
                    <dt>최종 변경</dt><dd className="num">{govLog[0].at}</dd>
                    <dt>책임 노무사</dt><dd>{ctx.user.name.replace(/\s*노무사$/, "")}</dd>
                  </div>
                </div>

                <div className="card card-pad">
                  <div style={{ fontSize: 12, fontWeight: 700, color: "var(--ink-3)", letterSpacing: ".03em", marginBottom: 10 }}>표준 버전 이력 · 감사연결</div>
                  <StdTimeline versions={ctx.stdVersions} currentRef={standardRef} pending={pending} adopted={gov.adopted} onView={(v) => setSnap(v)} onRuns={(v) => setRunsVer(v)} runsForStd={ctx.runsForStd} statusOf={ctx.stdStatusOf} />
                </div>

                <div className="card card-pad">
                  <div style={{ fontSize: 12, fontWeight: 700, color: "var(--ink-3)", letterSpacing: ".03em", marginBottom: 10 }}>우리 법인 룰셋 변경 이력</div>
                  <div className="rs-flog">
                    {govLog.map((g, i) => (
                      <div className="rs-flog-row" key={g.id}>
                        <div className="rs-flog-dot" data-on={i === 0 ? "1" : "0"} />
                        <div style={{ flex: 1 }}>
                          <div style={{ fontSize: 12.5, fontWeight: 600 }}>{g.label}</div>
                          <div className="muted" style={{ fontSize: 11 }}>{g.by} · <span className="num">{g.at}</span></div>
                        </div>
                      </div>
                    ))}
                  </div>
                  <div className="rs-vfoot" style={{ marginTop: 8 }}><Ms name="lock" style={{ fontSize: 13 }} />변경은 누적 기록 — 삭제 불가</div>
                </div>
              </div>
            </div>

            {adoptOpen && <AdoptModal to={ctx.stdVer(pending)} fromId={standardRef} diffs={ctx.diffStdLive(standardRef, pending)} onClose={() => setAdoptOpen(false)} onAdopt={adopt} />}
            {diffOpen && (
              <Modal title={`변경 내역 — ${pending}`} width={560} onClose={() => setDiffOpen(false)}
                footer={<><button className="btn btn-default" onClick={() => setDiffOpen(false)}>닫기</button>{canEdit && <button className="btn btn-primary" onClick={() => { setDiffOpen(false); setAdoptOpen(true); }}><Ms name="verified" />채택하기</button>}</>}>
                <DiffList diffs={ctx.diffStdLive(standardRef, pending)} />
              </Modal>
            )}
            {ovItem && <OverrideModal item={ovItem} onClose={() => setOvItem(null)} onSave={saveOverride} onRemove={removeOverride} />}
          </>
        )}

      {snap && snap !== "publish" && <SnapshotModal version={snap} items={ctx.rsGov.RS_ITEMS} status={ctx.stdStatusOf(snap)} onClose={() => setSnap(null)} />}
      {snap === "publish" && <PublishModal ctx={ctx} onClose={() => setSnap(null)} />}
      {runsVer && <AppliedRunsModal version={runsVer} runs={ctx.runsForStd(runsVer.id)} status={ctx.stdStatusOf(runsVer)} agg={persp === "admin" ? ctx.adminRunsForStd(runsVer.id) : null} onClose={() => setRunsVer(null)} onGo={(cid) => { setRunsVer(null); go("documents", { clientId: cid }); }} />}
    </div>
  );
}

/* 적용 항목 테이블 (법정/정책) */
function ItemTable({ title, icon, sub, items, onEdit, accent, canEdit }) {
  return (
    <div className="card">
      <CardHead icon={icon} title={title} sub={sub}
        right={<span className="tag">{items.length}개 항목</span>} />
      <table className="tbl tbl-cards">
        <thead><tr><th>항목</th><th className="r" style={{ width: 200 }}>적용값</th><th style={{ width: 116, textAlign: "center" }}>출처</th><th style={{ width: 84, textAlign: "center" }}>재정의</th></tr></thead>
        <tbody>
          {items.map((it) => (
            <tr key={it.key} className={it.source === "firm" ? "rs-row-firm" : ""}>
              <td className="tc-name">
                <div style={{ fontWeight: 600 }}>{it.label}</div>
                <div className="muted" style={{ fontSize: 11 }}>{it.note || it.legal}</div>
              </td>
              <td className="r num" data-label="적용값" style={{ fontWeight: 700, color: "var(--accent-ink)" }}>
                {it.value}
                {it.source === "firm" && (
                  it.unit === "enum" || it.unit === "text"
                    ? <div className="muted" style={{ fontSize: 10.5, fontWeight: 500, marginTop: 2, textWrap: "pretty" }}>표준값: {it.stdValue}</div>
                    : <div className="muted num" style={{ fontSize: 10.5, fontWeight: 500, textDecoration: "line-through" }}>표준 {it.stdValue}</div>
                )}
              </td>
              <td data-label="출처" style={{ textAlign: "center" }}><SourceBadge source={it.source} /></td>
              <td className="tc-action" data-label="재정의" style={{ textAlign: "center" }}>
                <button className="iconbtn" style={{ width: 30, height: 30, margin: "0 auto", opacity: canEdit ? 1 : .4, cursor: canEdit ? "pointer" : "not-allowed" }} aria-label={`${it.label} 재정의`} title={canEdit ? "재정의" : "전사총괄만 편집 가능"} disabled={!canEdit} onClick={() => canEdit && onEdit(it)}><Ms name="edit" style={{ fontSize: 16 }} /></button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

window.Ruleset = Ruleset;
