/* ============================================================
   dashboard.jsx — overview: readiness, alerts, department health
   ============================================================ */
function StatCard({ label, value, sub, tone, icon, onClick }) {
  const Ico = icon;
  const toneColor = { ok: 'var(--ok)', warn: 'var(--warn)', danger: 'var(--danger)', none: 'var(--ink-3)', accent: 'var(--accent)' }[tone] || 'var(--ink)';
  const toneSoft = { ok: 'var(--ok-soft)', warn: 'var(--warn-soft)', danger: 'var(--danger-soft)', none: 'var(--none-soft)', accent: 'var(--accent-soft)' }[tone] || 'var(--surface-2)';
  return (
    <button className="card card-pad enter" onClick={onClick} style={{
      textAlign: 'left', cursor: onClick ? 'pointer' : 'default', display: 'flex', flexDirection: 'column', gap: 14,
      border: '1px solid var(--line)', background: 'var(--surface)', transition: 'transform .12s, box-shadow .15s, border-color .15s',
    }}
    onMouseEnter={e => { if (onClick) { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = 'var(--shadow)'; } }}
    onMouseLeave={e => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-2)' }}>{label}</span>
        <span style={{ width: 32, height: 32, borderRadius: 9, background: toneSoft, color: toneColor, display: 'grid', placeItems: 'center' }}>
          {Ico && <Ico size={17} />}
        </span>
      </div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
        <span className="figure" style={{ fontSize: 38, color: tone === 'accent' ? 'var(--ink)' : toneColor === 'var(--ink)' ? 'var(--ink)' : toneColor }}>{value}</span>
        {sub && <span style={{ fontSize: 12.5, color: 'var(--ink-3)' }}>{sub}</span>}
      </div>
    </button>
  );
}

