/* ============================================================
   calplan.jsx — annual calibration master plan (ทะเบียน/แผน
   สอบเทียบประจำปี). Year grid: instruments × 12 months, marking
   each instrument's calibration-due month, grouped by department.
   ============================================================ */
function CalPlan({ instruments, go }) {
  const beYears = [2568, 2569, 2570];
  const [yearBE, setYearBE] = useState(TODAY.getFullYear() + 543);
  const yearAD = yearBE - 543;
  const [deptFilter, setDeptFilter] = useState('all');
  const [typeFilter, setTypeFilter] = useState('all');
  const [expOpen, setExpOpen] = useState(false);
  const expRef = useRef(null);
  const [groupOpen, setGroupOpen] = useState(() => {
    const o = {}; Object.keys(DEPT_META).forEach(d => o[d] = true); return o;
  });

  useEffect(() => {
    const h = (e) => { if (expRef.current && !expRef.current.contains(e.target)) setExpOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, []);

  const MON = ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'];
  const thisMonth = (TODAY.getFullYear() === yearAD) ? TODAY.getMonth() : -1;

  // available instrument types (by code abbreviation) for the filter
  const typeOptions = useMemo(() => {
    const m = {};
    instruments.forEach(i => {
      const ab = (i.code || '').split('-')[2];
      if (ab) m[ab] = m[ab] || { ab, name: i.typeName || i.type };
    });
    return Object.values(m).sort((a, b) => a.ab.localeCompare(b.ab));
  }, [instruments]);

  // apply dept + type filters → the working set the plan/export use
  const filtered = useMemo(() => instruments.filter(i => {
    if (deptFilter !== 'all' && i.dept !== deptFilter) return false;
    if (typeFilter !== 'all' && (i.code || '').split('-')[2] !== typeFilter) return false;
    return true;
  }), [instruments, deptFilter, typeFilter]);

  const scopeLabel = [
    deptFilter !== 'all' ? (DEPT_META[deptFilter] || {}).short || deptFilter : null,
    typeFilter !== 'all' ? (typeOptions.find(t => t.ab === typeFilter) || {}).name : null,
  ].filter(Boolean).join(' · ') || 'ทุกแผนก/ทุกชนิด';
  const fnameSuffix = (deptFilter !== 'all' ? '-' + (DEPT_META[deptFilter] || {}).abbr : '') + (typeFilter !== 'all' ? '-' + typeFilter : '') + '-' + yearBE;

  // build plan: instruments with an exp date falling in selected year
  const plan = useMemo(() => {
    const byDept = {};
    const monthLoad = Array(12).fill(0);
    let planned = 0;
    filtered.forEach(i => {
      if (!i.exp) return;
      const d = parseD(i.exp);
      if (!d || d.getFullYear() !== yearAD) return;
      const mo = d.getMonth();
      const dept = i.dept || '—';
      (byDept[dept] = byDept[dept] || []).push({ i, mo, day: d.getDate(), s: statusOf(i), cal: i.cal });
      monthLoad[mo]++;
      planned++;
    });
    Object.values(byDept).forEach(arr => arr.sort((a, b) => a.mo - b.mo || a.day - b.day));
    const depts = Object.keys(DEPT_META).filter(d => byDept[d]).map(d => ({ dept: d, rows: byDept[d] }));
    const noPlan = filtered.filter(i => !i.exp).length;
    const maxLoad = Math.max(1, ...monthLoad);
    return { depts, monthLoad, planned, noPlan, maxLoad };
  }, [filtered, yearAD]);

  const cellColor = (key) => key === 'danger' ? 'var(--danger)' : key === 'warn' ? 'var(--warn)' : 'var(--ok)';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      {/* toolbar */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <div className="seg">
          {beYears.map(y => <button key={y} className={yearBE === y ? 'on' : ''} onClick={() => setYearBE(y)}>{y}</button>)}
        </div>
        <select className="select" style={{ width: 'auto', minWidth: 150 }} value={deptFilter} onChange={e => setDeptFilter(e.target.value)}>
          <option value="all">ทุกแผนก</option>
          {Object.keys(DEPT_META).map(d => <option key={d} value={d}>{(DEPT_META[d] || {}).short || d}</option>)}
        </select>
        <select className="select" style={{ width: 'auto', minWidth: 160, maxWidth: 220 }} value={typeFilter} onChange={e => setTypeFilter(e.target.value)}>
          <option value="all">ทุกชนิดเครื่อง</option>
          {typeOptions.map(t => <option key={t.ab} value={t.ab}>{t.ab} · {t.name}</option>)}
        </select>
        {(deptFilter !== 'all' || typeFilter !== 'all') && (
          <button className="chip" onClick={() => { setDeptFilter('all'); setTypeFilter('all'); }}><I.close size={13} /> ล้างตัวกรอง</button>
        )}
        <div style={{ marginLeft: 'auto', position: 'relative' }} ref={expRef}>
          <button className="btn" onClick={() => setExpOpen(o => !o)}><I.download size={16} /> ส่งออก / พิมพ์ <I.chevD size={14} /></button>
          {expOpen && (
            <div className="card enter" style={{ position: 'absolute', right: 0, top: 'calc(100% + 6px)', width: 260, zIndex: 30, boxShadow: 'var(--shadow-lg)', padding: 6 }}>
              <div style={{ fontSize: 11, color: 'var(--ink-3)', padding: '6px 10px' }}>แผน {plan.planned} เครื่อง · ปี {yearBE} · {scopeLabel}</div>
              <button className="menu-item" onClick={() => { window.exportCalPlanCSV(filtered, yearAD, 'calibration-plan' + fnameSuffix); setExpOpen(false); }}>
                <span style={{ width: 30, height: 30, borderRadius: 8, background: 'var(--ok-soft)', color: 'var(--ok)', display: 'grid', placeItems: 'center', flex: 'none' }}><I.grid size={16} /></span>
                <div><div style={{ fontWeight: 600, fontSize: 13 }}>Excel (.csv)</div><div style={{ fontSize: 11, color: 'var(--ink-3)' }}>แผนสอบเทียบตามตัวกรอง</div></div>
              </button>
              <button className="menu-item" onClick={() => { window.printCalPlan(filtered, yearAD, { scope: scopeLabel }); setExpOpen(false); }}>
                <span style={{ width: 30, height: 30, borderRadius: 8, background: 'var(--danger-soft)', color: 'var(--danger)', display: 'grid', placeItems: 'center', flex: 'none' }}><I.list size={16} /></span>
                <div><div style={{ fontWeight: 600, fontSize: 13 }}>PDF / พิมพ์แผน</div><div style={{ fontSize: 11, color: 'var(--ink-3)' }}>เรียงตามเดือนครบกำหนด</div></div>
              </button>
            </div>
          )}
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
        <div style={{ fontSize: 13, color: 'var(--ink-3)' }}>
          วางแผนสอบเทียบ <b className="tnum" style={{ color: 'var(--ink)' }}>{plan.planned}</b> เครื่อง ในปี พ.ศ. {yearBE}
          {plan.noPlan > 0 && <> · ยังไม่กำหนดแผน <b className="tnum" style={{ color: 'var(--warn)' }}>{plan.noPlan}</b></>}
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 14, fontSize: 12, color: 'var(--ink-3)' }}>
          {[['ปกติ', 'var(--ok)'], ['ใกล้ครบ', 'var(--warn)'], ['เกินกำหนด', 'var(--danger)']].map(([l, c]) =>
            <span key={l} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 9, height: 9, borderRadius: 3, background: c }} />{l}</span>)}
        </div>
      </div>

      {/* month-load heatmap header */}
      <div className="card card-pad enter">
        <div style={{ fontWeight: 600, fontSize: 14.5, marginBottom: 12 }}>ภาระงานสอบเทียบรายเดือน · {yearBE}</div>
        <div className="cp-loadrow">
          {plan.monthLoad.map((n, m) => (
            <div key={m} className={`cp-loadcell${m === thisMonth ? ' now' : ''}`} title={`${MON[m]} · ${n} เครื่อง`}>
              <div className="cp-loadbar-track">
                <div className="cp-loadbar" style={{ height: `${Math.max(6, (n / plan.maxLoad) * 100)}%`, opacity: n ? 1 : 0.25 }} />
              </div>
              <div className="cp-loadnum tnum">{n}</div>
              <div className="cp-loadmon">{MON[m]}</div>
            </div>
          ))}
        </div>
      </div>

      {/* per-department year grid */}
      {plan.depts.length === 0 ? (
        <div className="card"><EmptyState icon={I.calendar} title="ไม่มีแผนสอบเทียบตามเงื่อนไข" sub={`ไม่พบเครื่องมือที่ครบกำหนดในปี ${yearBE}${scopeLabel !== 'ทุกแผนก/ทุกชนิด' ? ' · ' + scopeLabel : ''}`} /></div>
      ) : plan.depts.map(({ dept, rows }) => {
        const open = groupOpen[dept];
        return (
          <div className="card enter" key={dept} style={{ overflow: 'hidden' }}>
            <button className="cp-dept-head" onClick={() => setGroupOpen(o => ({ ...o, [dept]: !o[dept] }))}>
              <I.chevR size={15} style={{ transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .2s', color: 'var(--ink-3)' }} />
              <DeptDot dept={dept} />
              <span style={{ fontWeight: 600, fontSize: 14.5 }}>{(DEPT_META[dept] || {}).short || dept}</span>
              <span className="tnum" style={{ fontSize: 12, color: 'var(--ink-3)' }}>{rows.length} เครื่อง</span>
            </button>
            {open && (
              <div className="tbl-wrap">
                <table className="tbl cp-grid">
                  <thead>
                    <tr>
                      <th className="cp-name-col">เครื่องมือ</th>
                      {MON.map((m, i) => <th key={i} className={`cp-mon-col${i === thisMonth ? ' now' : ''}`}>{m}</th>)}
                    </tr>
                  </thead>
                  <tbody>
                    {rows.map(({ i, mo, day, s, cal }) => {
                      const calMo = cal ? (parseD(cal).getFullYear() === yearAD ? parseD(cal).getMonth() : -1) : -1;
                      return (
                        <tr key={i.code} onClick={() => go('detail', { code: i.code })}>
                          <td className="cp-name-col">
                            <div style={{ fontWeight: 600, fontSize: 12.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: 230 }}>{i.type}</div>
                            <span className="code" style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>{i.code}</span>
                          </td>
                          {MON.map((_, m) => (
                            <td key={m} className={`cp-cell${m === thisMonth ? ' now' : ''}`}>
                              {m === mo && (
                                <span className="cp-dot" style={{ background: cellColor(s.key) }} title={`ครบกำหนด ${fmtDate(i.exp)}`}>{day}</span>
                              )}
                              {m === calMo && m !== mo && (
                                <span className="cp-dot done" title={`สอบเทียบล่าสุด ${fmtDate(cal)}`} />
                              )}
                            </td>
                          ))}
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        );
      })}

      <div style={{ display: 'flex', gap: 16, fontSize: 12, color: 'var(--ink-3)', flexWrap: 'wrap', paddingLeft: 4 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}><span className="cp-dot" style={{ position: 'static', background: 'var(--ok)', width: 20, height: 20, fontSize: 10 }}>12</span> เลขในวงกลม = วันที่ครบกำหนดสอบเทียบ</span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}><span className="cp-dot done" style={{ position: 'static' }} /> สอบเทียบล่าสุดในปีนี้</span>
      </div>
    </div>
  );
}
window.CalPlan = CalPlan;
