/* ============================================================
   floormap.jsx — interactive lab floor map ("แผนผังแล็บ").
   Clean digital schematic: each room/zone is a positioned block
   (percent coords) coloured by the aggregate calibration/PM status
   of the instruments in that department. Click a zone → that
   department's instrument list. Admins can drag/resize/rename
   zones and save the layout to the shared Config tab (key labZones).
   ============================================================ */

const FLOORMAP_DEPTS = ['Blood bank', 'Chemistry', 'Hematology&Microscopy', 'Microbiology', 'Biomolecular', 'Serology', 'Pathology'];

/* default layout — a rough digital trace of the hand-drawn plan;
   admins drag/resize to match exactly, then Save. x/y/w/h are % of canvas. */
const DEFAULT_ZONES = [
  { id: 'z-mol', dept: 'Biomolecular',          name: 'ชีวโมเลกุล (Amp/PCR · Extraction)', x: 31, y: 4,  w: 66, h: 17 },
  { id: 'z-che', dept: 'Chemistry',             name: 'เคมีคลินิก',                         x: 31, y: 24, w: 32, h: 19 },
  { id: 'z-ser', dept: 'Serology',              name: 'ภูมิคุ้มกัน (Immunology)',           x: 65, y: 24, w: 32, h: 19 },
  { id: 'z-hem', dept: 'Hematology&Microscopy', name: 'โลหิตวิทยา / จุลทรรศน์',             x: 31, y: 46, w: 30, h: 24 },
  { id: 'z-bld', dept: 'Blood bank',            name: 'ธนาคารเลือด',                        x: 63, y: 46, w: 34, h: 24 },
  { id: 'z-mic', dept: 'Microbiology',          name: 'จุลชีววิทยา (Bacteria · Iden/Sens)', x: 2,  y: 4,  w: 26, h: 39 },
  { id: 'z-cyt', dept: 'Pathology',             name: 'พยาธิ / เซลล์วิทยา',                 x: 2,  y: 47, w: 26, h: 23 },
];

function fmZoneStats(insts) {
  let total = 0, danger = 0, warn = 0, ok = 0, none = 0;
  insts.forEach(i => {
    if (window.isDecommissioned && window.isDecommissioned(i)) return;
    total++;
    const k = window.statusOf(i).key;
    if (k === 'danger') danger++; else if (k === 'warn') warn++; else if (k === 'none') none++; else ok++;
  });
  const worst = danger ? 'danger' : warn ? 'warn' : total ? 'ok' : 'empty';
  return { total, danger, warn, ok, none, worst };
}
const FM_TONE = {
  danger: { color: 'var(--danger)', soft: 'var(--danger-soft)' },
  warn:   { color: 'var(--warn)',   soft: 'var(--warn-soft)' },
  ok:     { color: 'var(--ok)',     soft: 'var(--ok-soft)' },
  empty:  { color: 'var(--ink-4)',  soft: 'var(--surface-2)' },
};
const fmClamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