function Dashboard({ instruments, go, setFilter }) {
  const stats = useMemo(() => {
    let ok = 0, warn = 0, danger = 0, none = 0;
    instruments.forEach(i => { const s = statusOf(i).key; if (s === 'ok') ok++; else if (s === 'warn') warn++; else if (s === 'danger') danger++; else none++; });
    return { total: instruments.length, ok, warn, danger, none };
  }, [instruments]);

  const readiness = stats.total ? Math.round((stats.ok / stats.total) * 100) : 0;

  const deptRows = useMemo(() => {
    const map = {};
    instruments.forEach(i => {
      const d = i.dept || '—';
      map[d] = map[d] || { dept: d, total: 0, ok: 0, warn: 0, danger: 0, none: 0 };
      map[d].total++;
      const s = statusOf(i).key; map[d][s]++;
    });
    return Object.values(map).map(r => ({ ...r, pct: Math.round((r.ok / r.total) * 100) }))
      .sort((a, b) => a.pct - b.pct);
  }, [instruments]);

  const upcoming = useMemo(() => {
    return instruments
      .map(i => ({ i, s: statusOf(i) }))
      .filter(x => x.s.days != null && x.s.days <= NEAR_DAYS)
      .sort((a, b) => a.s.days - b.s.days)
      .slice(0, 7);
  }, [instruments]);

  const topTypes = useMemo(() => {
    const m = {};
    instruments.forEach(i => { const key = i.type || i.typeName || '—'; m[key] = m[key] || { name: key, count: 0, dept: i.dept }; m[key].count++; });
    return Object.values(m).sort((a, b) => b.count - a.count).slice(0, 6);
  }, [instruments]);
  const topMax = Math.max(1, ...topTypes.map(t => t.count));

  // ---- auditor-readiness (ISO 15189) ----
  const FIELD_LABEL = { brand: 'ยี่ห้อ', model: 'รุ่น/Model', serial: 'Serial No.', asset: 'รหัสครุภัณฑ์', cal: 'วันสอบเทียบ', exp: 'วันครบกำหนด' };
  const audit = useMemo(() => {
    const fields = Object.keys(FIELD_LABEL);
    const filled = (v) => v != null && v !== '' && v !== '-';
    let hits = 0, total = 0, fullyComplete = 0;
    const incomplete = [], outService = [], pm = [];
    instruments.forEach(i => {
      let n = 0;
      fields.forEach(f => { total++; if (filled(i[f])) { hits++; n++; } });
      if (n === fields.length) fullyComplete++;
      else incomplete.push({ i, missing: fields.filter(f => !filled(i[f])) });
      const meta = window.instrumentMeta(i);
      if (meta.op.key === 'repair' || meta.op.key === 'down') outService.push({ i, op: meta.op });
      if (meta.pmNext) { const d = daysUntil(meta.pmNext); if (d != null && d <= NEAR_DAYS) pm.push({ i, d, pmNext: meta.pmNext }); }
    });
    pm.sort((a, b) => a.d - b.d);
    outService.sort((a, b) => (a.op.key === 'down' ? -1 : 1));
    return {
      completePct: total ? Math.round((hits / total) * 100) : 0,
      fullyComplete, incompleteCount: incomplete.length, incomplete: incomplete.slice(0, 6),
      outService, outCount: outService.length, pm: pm.slice(0, 6), pmCount: pm.length,
    };
  }, [instruments]);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
      {/* hero readiness banner */}
      <div className="card enter" style={{ overflow: 'hidden', display: 'grid', gridTemplateColumns: '1fr auto', gap: 0 }}>
        <div style={{ padding: '26px 28px' }}>
          <div style={{ fontSize: 12.5, fontWeight: 600, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>ความพร้อมรวมของห้องปฏิบัติการ</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, marginTop: 10 }}>
            <span className="figure" style={{ fontSize: 64, lineHeight: 1, color: 'var(--ink)' }}>{readiness}<span style={{ fontSize: 30, color: 'var(--ink-3)' }}>%</span></span>
            <span style={{ fontSize: 14, color: 'var(--ink-2)', maxWidth: 320 }}>
              เครื่องมือ <b className="tnum">{stats.ok}</b> จาก <b className="tnum">{stats.total}</b> เครื่อง อยู่ในสถานะปกติ ณ วันที่ {fmtDateFull(TODAY.toISOString().slice(0,10))}
            </span>
          </div>
          {/* stacked status bar */}
          <div style={{ display: 'flex', height: 12, borderRadius: 99, overflow: 'hidden', marginTop: 20, gap: 2, background: 'var(--surface-2)' }}>
            {[['ok', stats.ok, 'var(--ok)'], ['warn', stats.warn, 'var(--warn)'], ['none', stats.none, 'var(--none)'], ['danger', stats.danger, 'var(--danger)']].map(([k, v, c]) =>
              v > 0 && <div key={k} title={`${v}`} style={{ width: `${(v / stats.total) * 100}%`, background: c }} />)}
          </div>
          <div style={{ display: 'flex', gap: 18, marginTop: 14, flexWrap: 'wrap' }}>
            {[['ปกติ', stats.ok, 'var(--ok)'], ['ใกล้ครบกำหนด', stats.warn, 'var(--warn)'], ['ไม่มีข้อมูล', stats.none, 'var(--none)'], ['เกินกำหนด', stats.danger, 'var(--danger)']].map(([l, v, c]) =>
              <span key={l} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12.5, color: 'var(--ink-2)' }}>
                <span style={{ width: 9, height: 9, borderRadius: 3, background: c }} /> {l} <b className="tnum" style={{ color: 'var(--ink)' }}>{v}</b>
              </span>)}
          </div>
        </div>
        <div style={{ display: 'grid', placeItems: 'center', padding: '0 36px', borderLeft: '1px solid var(--line-soft)', background: 'var(--accent-softer)' }}>
          <Ring pct={readiness} size={132} stroke={12} label={`${readiness}%`} sub="พร้อมใช้งาน" color="var(--accent)" />
        </div>
      </div>

      {/* stat cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16 }}>
        <StatCard label="เครื่องมือทั้งหมด" value={stats.total} sub="รายการ" tone="accent" icon={I.beaker} onClick={() => { setFilter && setFilter('all'); go('inventory'); }} />
        <StatCard label="ใกล้ครบกำหนด" value={stats.warn} sub={`ภายใน ${NEAR_DAYS} วัน`} tone="warn" icon={I.clock} onClick={() => { setFilter && setFilter('warn'); go('alerts'); }} />
        <StatCard label="เกินกำหนดสอบเทียบ" value={stats.danger} sub="ต้องดำเนินการ" tone="danger" icon={I.warning} onClick={() => { setFilter && setFilter('danger'); go('alerts'); }} />
        <StatCard label="ไม่มีข้อมูลสอบเทียบ" value={stats.none} sub="รอบันทึก" tone="none" icon={I.tag} onClick={() => { setFilter && setFilter('none'); go('inventory'); }} />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.25fr 1fr', gap: 22, alignItems: 'start' }}>
        {/* department readiness */}
        <div className="card enter">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '18px 22px 12px' }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontWeight: 600, fontSize: 16, whiteSpace: 'nowrap' }}>ความพร้อมรายแผนก</div>
              <div className="page-sub">เรียงจากแผนกที่ต้องดูแลก่อน</div>
            </div>
            <span className="chip" style={{ flex: 'none' }} onClick={() => go('inventory')}>ดูทั้งหมด <I.chevR size={14} /></span>
          </div>
          <hr className="divider" />
          <div style={{ padding: '8px 22px 18px' }}>
            {deptRows.map((r, idx) => (
              <div key={r.dept} className="dept-health-row" style={{ display: 'grid', gridTemplateColumns: '188px 1fr 52px', gap: 14, alignItems: 'center', padding: '11px 0', borderBottom: idx < deptRows.length - 1 ? '1px solid var(--line-soft)' : 'none', cursor: 'pointer' }}
                onClick={() => { setFilter && setFilter('all'); go('inventory', { dept: r.dept }); }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 9, minWidth: 0 }}>
                  <DeptDot dept={r.dept} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{(DEPT_META[r.dept] || {}).short || r.dept}</div>
                    <div style={{ fontSize: 11, color: 'var(--ink-3)' }} className="tnum">{r.total} เครื่อง</div>
                  </div>
                </div>
                <div className="bar" style={{ background: 'var(--surface-2)' }}>
                  <span style={{ width: `${r.pct}%`, background: r.pct >= 80 ? 'var(--ok)' : r.pct >= 55 ? 'var(--warn)' : 'var(--danger)' }} />
                </div>
                <div className="figure tnum" style={{ fontSize: 17, textAlign: 'right', color: 'var(--ink)' }}>{r.pct}%</div>
              </div>
            ))}
          </div>
        </div>

        {/* upcoming / due */}
        <div className="card enter">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '18px 22px 12px' }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontWeight: 600, fontSize: 16, whiteSpace: 'nowrap' }}>คิวสอบเทียบที่ใกล้ถึง</div>
              <div className="page-sub">นับถอยหลังถึงวันหมดอายุ</div>
            </div>
            <span className="chip" style={{ flex: 'none' }} onClick={() => go('alerts')}>การแจ้งเตือน <I.chevR size={14} /></span>
          </div>
          <hr className="divider" />
          <div>
            {upcoming.length === 0 && <EmptyState icon={I.check} title="ไม่มีคิวใกล้ครบกำหนด" sub="ทุกเครื่องอยู่ในเกณฑ์ปกติ" />}
            {upcoming.map((x, idx) => {
              const s = x.s;
              return (
                <div key={x.i.code} onClick={() => go('detail', { code: x.i.code })}
                  style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '11px 22px', borderBottom: idx < upcoming.length - 1 ? '1px solid var(--line-soft)' : 'none', cursor: 'pointer' }}
                  className="upcoming-row">
                  <div style={{ width: 44, textAlign: 'center', flex: 'none' }}>
                    <div className="figure" style={{ fontSize: 22, lineHeight: 1, color: s.key === 'danger' ? 'var(--danger)' : 'var(--warn)' }}>{Math.abs(s.days)}</div>
                    <div style={{ fontSize: 9.5, color: 'var(--ink-3)' }}>{s.days < 0 ? 'เกิน(วัน)' : 'วัน'}</div>
                  </div>
                  <div style={{ width: 1, height: 30, background: 'var(--line)' }} />
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{x.i.type}</div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <span className="code" style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{x.i.code}</span>
                      <DeptDot dept={x.i.dept} />
                    </div>
                  </div>
                  <Pill status={s} />
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* top instrument types */}
      <div className="card enter card-pad">
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 600, fontSize: 16, whiteSpace: 'nowrap' }}>ชนิดเครื่องมือที่มีมากที่สุด</div>
            <div className="page-sub">6 อันดับแรกตามจำนวนในทะเบียน</div>
          </div>
          <span className="chip" style={{ flex: 'none' }} onClick={() => go('analytics')}>วิเคราะห์เชิงลึก <I.chevR size={14} /></span>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '4px 36px' }} className="dash-grid">
          {topTypes.map((tp, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr 80px 32px', gap: 12, alignItems: 'center', padding: '8px 0' }}>
              <span style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} title={tp.name}>{tp.name}</span>
              <div className="bar" style={{ background: 'var(--surface-2)' }}><span style={{ width: `${(tp.count / topMax) * 100}%`, background: deptColor(tp.dept) }} /></div>
              <span className="figure tnum" style={{ fontSize: 16, textAlign: 'right' }}>{tp.count}</span>
            </div>
          ))}
        </div>
      </div>

      {/* ===== auditor readiness (ISO 15189) ===== */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 4 }}>
        <span style={{ width: 34, height: 34, borderRadius: 9, background: 'var(--accent-soft)', color: 'var(--accent-strong)', display: 'grid', placeItems: 'center', flex: 'none' }}><I.shield size={18} /></span>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontWeight: 600, fontSize: 16, whiteSpace: 'nowrap' }}>พร้อมสำหรับการตรวจประเมิน (ISO 15189)</div>
          <div className="page-sub">หลักฐานการควบคุมเครื่องมือที่ผู้ตรวจประเมินมักขอดู</div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '0.85fr 1fr 1fr', gap: 22, alignItems: 'start' }}>
        {/* data completeness */}
        <div className="card enter card-pad" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div>
            <div style={{ fontWeight: 600, fontSize: 15 }}>ความครบถ้วนของทะเบียน</div>
            <div className="page-sub">Master list completeness</div>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
            <Ring pct={audit.completePct} size={92} stroke={9} label={`${audit.completePct}%`} sub="ครบถ้วน"
              color={audit.completePct >= 85 ? 'var(--ok)' : audit.completePct >= 60 ? 'var(--warn)' : 'var(--danger)'} />
            <div style={{ fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.7 }}>
              <div>สมบูรณ์ครบทุกช่อง <b className="tnum" style={{ color: 'var(--ink)' }}>{audit.fullyComplete}</b>/{stats.total}</div>
              <div>ข้อมูลไม่ครบ <b className="tnum" style={{ color: audit.incompleteCount ? 'var(--warn)' : 'var(--ok)' }}>{audit.incompleteCount}</b> เครื่อง</div>
            </div>
          </div>
          {audit.incomplete.length > 0 && (
            <div style={{ borderTop: '1px solid var(--line-soft)', paddingTop: 10, display: 'flex', flexDirection: 'column', gap: 7 }}>
              {audit.incomplete.map(x => (
                <div key={x.i.code} onClick={() => go('detail', { code: x.i.code })} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
                  <span className="code" style={{ color: 'var(--ink-2)', fontWeight: 600, whiteSpace: 'nowrap' }}>{x.i.code}</span>
                  <span style={{ color: 'var(--ink-4)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>ขาด {x.missing.map(f => FIELD_LABEL[f]).join(', ')}</span>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* out of service */}
        <div className="card enter">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '18px 22px 12px' }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontWeight: 600, fontSize: 15, whiteSpace: 'nowrap' }}>เครื่องงดใช้ / รอซ่อม</div>
              <div className="page-sub">หลักฐานการกันเครื่องที่ชำรุดออกจากการใช้งาน</div>
            </div>
            <span className="figure" style={{ fontSize: 24, color: audit.outCount ? 'var(--danger)' : 'var(--ok)', flex: 'none' }}>{audit.outCount}</span>
          </div>
          <hr className="divider" />
          {audit.outService.length === 0 ? <EmptyState icon={I.check} title="ไม่มีเครื่องงดใช้" sub="เครื่องมือทุกเครื่องพร้อมใช้งาน" /> : (
            <div>
              {audit.outService.slice(0, 6).map((x, idx) => (
                <div key={x.i.code} onClick={() => go('detail', { code: x.i.code })} style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '10px 22px', borderBottom: idx < Math.min(audit.outService.length, 6) - 1 ? '1px solid var(--line-soft)' : 'none', cursor: 'pointer' }}>
                  <span style={{ width: 8, height: 8, borderRadius: 99, background: x.op.key === 'down' ? 'var(--danger)' : 'var(--warn)', flex: 'none' }} />
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{x.i.type}</div>
                    <span className="code" style={{ fontSize: 11, color: 'var(--ink-3)' }}>{x.i.code}</span>
                  </div>
                  <span style={{ fontSize: 11.5, fontWeight: 600, color: x.op.key === 'down' ? 'var(--danger)' : 'var(--warn)' }}>{x.op.label}</span>
                </div>
              ))}
              <div style={{ padding: '10px 22px' }}><span className="chip" onClick={(e) => { e.stopPropagation(); go('repair'); }}>ไปที่งานแจ้งซ่อม <I.chevR size={14} /></span></div>
            </div>
          )}
        </div>

        {/* PM near due */}
        <div className="card enter">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '18px 22px 12px' }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontWeight: 600, fontSize: 15, whiteSpace: 'nowrap' }}>บำรุงรักษา (PM) ใกล้ถึง</div>
              <div className="page-sub">แผน PM ที่ครบกำหนดภายใน {NEAR_DAYS} วัน</div>
            </div>
            <span className="figure" style={{ fontSize: 24, color: audit.pmCount ? 'var(--warn)' : 'var(--ok)', flex: 'none' }}>{audit.pmCount}</span>
          </div>
          <hr className="divider" />
          {audit.pm.length === 0 ? <EmptyState icon={I.check} title="ไม่มี PM ใกล้ถึง" sub="แผนบำรุงรักษาเป็นปัจจุบัน" /> : (
            <div>
              {audit.pm.map((x, idx) => (
                <div key={x.i.code} onClick={() => go('detail', { code: x.i.code })} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 22px', borderBottom: idx < audit.pm.length - 1 ? '1px solid var(--line-soft)' : 'none', cursor: 'pointer' }}>
                  <div style={{ width: 40, textAlign: 'center', flex: 'none' }}>
                    <div className="figure" style={{ fontSize: 20, lineHeight: 1, color: x.d < 0 ? 'var(--danger)' : 'var(--accent)' }}>{Math.abs(x.d)}</div>
                    <div style={{ fontSize: 9, color: 'var(--ink-3)' }}>{x.d < 0 ? 'เกิน(วัน)' : 'วัน'}</div>
                  </div>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{x.i.type}</div>
                    <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>PM {fmtDate(x.pmNext)}</span>
                  </div>
                  <DeptDot dept={x.i.dept} />
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
window.Dashboard = Dashboard;
