/* @jsx React.createElement */
const { useState, useEffect, useRef, useMemo } = React;
/* ============================================================
   Yappari — MACHINE CONTROL (remote, dangerous)
   ============================================================ */
function ControlView({ selectedMachine, machines }) {
  const Y = window.YAPPARI;
  const mid = selectedMachine || machines[0].id;
  const mObj = machines.find(m => m.id === mid);
  const slots = Y.SLOTS[mid];
  const prodMap = Object.fromEntries(Y.PRODUCTS.map(p => [p.id, p]));

  const [hw, setHw] = useState({ led: true, buzzer: false, glassHeater: false, temp: 6, tempMode: 'dingin' });
  const [dispenseSlot, setDispenseSlot] = useState(slots[0].label);
  const [pending, setPending] = useState(null);
  const [log, setLog] = useState([
    { id: 1, time: '−2 mnt', cmd: 'Sinkronisasi inventaris', status: 'ok', detail: 'ACK · 60 slot tersinkron' },
    { id: 2, time: '−14 mnt', cmd: 'Heartbeat ping', status: 'ok', detail: 'Latensi 142ms' },
  ]);
  const logId = useRef(100);
  useEffect(() => { setDispenseSlot(slots[0].label); }, [mid]);

  const now = () => new Date().toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  const sendCommand = (cmd, willFail, apiCmd, apiParams) => {
    const id = ++logId.current;
    setLog(prev => [{ id, time: 'baru saja', cmd, machine: mObj.name, status: 'pending', detail: 'Mengirim perintah…' }, ...prev]);
    // kirim ke backend (tabel vm_commands) bila tersedia
    if (Y.sendCommand && apiCmd) {
      Y.sendCommand(mid, apiCmd, apiParams || {})
        .then(() => setLog(prev => prev.map(l => l.id === id ? { ...l, time: now(), status: willFail ? 'fail' : 'ok', detail: willFail ? 'Mesin offline · menunggu koneksi' : 'Terkirim · menunggu ACK mesin' } : l)))
        .catch((e) => setLog(prev => prev.map(l => l.id === id ? { ...l, time: now(), status: 'fail', detail: 'Gagal kirim: ' + (e.message || 'error') } : l)));
    } else {
      setTimeout(() => {
        setLog(prev => prev.map(l => l.id === id ? { ...l, time: now(), status: willFail ? 'fail' : 'ok', detail: willFail ? 'Timeout · mesin tidak merespons' : 'ACK · perintah dieksekusi' } : l));
      }, 1400);
    }
  };
  const confirm = (cfg) => setPending(cfg);
  const runPending = () => { if (pending) { pending.run(); setPending(null); } };

  const offline = mObj.status === 'offline';

  // ---- section helpers ----
  const sectionCard = (accent, icon, title, sub, children, danger) => React.createElement('div', { className: 'card', style: { overflow: 'hidden', borderTop: '3px solid ' + accent } },
    React.createElement('div', { className: 'card-head' },
      React.createElement('div', { className: 'row gap-3' },
        React.createElement('div', { style: { width: 38, height: 38, borderRadius: 9, background: accent, color: '#fff', display: 'grid', placeItems: 'center', flexShrink: 0 } }, React.createElement(Icon, { name: icon, size: 20 })),
        React.createElement('div', null, React.createElement('h3', null, title), React.createElement('div', { className: 'ch-sub' }, sub))),
      danger && React.createElement('span', { className: 'badge badge-error' }, React.createElement(Icon, { name: 'alert', size: 12 }), 'Hati-hati')),
    React.createElement('div', { className: 'card-pad' }, children),
  );

  const tempColor = hw.tempMode === 'panas' ? 'var(--accent)' : hw.tempMode === 'off' ? 'var(--fg-3)' : 'var(--st-maint)';

  return React.createElement('div', { className: 'view' },
    // danger banner
    React.createElement('div', { style: { borderRadius: 'var(--r-3)', padding: '14px 20px', marginBottom: 'var(--sp-5)', background: 'var(--st-error-bg)', border: '1px solid var(--st-error)', display: 'flex', gap: 14, alignItems: 'center' } },
      React.createElement('div', { className: 'attn-pulse', style: { width: 40, height: 40, borderRadius: 10, background: 'var(--st-error)', color: '#fff', display: 'grid', placeItems: 'center', flexShrink: 0 } }, React.createElement(Icon, { name: 'zap', size: 22 })),
      React.createElement('div', { style: { flex: 1 } },
        React.createElement('div', { style: { fontWeight: 800, color: 'var(--st-error)', fontSize: 15 } }, 'Kontrol jarak jauh langsung — ' + mObj.name),
        React.createElement('div', { style: { fontSize: 13, color: 'var(--fg-2)' } }, 'Perintah dikirim langsung ke perangkat fisik. Pastikan tidak ada pelanggan di depan mesin sebelum mengeksekusi.')),
      offline && React.createElement('span', { className: 'badge badge-offline' }, React.createElement(Icon, { name: 'wifiOff', size: 12 }), 'Offline — perintah akan gagal'),
    ),
    React.createElement('div', { className: 'l-split l-half' },
      React.createElement('div', { className: 'col gap-5' },
        // (a) Dispense
        sectionCard('var(--accent)', 'package', 'Dispense', 'Keluarkan produk untuk pengujian (gratis)', React.createElement('div', { className: 'col gap-4' },
          React.createElement('div', null,
            React.createElement('label', { className: 'field-label' }, 'Pilih slot'),
            React.createElement('select', { className: 'select-native', value: dispenseSlot, onChange: e => setDispenseSlot(e.target.value) },
              slots.map(s => React.createElement('option', { key: s.label, value: s.label }, s.label + ' — ' + prodMap[s.productId].name + (s.cur === 0 ? ' (habis)' : ' · stok ' + s.cur))))),
          React.createElement('button', { className: 'btn btn-accent btn-stamp', style: { justifyContent: 'center' }, onClick: () => confirm({
            danger: true, eyebrow: 'Konfirmasi dispense', title: 'Keluarkan produk dari slot ' + dispenseSlot + '?',
            body: 'Mesin akan memutar coil slot ' + dispenseSlot + ' dan menjatuhkan satu unit ' + prodMap[slots.find(s => s.label === dispenseSlot).productId].name + ' tanpa pembayaran. Gunakan hanya untuk pengujian.',
            confirmLabel: 'Ya, keluarkan', run: () => sendCommand('Dispense slot ' + dispenseSlot + ' (test/gratis)', offline, 'dispense', { slot_label: dispenseSlot, slot_no: (slots.find(function(x){return x.label === dispenseSlot;}) || {}).no }) }) },
            React.createElement(Icon, { name: 'play', size: 16 }), 'Keluarkan produk (gratis / test)'),
        )),
        // (b) Maintenance
        sectionCard('var(--st-warn)', 'cpu', 'Maintenance', 'Operasi tingkat sistem', React.createElement('div', { className: 'col gap-3' },
          React.createElement('div', { className: 'row gap-3', style: { flexWrap: 'wrap' } },
            React.createElement('button', { className: 'btn btn-ghost', style: { flex: 1, minWidth: 130, justifyContent: 'center' }, onClick: () => confirm({
              danger: true, eyebrow: 'Konfirmasi reset', title: 'Reset mesin ' + mObj.name + '?',
              body: 'Mesin akan reboot dan tidak dapat melayani transaksi selama ±90 detik. Semua sesi berjalan akan dibatalkan.', confirmLabel: 'Reset sekarang', run: () => sendCommand('Reset / reboot mesin', offline, 'reset') }) },
              React.createElement(Icon, { name: 'reset', size: 16 }), 'Reset mesin'),
            React.createElement('button', { className: 'btn btn-ghost', style: { flex: 1, minWidth: 130, justifyContent: 'center' }, onClick: () => sendCommand('Self-check diagnostik', offline, 'self_check') },
              React.createElement(Icon, { name: 'check2', size: 16 }), 'Self-check')),
          React.createElement('button', { className: 'btn btn-danger', style: { justifyContent: 'center' }, onClick: () => confirm({
            danger: true, eyebrow: 'Operasi berisiko tinggi', title: 'Jalankan Test Mode (semua slot keluar 1)?',
            body: 'PERINGATAN: mesin akan mengeluarkan SATU unit dari SETIAP slot terisi (hingga 60 produk) secara berurutan. Produk akan jatuh ke tray. Operasi tidak dapat dibatalkan.', confirmLabel: 'Saya paham, jalankan', run: () => sendCommand('Test mode - dispense semua slot x1', offline, 'test_mode') }) },
            React.createElement(Icon, { name: 'alert', size: 16 }), 'Test mode — semua slot keluar 1'),
        ), true),
      ),
      React.createElement('div', { className: 'col gap-5' },
        // (c) Hardware
        sectionCard('var(--st-maint)', 'control', 'Hardware', 'Kontrol periferal mesin', React.createElement('div', { className: 'col gap-4' },
          [['led', 'bulb', 'Lampu LED', 'Penerangan kabin display'], ['buzzer', 'volume', 'Buzzer', 'Suara konfirmasi & alarm'], ['glassHeater', 'flame', 'Pemanas kaca', 'Anti-embun pada pintu kaca']].map(([key, icon, label, sub]) =>
            React.createElement('div', { key, className: 'row', style: { justifyContent: 'space-between', padding: '8px 0', borderBottom: '1px solid var(--border-subtle)' } },
              React.createElement('div', { className: 'row gap-3' },
                React.createElement('div', { style: { width: 34, height: 34, borderRadius: 8, background: 'var(--bg-sunken)', color: hw[key] ? (key === 'glassHeater' ? 'var(--accent)' : 'var(--st-online)') : 'var(--fg-3)', display: 'grid', placeItems: 'center' } }, React.createElement(Icon, { name: icon, size: 18 })),
                React.createElement('div', null, React.createElement('div', { style: { fontWeight: 700, fontSize: 14 } }, label), React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, sub))),
              React.createElement('button', { className: 'toggle ' + (hw[key] ? 'on ' : '') + (key === 'glassHeater' ? 'warn' : ''), onClick: () => { setHw(h => ({ ...h, [key]: !h[key] })); sendCommand((hw[key] ? 'Matikan ' : 'Nyalakan ') + label, offline, key === 'glassHeater' ? 'glass_heat' : key, { enable: !hw[key] }); } })),
          ),
          // temperature
          React.createElement('div', { style: { paddingTop: 6 } },
            React.createElement('div', { className: 'row', style: { justifyContent: 'space-between', marginBottom: 10 } },
              React.createElement('label', { className: 'field-label', style: { margin: 0 } }, 'Set suhu kabin'),
              React.createElement('span', { style: { fontFamily: 'var(--font-display)', fontSize: 26, color: tempColor, lineHeight: 1 } }, hw.tempMode === 'off' ? 'OFF' : hw.temp + '°C')),
            React.createElement('input', { type: 'range', min: 2, max: 25, value: hw.temp, disabled: hw.tempMode === 'off', onChange: e => setHw(h => ({ ...h, temp: +e.target.value })), onMouseUp: () => sendCommand('Set suhu ' + hw.temp + 'C', offline, 'set_temp', { temp: hw.temp, mode: hw.tempMode }), style: { width: '100%', accentColor: tempColor } }),
            React.createElement('div', { className: 'row gap-2', style: { marginTop: 12 } },
              [['dingin', 'snow', 'Dingin'], ['panas', 'flame', 'Panas'], ['off', 'power', 'Off']].map(([m, ic, lab]) =>
                React.createElement('button', { key: m, className: 'chip ' + (hw.tempMode === m ? 'active' : ''), style: { flex: 1, justifyContent: 'center' }, onClick: () => { setHw(h => ({ ...h, tempMode: m })); sendCommand('Mode suhu: ' + lab, offline, 'set_temp', { temp: hw.temp, mode: m }); } }, React.createElement(Icon, { name: ic, size: 14 }), lab))),
          ),
        )),
        // (d) Status / log
        React.createElement(SectionCard, { title: 'Log perintah', sub: 'Riwayat command terakhir', motif: true, bodyStyle: { maxHeight: 320, overflowY: 'auto' } },
          log.map(l => React.createElement('div', { key: l.id, className: 'row gap-3', style: { padding: '11px 20px', borderBottom: '1px solid var(--border-subtle)', alignItems: 'flex-start' } },
            React.createElement('div', { style: { width: 28, height: 28, borderRadius: 7, flexShrink: 0, display: 'grid', placeItems: 'center', background: l.status === 'ok' ? 'var(--st-online-bg)' : l.status === 'fail' ? 'var(--st-error-bg)' : 'var(--st-warn-bg)', color: l.status === 'ok' ? 'var(--st-online)' : l.status === 'fail' ? 'var(--st-error)' : 'var(--st-warn)' } },
              React.createElement(Icon, { name: l.status === 'ok' ? 'check' : l.status === 'fail' ? 'x' : 'refresh', size: 15, className: l.status === 'pending' ? 'spinning' : '' })),
            React.createElement('div', { style: { flex: 1, minWidth: 0 } },
              React.createElement('div', { style: { fontWeight: 700, fontSize: 13.5, color: 'var(--fg-1)' } }, l.cmd),
              React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, l.detail)),
            React.createElement('span', { style: { fontSize: 11, color: 'var(--fg-4)', whiteSpace: 'nowrap', fontFamily: 'var(--font-mono)' } }, l.time))),
        ),
      ),
    ),
    pending && React.createElement(Modal, {
      danger: pending.danger, eyebrow: pending.eyebrow, title: pending.title, onClose: () => setPending(null),
      footer: React.createElement('div', { className: 'row gap-3' },
        React.createElement('button', { className: 'btn btn-ghost', onClick: () => setPending(null) }, 'Batal'),
        React.createElement('button', { className: 'btn btn-danger', onClick: runPending }, React.createElement(Icon, { name: 'zap', size: 15 }), pending.confirmLabel)),
    },
      React.createElement('div', { className: 'row gap-3', style: { alignItems: 'flex-start' } },
        React.createElement('div', { style: { width: 40, height: 40, borderRadius: 10, background: 'var(--st-error-bg)', color: 'var(--st-error)', display: 'grid', placeItems: 'center', flexShrink: 0 } }, React.createElement(Icon, { name: 'alert', size: 22 })),
        React.createElement('p', { style: { margin: 0, color: 'var(--fg-2)', fontSize: 14.5, lineHeight: 1.55 } }, pending.body)),
    ),
  );
}
Object.assign(window, { ControlView });