function FloorMap({ instruments, go, admin, config, onSaveZones, readOnly }) {
  const initialZones = useMemo(() => {
    try { const raw = config && config.labZones; if (raw) { const z = typeof raw === 'string' ? JSON.parse(raw) : raw; if (Array.isArray(z) && z.length) return z; } } catch (e) {}
    return DEFAULT_ZONES;
  }, []);
  const [zones, setZones] = useState(initialZones);
  const [editing, setEditing] = useState(false);
  const [sel, setSel] = useState(null);
  const [dirty, setDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const canvasRef = useRef(null);

  const canEdit = admin && !readOnly;

  // instruments grouped by department
  const byDept = useMemo(() => {
    const m = {}; instruments.forEach(i => { (m[i.dept] = m[i.dept] || []).push(i); }); return m;
  }, [instruments]);

  const updateZone = (id, patch) => { setZones(zs => zs.map(z => z.id === id ? { ...z, ...patch } : z)); setDirty(true); };

  const startDrag = (e, zone, mode) => {
    if (!editing) return;
    e.preventDefault(); e.stopPropagation();
    setSel(zone.id);
    const rect = canvasRef.current.getBoundingClientRect();
    const sx = e.clientX, sy = e.clientY; const z0 = { ...zone };
    const move = (ev) => {
      const dx = (ev.clientX - sx) / rect.width * 100;
      const dy = (ev.clientY - sy) / rect.height * 100;
      if (mode === 'move') updateZone(zone.id, { x: fmClamp(z0.x + dx, 0, 100 - z0.w), y: fmClamp(z0.y + dy, 0, 100 - z0.h) });
      else updateZone(zone.id, { w: fmClamp(z0.w + dx, 8, 100 - z0.x), h: fmClamp(z0.h + dy, 7, 100 - z0.y) });
    };
    const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up); };
    window.addEventListener('pointermove', move); window.addEventListener('pointerup', up);
  };

  const addZone = () => {
    const id = 'z-' + Math.random().toString(36).slice(2, 7);
    const z = { id, dept: FLOORMAP_DEPTS[0], name: 'ห้องใหม่', x: 35, y: 35, w: 26, h: 18 };
    setZones(zs => [...zs, z]); setSel(id); setDirty(true);
  };
  const delZone = (id) => { setZones(zs => zs.filter(z => z.id !== id)); setSel(null); setDirty(true); };
  const save = async () => { setSaving(true); try { await onSaveZones(zones); setDirty(false); } finally { setSaving(false); } };
  const resetDefault = () => { if (window.confirm('คืนค่าผังเริ่มต้น? (ตำแหน่งที่จัดไว้จะหาย)')) { setZones(DEFAULT_ZONES); setDirty(true); } };

  const selZone = zones.find(z => z.id === sel);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {/* toolbar */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', gap: 14, fontSize: 12, color: 'var(--ink-3)', flexWrap: 'wrap' }}>
          {[['ปกติ', 'var(--ok)'], ['ใกล้ครบ/ใกล้ PM', 'var(--warn)'], ['เกินกำหนด', 'var(--danger)']].map(([l, c]) =>
            <span key={l} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 10, height: 10, borderRadius: 3, background: c }} />{l}</span>)}
        </div>
        {canEdit && (
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <button className={`btn btn-sm${editing ? ' btn-primary' : ''}`} onClick={() => { setEditing(e => !e); setSel(null); }}>
              <I.edit size={14} /> {editing ? 'กำลังจัดผัง' : 'จัดผัง (admin)'}
            </button>
            {editing && <button className="btn btn-sm" onClick={addZone}><I.plus size={14} /> เพิ่มห้อง</button>}
            {editing && <button className="btn btn-sm" onClick={resetDefault}><I.refresh size={14} /> ค่าเริ่มต้น</button>}
            {editing && <button className="btn btn-sm btn-primary" disabled={!dirty || saving} onClick={save}>{saving ? 'กำลังบันทึก…' : (dirty ? 'บันทึกผัง' : 'บันทึกแล้ว')}</button>}
          </div>
        )}
      </div>

      {/* canvas */}
      <div className="card" style={{ padding: 14 }}>
        <div ref={canvasRef} onClick={() => setSel(null)} style={{
          position: 'relative', width: '100%', aspectRatio: '16 / 10', borderRadius: 12,
          background: 'repeating-linear-gradient(0deg, var(--surface-2) 0 1px, transparent 1px 28px), repeating-linear-gradient(90deg, var(--surface-2) 0 1px, transparent 1px 28px), var(--surface)',
          border: '1px solid var(--line)', overflow: 'hidden', cursor: editing ? 'default' : 'auto',
        }}>
          {zones.map(z => {
            const st = fmZoneStats(byDept[z.dept] || []);
            const tone = FM_TONE[st.worst] || FM_TONE.empty;
            const on = sel === z.id;
            return (
              <div key={z.id}
                onClick={(e) => { e.stopPropagation(); if (editing) setSel(z.id); else go('inventory', { dept: z.dept }); }}
                onPointerDown={(e) => editing && startDrag(e, z, 'move')}
                title={editing ? 'ลากเพื่อย้าย' : 'คลิกเพื่อดูเครื่องในห้องนี้'}
                style={{
                  position: 'absolute', left: z.x + '%', top: z.y + '%', width: z.w + '%', height: z.h + '%',
                  background: tone.soft, border: `2px solid ${on ? 'var(--accent)' : tone.color}`,
                  borderRadius: 10, padding: 9, cursor: editing ? 'move' : 'pointer',
                  display: 'flex', flexDirection: 'column', gap: 4, overflow: 'hidden',
                  boxShadow: on ? '0 0 0 3px var(--accent-ring)' : 'none', transition: 'box-shadow .12s',
                }}>
                <div style={{ display: 'flex', alignItems: 'flex-start', gap: 6 }}>
                  <span style={{ width: 22, height: 22, borderRadius: 6, background: deptColor(z.dept), color: '#fff', display: 'grid', placeItems: 'center', flex: 'none' }}>
                    {(typeof deptIcon === 'function' && deptIcon(z.dept)) ? (() => { const DI = deptIcon(z.dept); return <DI size={13} />; })() : null}
                  </span>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontWeight: 700, fontSize: 12.5, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{z.name}</div>
                    <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>{(DEPT_META[z.dept] || {}).short || z.dept}</div>
                  </div>
                  <span className="figure" style={{ fontSize: 17, color: tone.color, lineHeight: 1 }}>{st.total}</span>
                </div>
                {st.worst !== 'empty' && (
                  <div style={{ marginTop: 'auto', display: 'flex', gap: 8, fontSize: 10, flexWrap: 'wrap' }}>
                    {st.danger > 0 && <span style={{ color: 'var(--danger)', fontWeight: 700 }}>เกิน {st.danger}</span>}
                    {st.warn > 0 && <span style={{ color: 'var(--warn)', fontWeight: 700 }}>ใกล้ครบ {st.warn}</span>}
                    <span style={{ color: 'var(--ok)' }}>ปกติ {st.ok}</span>
                  </div>
                )}
                {editing && (
                  <div onPointerDown={(e) => startDrag(e, z, 'resize')} title="ลากเพื่อปรับขนาด"
                    style={{ position: 'absolute', right: 2, bottom: 2, width: 14, height: 14, cursor: 'nwse-resize', borderRight: '3px solid var(--accent)', borderBottom: '3px solid var(--accent)', borderBottomRightRadius: 6 }} />
                )}
              </div>
            );
          })}
        </div>
      </div>

      {/* edit panel for the selected zone */}
      {editing && selZone && (
        <div className="card card-pad enter" style={{ display: 'flex', gap: 14, alignItems: 'flex-end', flexWrap: 'wrap' }}>
          <div style={{ flex: '1 1 220px' }}>
            <label className="field-label">ชื่อห้อง</label>
            <input className="input" value={selZone.name} onChange={e => updateZone(selZone.id, { name: e.target.value })} />
          </div>
          <div style={{ flex: '1 1 180px' }}>
            <label className="field-label">แผนก (ใช้ดึงเครื่อง/สถานะ)</label>
            <select className="select" value={selZone.dept} onChange={e => updateZone(selZone.id, { dept: e.target.value })}>
              {FLOORMAP_DEPTS.map(d => <option key={d} value={d}>{(DEPT_META[d] || {}).short || d}</option>)}
            </select>
          </div>
          <button className="btn btn-sm" style={{ color: 'var(--danger)', borderColor: 'var(--danger)' }} onClick={() => delZone(selZone.id)}><I.trash size={14} /> ลบห้องนี้</button>
        </div>
      )}

      <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>
        {canEdit
          ? (editing ? 'โหมดจัดผัง: ลากกล่องเพื่อย้าย · ลากมุมขวาล่างเพื่อปรับขนาด · คลิกเลือกห้องเพื่อแก้ชื่อ/แผนก · อย่าลืมกด “บันทึกผัง”' : 'คลิกที่ห้องเพื่อดูเครื่องในแผนกนั้น · กด “จัดผัง” เพื่อปรับตำแหน่งห้องให้ตรงแล็บจริง')
          : 'คลิกที่ห้องเพื่อดูเครื่องในแผนกนั้น · สีกรอบ = สถานะรวมของห้อง'}
      </div>
    </div>
  );
}
window.FloorMap = FloorMap;
