/* ============================================================
   바른셈 — 대시보드
   ============================================================ */
function Dashboard({ ctx }) {
  const { statusOf, clientTotals, go, period } = ctx;
  const clients = ctx.scopedClients;
  const approvalQueue = ctx.approvalQueue || [];
  const [sortMode, setSortMode] = useState("default");
  const [reminded, setReminded] = useState({});
  const LANE_TODAY = "2026-06-08";
  const lane = clients.map((c) => ({ c, rem: window.BARUNSEM.reminderState(period.payDate, c.dueOffset, statusOf(c.id) !== "draft", LANE_TODAY) }))
    .filter((x) => x.rem.status === "pending")
    .sort((a, b) => a.rem.dday - b.rem.dday);
  const totals = clients.map((c) => ({ c, st: statusOf(c.id), t: clientTotals(c), audit: ctx.clientAudit(c) }));
  // 하드코딩된 43건이 있던 자리 — 실제 변동분(연장·야간·휴일·상여·결근)이 있는 근로자 수를 센다.
  const normalizedCount = clients.reduce((n, c) => n + c.employees.filter((e) => {
    const v = e.variation || {};
    return ["overtime", "night", "holiday", "holidayOver", "bonus", "absentDays"].some((k) => (v[k] || 0) > 0);
  }).length, 0);
  const ordered = sortMode === "risk"
    ? [...totals].sort((a, b) => (b.audit.errors - a.audit.errors) || (b.audit.warns - a.audit.warns))
    : totals;
  const riskClients = totals.filter((x) => x.audit.errors > 0 || x.audit.warns > 0).length;
  const sumNet = totals.reduce((s, x) => s + x.t.net, 0);
  const sumGross = totals.reduce((s, x) => s + x.t.gross, 0);
  const heads = totals.reduce((s, x) => s + x.c.headcount, 0);
  const needReview = totals.filter((x) => ["submitted", "in_review"].includes(x.st)).length;
  const calcDone = totals.filter((x) => ["calculated", "pending_approval", "confirmed", "distributed"].includes(x.st)).length;
  const distributed = totals.filter((x) => x.st === "distributed").length;

  const FLOW = window.BARUNSEM.FLOW;
  const flowIdx = (st) => FLOW.findIndex((f) => f.key === st);

  const actionFor = (st) => {
    if (st === "draft") return { label: "고객사 입력 대기", view: "review", icon: "pending", primary: false };
    if (["submitted", "in_review"].includes(st)) return { label: "검수하기", view: "review", icon: "fact_check", primary: true };
    if (st === "locked") return { label: "급여 계산", view: "calc", icon: "calculate", primary: true };
    if (st === "calculated") return { label: "계산 검토", view: "calc", icon: "rule", primary: true };
    if (st === "pending_approval") return { label: "승인 검토", view: "documents", icon: "approval", primary: true };
    if (st === "confirmed") return { label: "명세서 발송", view: "documents", icon: "send", primary: true };
    return { label: "급여대장 보기", view: "documents", icon: "description", primary: false };
  };

  return (
    <div className="page rise">
      <div className="page-head row-between">
        <div>
          <div className="page-title">안녕하세요, {ctx.user.name}님</div>
          <div className="page-desc">{period.label} 귀속 급여 · 지급 {period.state === "past" ? "완료" : "예정"}일 {period.payDate} · <b style={{ color: "var(--accent-ink)" }}>{period.state === "past" ? "마감 완료" : period.state === "upcoming" ? "마감 예정" : "마감 D-5"}</b></div>
        </div>
        <button className="btn btn-default" onClick={() => go("clientform")}>
          <Ms name="open_in_new" />고객사 입력화면 미리보기
        </button>
      </div>

      {/* KPI */}
      <div className="kpi-grid" data-stagger style={{ marginBottom: 22 }}>
        <div className="kpi">
          <div className="kpi-label"><Ms name="fact_check" style={{ color: "var(--warn)" }} />검수 대기</div>
          <div className="kpi-val">{needReview}<small> / {clients.length}곳</small></div>
          <div className="kpi-sub">고객사 제출분 검수 필요</div>
        </div>
        <div className="kpi">
          <div className="kpi-label"><Ms name="calculate" style={{ color: "var(--teal)" }} />계산 완료</div>
          <div className="kpi-val">{calcDone}<small> / {clients.length}곳</small></div>
          <div className="kpi-sub">확정·발송 대기 포함</div>
        </div>
        <div className="kpi">
          <div className="kpi-label"><Ms name="groups" />대상 근로자</div>
          <div className="kpi-val num">{heads}<small> 명</small></div>
          <div className="kpi-sub">전체 고객사 합산</div>
        </div>
        <div className="kpi">
          <div className="kpi-label"><Ms name="payments" style={{ color: "var(--accent)" }} />실지급 예정</div>
          <div className="kpi-val num">{(sumNet / 10000).toLocaleString("ko-KR", { maximumFractionDigits: 0 })}<small> 만원</small></div>
          <div className="kpi-sub num">총지급 {KRW(sumGross)}원</div>
        </div>
      </div>

      <div className="l-split dash-split">
        {/* 고객사별 진행 */}
        <div className="card">
          <CardHead icon="apartment" title="이번 달 고객사 진행 상황" sub={`${clients.length}개 고객사`}
            right={
              <div className="seg" style={{ height: 30 }} title="정렬 — 검수 리스크 높은 순서">
                <button className={sortMode === "default" ? "on" : ""} onClick={() => setSortMode("default")} style={{ fontSize: 12 }}>기본 순서</button>
                <button className={sortMode === "risk" ? "on" : ""} onClick={() => setSortMode("risk")} style={{ fontSize: 12 }}>
                  리스크 순{riskClients > 0 && <span style={{ marginLeft: 4, fontVariantNumeric: "tabular-nums" }}>{riskClients}</span>}
                </button>
              </div>
            } />
          <div>
            {ordered.map(({ c, st, t, audit }, i) => {
              const act = actionFor(st);
              const idx = flowIdx(st);
              const pct = Math.round((idx / (FLOW.length - 1)) * 100);
              return (
                <div key={c.id} className="dash-row" style={{ padding: "16px 22px", borderBottom: i < ordered.length - 1 ? "1px solid var(--line)" : "none" }}>
                  <ClientAvatar client={c} size={42} />
                  <div className="dash-id" style={{ minWidth: 0, flex: "0 0 200px" }}>
                    <div style={{ fontWeight: 650, fontSize: 14, letterSpacing: "-0.01em" }}>{c.name}</div>
                    <div className="muted" style={{ fontSize: 12, marginTop: 1 }}>{c.biz} · {c.headcount}명 · {c.size}</div>
                  </div>
                  <div className="dash-prog" style={{ flex: 1, minWidth: 90 }}>
                    <div className="dash-prog-hd" style={{ display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
                      <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                        <StatusPill status={st} />
                        {(audit.errors > 0 || audit.warns > 0) && <RiskBadge errors={audit.errors} warns={audit.warns} size="sm" />}
                        {ctx.recalcNeeded(c.id) && <span className="tag tag-warn" title="룰셋이 변경됨 — 재계산 권장"><Ms name="sync_problem" style={{ fontSize: 12 }} />재계산 권장</span>}
                      </div>
                      <span className="muted num" style={{ fontSize: 12, fontWeight: 600 }}>실지급 {KRW(t.net)}원</span>
                    </div>
                    <div className="prog"><i style={{ width: pct + "%" }} /></div>
                  </div>
                  <div className="dash-actwrap">
                    <button className={"btn " + (act.primary ? "btn-primary" : "btn-default") + " btn-sm dash-act"} onClick={() => go(act.view, { clientId: c.id })}>
                      <Ms name={act.icon} />{act.label}
                    </button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* 우측 레일 */}
        <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
          {/* §08-A 승인 대기 큐 (팀장·대표 — 2차 승인) */}
          {approvalQueue.length > 0 && (
            <div className="card card-pad" style={{ background: "var(--warn-soft)", border: "1px solid var(--warn-line)" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 12 }}>
                <Ms name="approval" style={{ color: "color-mix(in oklab, var(--warn) 65%, black)", fontSize: 20 }} />
                <h3 style={{ fontSize: 14, fontWeight: 650, color: "color-mix(in oklab, var(--warn) 55%, black)" }}>승인 대기</h3>
                <span className="pill pill-warn" style={{ height: 20 }}>{approvalQueue.length}</span>
                <span className="muted" style={{ fontSize: 11.5, marginLeft: "auto" }}>2차 승인 — 팀장·대표</span>
              </div>
              {approvalQueue.map((c) => {
                const assignee = ctx.userOf(c.primaryAssigneeId);
                return (
                  <div key={c.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "9px 0", borderBottom: "1px solid var(--warn-line)" }}>
                    <ClientAvatar client={c} size={28} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 650, fontSize: 13, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.name}</div>
                      <div className="muted" style={{ fontSize: 11 }}>{assignee ? assignee.name + " 상신" : "상신됨"} · {c.headcount}명</div>
                    </div>
                    <button className="btn btn-primary btn-sm" onClick={() => go("documents", { clientId: c.id })}><Ms name="approval" style={{ fontSize: 14 }} />검토</button>
                  </div>
                );
              })}
            </div>
          )}

          {/* §05 변동분 마감 레인 (리마인드) */}
          <div className="card card-pad">
            <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 12 }}>
              <Ms name="notifications_active" style={{ color: "var(--accent)", fontSize: 20 }} />
              <h3 style={{ fontSize: 14, fontWeight: 650 }}>변동분 마감 레인</h3>
              <span className="muted" style={{ fontSize: 12 }}>제출 마감 D-day</span>
            </div>
            {lane.length === 0 ? (
              <div style={{ display: "flex", gap: 9, alignItems: "center", padding: "8px 0", color: "var(--ink-3)", fontSize: 13 }}>
                <Ms name="task_alt" style={{ color: "var(--ok)", fontSize: 19 }} />전 고객사 변동분 제출 완료
              </div>
            ) : lane.map(({ c, rem }) => {
              const TONE = { overdue: "var(--danger)", urgent: "var(--danger)", soon: "var(--warn)", ok: "var(--ink-3)" }[rem.level];
              return (
                <div key={c.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "9px 0", borderBottom: "1px solid var(--line)" }}>
                  <ClientAvatar client={c} size={28} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 650, fontSize: 13, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.name}</div>
                    <div style={{ fontSize: 11, color: TONE, fontWeight: 600 }}>마감 {rem.due.slice(5)} · {rem.dday < 0 ? "마감 " + (-rem.dday) + "일 지남" : rem.dday === 0 ? "오늘 마감" : "D-" + rem.dday}</div>
                  </div>
                  {reminded[c.id]
                    ? <span className="tag tag-ok" style={{ height: 24 }}><Ms name="check" style={{ fontSize: 12 }} />발송함</span>
                    : <button className="btn btn-primary btn-sm" onClick={() => { setReminded((s) => ({ ...s, [c.id]: true })); ctx.addAudit(c.id, "변동분 제출 리마인드 발송"); ctx.toast(c.short + " 리마인드를 보냈습니다", "ok"); }}><Ms name="send" />리마인드</button>}
                </div>
              );
            })}
          </div>

          <div className="card card-pad">
            <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 12 }}>
              <Ms name="event" style={{ color: "var(--accent)", fontSize: 20 }} />
              <h3 style={{ fontSize: 14, fontWeight: 650 }}>마감 일정</h3>
            </div>
            {[
              { d: "6/2", t: "고객사 변동분 제출 마감", done: true },
              { d: "6/5", t: "노무사 검수·계산 마감", done: false, now: true },
              { d: "6/8", t: "급여명세서 발송", done: false },
              { d: "6/10", t: "급여 지급일", done: false },
            ].map((x, i) => (
              <div key={i} style={{ display: "flex", gap: 11, alignItems: "center", padding: "7px 0" }}>
                <span className="kbd num" style={{ width: 38, textAlign: "center" }}>{x.d}</span>
                <span style={{ fontSize: 13, fontWeight: x.now ? 700 : 500, color: x.done ? "var(--ink-4)" : x.now ? "var(--accent-ink)" : "var(--ink-2)", textDecoration: x.done ? "line-through" : "none", flex: 1 }}>{x.t}</span>
                {x.done && <Ms name="check_circle" style={{ color: "var(--ok)", fontSize: 17 }} />}
                {x.now && <span className="tag tag-accent">오늘</span>}
              </div>
            ))}
          </div>

          <div className="card card-pad" style={{ cursor: "pointer" }} onClick={() => go("ruleset")}>
            <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 10 }}>
              <Ms name="gavel" style={{ color: "var(--accent)", fontSize: 20 }} />
              <h3 style={{ fontSize: 14, fontWeight: 650 }}>적용 룰셋</h3>
              <div style={{ flex: 1 }} />
              <Ms name="chevron_right" style={{ color: "var(--ink-4)" }} />
            </div>
            <div style={{ fontWeight: 700, fontSize: 15 }}>{ctx.appliedRuleset().firmId} <span className="muted" style={{ fontWeight: 500, fontSize: 12.5 }}>· 우리 법인</span></div>
            <div className="muted" style={{ fontSize: 12, marginTop: 3 }}>표준 {ctx.appliedRuleset().stdId} 상속 · 재정의 {ctx.appliedRuleset().overrideCount}개</div>
            {ctx.appliedRuleset().scheduled && (
              <div style={{ marginTop: 10, display: "flex", alignItems: "center", gap: 7, padding: "8px 10px", background: "var(--bg-sunken, var(--surface-2))", borderRadius: 8 }}>
                <Ms name="schedule" style={{ color: "var(--accent)", fontSize: 18 }} />
                <span style={{ fontSize: 12, fontWeight: 600, color: "var(--ink-2)" }}>{ctx.appliedRuleset().scheduled.id} 예약 · {ctx.appliedRuleset().scheduled.effective.slice(5, 7)}월 귀속부터 자동 적용</span>
              </div>
            )}
            {ctx.gov.pending ? (
              <div style={{ marginTop: 10, display: "flex", alignItems: "center", gap: 7, padding: "8px 10px", background: "var(--warn-soft)", borderRadius: 8 }}>
                <Ms name="mark_email_unread" style={{ color: "color-mix(in oklab, var(--warn) 70%, black)", fontSize: 18 }} />
                <span style={{ fontSize: 12, fontWeight: 600, color: "color-mix(in oklab, var(--warn) 60%, black)" }}>새 표준 {ctx.gov.pending} 도착 · 검토 대기</span>
              </div>
            ) : (
              <div style={{ marginTop: 10, display: "flex", alignItems: "center", gap: 7, padding: "8px 10px", background: "var(--ok-soft)", borderRadius: 8 }}>
                <Ms name="verified" style={{ color: "var(--ok)", fontSize: 18 }} />
                <span style={{ fontSize: 12, fontWeight: 600, color: "color-mix(in oklab, var(--ok) 80%, black)" }}>표준 최신 · 노무사 채택 완료</span>
              </div>
            )}
          </div>

          <div className="card card-pad" style={{ background: "var(--accent-soft)", border: "1px solid var(--accent-line)" }}>
            <div style={{ display: "flex", gap: 10 }}>
              <Ms name="lightbulb" style={{ color: "var(--accent)", fontSize: 20 }} />
              <div>
                <div style={{ fontWeight: 650, fontSize: 13, color: "var(--accent-ink)" }}>입력 경계 마찰 제거</div>
                <div style={{ fontSize: 12, color: "var(--accent-ink)", opacity: .85, marginTop: 4, lineHeight: 1.55 }}>
                  고객사가 웹 폼으로 직접 제출 → 엑셀 재입력 0건. 이번 달 정규화된 변동분 <b>{normalizedCount}건</b>이 자동 매핑되었습니다.
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
window.Dashboard = Dashboard;
