// VendingPick — v2 with Routing, Duplicate Detection, OCR Confidence, Camera Scanner
const { useState, useEffect, useRef, useCallback } = React;

// ─── API ─────────────────────────────────────────────────────────────────────
const api = {
  async get(url) {
    const r = await fetch(url, { credentials: 'include' });
    if (!r.ok) throw await r.json().catch(() => ({ error: r.statusText }));
    return r.json();
  },
  async post(url, body) {
    const r = await fetch(url, { method: 'POST', credentials: 'include',
      headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
    if (!r.ok) throw await r.json().catch(() => ({ error: r.statusText }));
    return r.json();
  },
  async put(url, body) {
    const r = await fetch(url, { method: 'PUT', credentials: 'include',
      headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
    if (!r.ok) throw await r.json().catch(() => ({ error: r.statusText }));
    return r.json();
  },
  async del(url) {
    const r = await fetch(url, { method: 'DELETE', credentials: 'include' });
    if (!r.ok) throw await r.json().catch(() => ({ error: r.statusText }));
    return r.json();
  },
  async upload(url, formData) {
    const r = await fetch(url, { method: 'POST', credentials: 'include', body: formData });
    const data = await r.json().catch(() => ({ error: r.statusText }));
    if (!r.ok) throw data;
    return data;
  }
};

// ─── Toast ────────────────────────────────────────────────────────────────────
function Toast({ toasts }) {
  return React.createElement('div', { className: 'toast-container' },
    toasts.map(t => React.createElement('div', { key: t.id, className: `toast ${t.type}` },
      React.createElement('span', null, t.type==='success'?'✓':t.type==='error'?'✕':'ℹ'),
      t.msg
    ))
  );
}

// ─── Constants ────────────────────────────────────────────────────────────────
const COLORS = ['#f97316','#3b82f6','#22c55e','#a855f7','#ef4444','#eab308','#06b6d4','#ec4899','#84cc16','#f59e0b'];

function statusLabel(s) {
  return {open:'Offen',assigned:'Zugewiesen',in_progress:'In Bearbeitung',completed:'Abgeschlossen'}[s]||s;
}
function StatusBadge({ status }) {
  return React.createElement('span', { className: `badge badge-${status}` }, statusLabel(status));
}
function ConfBadge({ level, conf }) {
  if (!level || level === 'high') return null;
  const cls = level === 'low' ? 'badge-conf-low' : 'badge-conf-med';
  const label = level === 'low' ? `⚠ OCR ${conf}%` : `~ ${conf}%`;
  return React.createElement('span', { className: `badge ${cls}`, title: 'OCR-Konfidenz – bitte manuell prüfen' }, label);
}

// ─── Progress Ring ────────────────────────────────────────────────────────────
function ProgressRing({ done, total, size=72 }) {
  const r = size/2-7, circ = 2*Math.PI*r, pct = total>0 ? done/total : 0;
  return React.createElement('div', { className: 'progress-ring', style:{width:size,height:size} },
    React.createElement('svg', { width:size, height:size },
      React.createElement('circle', {cx:size/2,cy:size/2,r,fill:'none',stroke:'var(--border)',strokeWidth:6}),
      React.createElement('circle', {cx:size/2,cy:size/2,r,fill:'none',
        stroke: pct===1?'var(--green)':'var(--accent)', strokeWidth:6,
        strokeDasharray:circ, strokeDashoffset:circ*(1-pct), strokeLinecap:'round',
        style:{transition:'stroke-dashoffset .4s ease'}})
    ),
    React.createElement('div', { className:'progress-ring-text' }, `${done}/${total}`)
  );
}

// ─── Modal ────────────────────────────────────────────────────────────────────
function Modal({ title, onClose, children, footer }) {
  useEffect(() => {
    const h = e => e.key==='Escape' && onClose();
    document.addEventListener('keydown', h);
    return () => document.removeEventListener('keydown', h);
  }, []);
  return React.createElement('div', { className:'modal-overlay', onClick:e=>e.target===e.currentTarget&&onClose() },
    React.createElement('div', { className:'modal' },
      React.createElement('div', { className:'modal-header' },
        React.createElement('div', { className:'modal-title' }, title),
        React.createElement('button', { className:'btn btn-sm btn-secondary btn-icon', onClick:onClose }, '✕')
      ),
      React.createElement('div', { className:'modal-body' }, children),
      footer && React.createElement('div', { className:'modal-footer' }, footer)
    )
  );
}

// ─── Camera Scanner ───────────────────────────────────────────────────────────
function CameraScanner({ onScan, onClose }) {
  const videoRef = useRef();
  const canvasRef = useRef();
  const streamRef = useRef();
  const animRef = useRef();
  const [status, setStatus] = useState('Kamera wird gestartet...');
  const [error, setError] = useState('');

  useEffect(() => {
    let active = true;
    navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width:1280, height:720 } })
      .then(stream => {
        if (!active) { stream.getTracks().forEach(t => t.stop()); return; }
        streamRef.current = stream;
        videoRef.current.srcObject = stream;
        videoRef.current.play();
        setStatus('Barcode vor die Kamera halten...');
        startScan();
      })
      .catch(e => setError('Kamera nicht verfügbar: ' + e.message));

    return () => {
      active = false;
      cancelAnimationFrame(animRef.current);
      streamRef.current?.getTracks().forEach(t => t.stop());
    };
  }, []);

  function startScan() {
    // Use BarcodeDetector API if available (Chrome/Edge on iPad with iOS 17+)
    if ('BarcodeDetector' in window) {
      const detector = new BarcodeDetector({ formats: ['ean_13','ean_8','code_128','code_39','itf','upc_a','upc_e'] });
      const tick = async () => {
        if (videoRef.current?.readyState === 4) {
          try {
            const codes = await detector.detect(videoRef.current);
            if (codes.length > 0) {
              const code = codes[0].rawValue;
              vibrate();
              onScan(code);
              return;
            }
          } catch (_) {}
        }
        animRef.current = requestAnimationFrame(tick);
      };
      animRef.current = requestAnimationFrame(tick);
    } else {
      // Fallback: draw to canvas, show message
      setStatus('BarcodeDetector nicht verfügbar. Bitte Bluetooth-Scanner verwenden oder manuell eingeben.');
    }
  }

  function vibrate() {
    if (navigator.vibrate) navigator.vibrate([100, 50, 100]);
  }

  return React.createElement(Modal, { title: '📷 Kamera-Scanner', onClose,
    footer: React.createElement('button', { className:'btn btn-secondary', onClick:onClose }, 'Schließen')
  },
    error
      ? React.createElement('div', { className:'text-danger' }, error)
      : React.createElement('div', null,
          React.createElement('div', { style:{position:'relative',borderRadius:12,overflow:'hidden',background:'#000'} },
            React.createElement('video', {
              ref: videoRef, playsInline:true, muted:true,
              style:{width:'100%',maxHeight:300,display:'block',objectFit:'cover'}
            }),
            // Scan reticle
            React.createElement('div', { className:'scan-reticle' })
          ),
          React.createElement('canvas', { ref:canvasRef, style:{display:'none'} }),
          React.createElement('div', { className:'text-muted text-sm mt-4', style:{textAlign:'center'} }, status),
          React.createElement('div', { className:'mt-4' },
            React.createElement('label', { className:'form-label' }, 'Oder manuell eingeben:'),
            React.createElement('div', { className:'flex gap-2' },
              React.createElement('input', {
                className:'form-input', id:'manual-barcode', placeholder:'Artikelnummer...',
                onKeyDown: e => { if (e.key==='Enter') { onScan(e.target.value); e.target.value=''; } },
                autoFocus: true
              }),
              React.createElement('button', { className:'btn btn-primary',
                onClick: () => {
                  const v = document.getElementById('manual-barcode')?.value;
                  if (v) { onScan(v); document.getElementById('manual-barcode').value=''; }
                }
              }, 'OK')
            )
          )
        )
  );
}

// ─── Login ────────────────────────────────────────────────────────────────────
function LoginView({ onLogin }) {
  const [form, setForm] = useState({ username:'', password:'' });
  const [err, setErr] = useState('');
  const [loading, setLoading] = useState(false);
  const submit = async () => {
    setErr(''); setLoading(true);
    try { onLogin(await api.post('/api/auth/login', form)); }
    catch(e) { setErr(e.error||'Login fehlgeschlagen'); }
    finally { setLoading(false); }
  };
  return React.createElement('div', { className:'login-wrap' },
    React.createElement('div', { className:'login-card' },
      React.createElement('img', { src:'/martin_gruppe_logo.svg', className:'login-logo-img', alt:'Martin Gruppe' }),
      React.createElement('div', { className:'login-product' }, 'VendingPick'),
      React.createElement('div', { className:'login-sub' }, 'Digitales Picklisten-System'),
      ['username','password'].map(k =>
        React.createElement('div', { key:k, className:'form-group' },
          React.createElement('label', { className:'form-label' }, k==='username'?'Benutzername':'Passwort'),
          React.createElement('input', {
            type: k==='password'?'password':'text', className:'form-input', value:form[k],
            autoCapitalize:'none', autoFocus: k==='username',
            onChange: e => setForm(f=>({...f,[k]:e.target.value})),
            onKeyDown: e => e.key==='Enter' && submit()
          })
        )
      ),
      err && React.createElement('div', { className:'text-danger text-sm mt-2 mb-4' }, err),
      React.createElement('button', { className:'btn btn-primary btn-full btn-lg', onClick:submit,
        disabled: loading||!form.username||!form.password
      }, loading ? React.createElement('div',{className:'spinner'}) : '→ Anmelden')
    )
  );
}

// ─── Upload Modal with Duplicate Handling ─────────────────────────────────────
function UploadModal({ onClose, onDone, showToast }) {
  const [drag, setDrag] = useState(false);
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState('');
  const [duplicate, setDuplicate] = useState(null);
  const [pendingFile, setPendingFile] = useState(null);
  const fileRef = useRef();

  const handleFile = async (file) => {
    if (!file) return;
    setLoading(true); setErr(''); setDuplicate(null);
    try {
      const fd = new FormData(); fd.append('file', file);
      await api.upload('/api/upload', fd);
      onDone();
    } catch(e) {
      if (e.error === 'duplicate') {
        setDuplicate(e);
        setPendingFile(file);
      } else {
        setErr(e.error || 'Upload-Fehler');
      }
    } finally { setLoading(false); }
  };

  const forceImport = async () => {
    if (!pendingFile) return;
    setLoading(true);
    try {
      const fd = new FormData(); fd.append('file', pendingFile);
      await api.upload('/api/upload/force', fd);
      onDone();
    } catch(e) { setErr(e.error||'Fehler'); }
    finally { setLoading(false); }
  };

  if (duplicate) {
    return React.createElement(Modal, { title:'⚠ Duplikat erkannt', onClose,
      footer: React.createElement('div', { className:'flex gap-2' },
        React.createElement('button', { className:'btn btn-secondary', onClick:onClose }, 'Abbrechen'),
        React.createElement('button', { className:'btn btn-primary', onClick:forceImport, disabled:loading },
          loading ? React.createElement('div',{className:'spinner'}) : 'Trotzdem importieren')
      )
    },
      React.createElement('div', { className:'duplicate-warning' },
        React.createElement('div', { className:'duplicate-icon' }, '🔄'),
        React.createElement('div', null,
          React.createElement('div', { className:'bold' }, duplicate.message),
          React.createElement('div', { className:'text-muted text-sm mt-2' },
            `${duplicate.parsed.items} Artikel · Tour ${duplicate.parsed.tour_nr} · ${duplicate.parsed.date}`)
        )
      ),
      React.createElement('div', { className:'text-muted text-sm mt-4' },
        'Möchten Sie diese Liste trotzdem als neue Pickliste anlegen?')
    );
  }

  return React.createElement(Modal, { title:'PDF hochladen', onClose,
    footer: React.createElement('button', { className:'btn btn-secondary', onClick:onClose }, 'Abbrechen')
  },
    React.createElement('div', {
      className:`upload-zone${drag?' drag-over':''}`,
      onClick: () => fileRef.current?.click(),
      onDragOver: e => { e.preventDefault(); setDrag(true); },
      onDragLeave: () => setDrag(false),
      onDrop: e => { e.preventDefault(); setDrag(false); handleFile(e.dataTransfer.files[0]); }
    },
      React.createElement('div', { className:'upload-zone-icon' }, loading?'⏳':'📄'),
      React.createElement('div', { className:'upload-zone-text' },
        loading ? 'OCR läuft...' : 'PDF hier ablegen oder antippen'),
      React.createElement('div', { className:'upload-zone-hint' }, 'Packliste der Planungssoftware')
    ),
    React.createElement('input', { ref:fileRef, type:'file', accept:'.pdf', style:{display:'none'},
      onChange: e => handleFile(e.target.files[0]) }),
    err && React.createElement('div', { className:'text-danger text-sm mt-4' }, err),
    React.createElement('div', { className:'text-muted text-sm mt-4' },
      '💡 PDFs werden auch automatisch aus dem Watchfolder eingelesen (90s Verzögerung).')
  );
}

// ─── Picklists Dashboard ──────────────────────────────────────────────────────
function PicklistsView({ user, onSelect, showToast }) {
  const [lists, setLists] = useState([]);
  const [loading, setLoading] = useState(true);
  const [showUpload, setShowUpload] = useState(false);
  const [filter, setFilter] = useState('all');

  const load = useCallback(async () => {
    try { setLists(await api.get('/api/picklists')); }
    catch(e) { showToast('Fehler beim Laden','error'); }
    finally { setLoading(false); }
  }, []);
  useEffect(() => { load(); }, []);

  const filtered = filter==='all' ? lists : lists.filter(l=>l.status===filter);

  const del = async (id, e) => {
    e.stopPropagation();
    if (!confirm('Pickliste löschen?')) return;
    await api.del(`/api/picklists/${id}`);
    showToast('Gelöscht','success'); load();
  };

  return React.createElement('div', null,
    React.createElement('div', { className:'flex items-center justify-between mb-6' },
      React.createElement('div', { className:'page-title' }, '📋 Picklisten'),
      React.createElement('div', { className:'flex gap-2' },
        React.createElement('button', { className:'btn btn-secondary btn-sm', onClick:load }, '↻'),
        React.createElement('button', { className:'btn btn-primary btn-sm', onClick:()=>setShowUpload(true) },
          '+ PDF hochladen')
      )
    ),
    React.createElement('div', { className:'flex gap-2 mb-4' },
      ['all','open','in_progress','completed'].map(s =>
        React.createElement('button', { key:s, className:`btn btn-sm ${filter===s?'btn-primary':'btn-secondary'}`,
          onClick:()=>setFilter(s) }, s==='all'?'Alle':statusLabel(s))
      )
    ),
    loading
      ? React.createElement('div', { className:'loading-wrap' }, React.createElement('div',{className:'spinner'}))
      : filtered.length===0
        ? React.createElement('div', { className:'empty-state' },
            React.createElement('div',{className:'empty-state-icon'},'📦'),
            React.createElement('div',{className:'empty-state-text'},'Keine Picklisten'),
            React.createElement('div',{className:'empty-state-hint'},'PDF hochladen oder Watchfolder nutzen'))
        : React.createElement('div', { className:'card' },
            React.createElement('table', { className:'pick-table' },
              React.createElement('thead', null, React.createElement('tr', null,
                React.createElement('th',null,'Tour / Typ'),
                React.createElement('th',null,'Kunde'),
                React.createElement('th',null,'Datum'),
                React.createElement('th',null,'Fortschritt'),
                React.createElement('th',null,'Status'),
                React.createElement('th',null,'Bearbeiter'),
                user.role==='admin' && React.createElement('th',null,'')
              )),
              React.createElement('tbody', null, filtered.map(l => {
                const pct = l.total_items>0 ? Math.round(l.done_items/l.total_items*100) : 0;
                const hasOcrWarning = (l.low_conf_items||0)>0;
                return React.createElement('tr', { key:l.id, onClick:()=>onSelect(l.id) },
                  React.createElement('td', null,
                    React.createElement('div',{className:'bold'},
                      l.tour_nr?`Tour ${l.tour_nr}`:'–',
                      hasOcrWarning && React.createElement('span',{
                        className:'ocr-warning-dot',title:`${l.low_conf_items} Artikel mit niedriger OCR-Konfidenz`
                      },'⚠')),
                    React.createElement('div',{className:'text-xs text-muted mono'}, l.tour_type||l.automat_name||'–')
                  ),
                  React.createElement('td',null,
                    React.createElement('div',null,l.customer_name||'–'),
                    React.createElement('div',{className:'text-xs text-muted'},l.customer_location||'')
                  ),
                  React.createElement('td',{className:'mono text-sm'},l.date||l.created_at?.slice(0,10)||'–'),
                  React.createElement('td',null,
                    React.createElement('div',{className:'flex items-center gap-2'},
                      React.createElement('div',{style:{width:80}},
                        React.createElement('div',{className:'progress-bar-wrap'},
                          React.createElement('div',{className:'progress-bar-fill',style:{width:`${pct}%`}}))),
                      React.createElement('span',{className:'text-xs mono text-muted'},`${l.done_items||0}/${l.total_items||0}`)
                    )
                  ),
                  React.createElement('td',null,React.createElement(StatusBadge,{status:l.status})),
                  React.createElement('td',null, l.assigned_name
                    ? React.createElement('div',{className:'flex items-center gap-2'},
                        React.createElement('div',{className:'user-dot',
                          style:{background:l.assigned_color,width:24,height:24,fontSize:10}
                        }, l.assigned_name.charAt(0).toUpperCase()),
                        React.createElement('span',{className:'text-sm'},l.assigned_name))
                    : React.createElement('span',{className:'text-muted text-sm'},'–')
                  ),
                  user.role==='admin' && React.createElement('td',null,
                    React.createElement('button',{className:'btn btn-sm btn-danger btn-icon',
                      onClick:e=>del(l.id,e)},'✕'))
                );
              }))
            )
        ),
    showUpload && React.createElement(UploadModal, { showToast,
      onClose:()=>setShowUpload(false),
      onDone:()=>{ setShowUpload(false); load(); showToast('Pickliste importiert!','success'); }
    })
  );
}

// ─── Pick Session ─────────────────────────────────────────────────────────────
function PickSessionView({ listId, user, onBack, showToast }) {
  const [list, setList] = useState(null);
  const [loading, setLoading] = useState(true);
  const [scanVal, setScanVal] = useState('');
  const [showCompleted, setShowCompleted] = useState(false);
  const [routeMode, setRouteMode] = useState('lager');
  const [showCamera, setShowCamera] = useState(false);
  const [wrongScan, setWrongScan] = useState(false);
  const scanRef = useRef();
  const activeRef = useRef();

  const load = useCallback(async () => {
    try {
      const data = await api.get(`/api/picklists/${listId}`);
      setList(data);
      setRouteMode(data.route_mode||'lager');
      if (data.status==='completed') setShowCompleted(true);
    } catch(e) { showToast('Fehler','error'); }
    finally { setLoading(false); }
  }, [listId]);

  useEffect(() => { load(); }, []);

  const activeItem = list?.items?.find(i=>i.status==='pending');
  const doneCount = list?.items?.filter(i=>i.status==='done').length??0;

  // TTS
  useEffect(() => {
    if (!activeItem||!window.speechSynthesis) return;
    window.speechSynthesis.cancel();
    const utt = new SpeechSynthesisUtterance(`${activeItem.description}, Menge: ${activeItem.quantity}`);
    utt.lang = 'de-DE'; utt.rate = 0.95;
    window.speechSynthesis.speak(utt);
  }, [activeItem?.id]);

  // Scroll active into view
  useEffect(() => {
    activeRef.current?.scrollIntoView({ behavior:'smooth', block:'center' });
  }, [activeItem?.id]);

  // Start session
  useEffect(() => {
    if (list && (list.status==='open'||list.status==='assigned'))
      api.post(`/api/picklists/${listId}/start`, {}).then(load);
  }, [list?.id]);

  const toggleRouteMode = async () => {
    const newMode = routeMode==='lager' ? 'pdf' : 'lager';
    await api.post(`/api/picklists/${listId}/route-mode`, { mode: newMode });
    setRouteMode(newMode);
    await load();
    showToast(newMode==='lager' ? '🗺 Lager-Reihenfolge aktiv' : '📄 PDF-Reihenfolge aktiv', 'info');
  };

  const confirmItem = async (itemId, scannedNr) => {
    try {
      const res = await api.post(`/api/picklists/${listId}/items/${itemId}/scan`,
        scannedNr ? { article_nr: scannedNr } : {});
      setWrongScan(false);
      if (res.all_done) { setShowCompleted(true); }
      await load();
      setScanVal('');
      setTimeout(()=>scanRef.current?.focus(), 80);
    } catch(e) {
      if (e.error?.includes('stimmt nicht')) {
        setWrongScan(true);
        if (navigator.vibrate) navigator.vibrate([200,100,200]);
        setTimeout(()=>setWrongScan(false), 1500);
      }
      showToast(e.error||'Fehler','error');
    }
  };

  const undoItem = async (itemId) => {
    await api.post(`/api/picklists/${listId}/items/${itemId}/unscan`, {});
    await load();
  };

  const handleScanInput = async (val) => {
    const v = val.trim();
    if (!v) return;
    if (!activeItem) { setScanVal(''); return; }
    // Try match against active item first, then any pending item
    if (!activeItem.article_nr || activeItem.article_nr===v) {
      await confirmItem(activeItem.id, v);
    } else {
      const match = list.items.find(i=>i.status==='pending'&&i.article_nr===v);
      if (match) {
        await confirmItem(match.id, v);
      } else {
        setWrongScan(true);
        if (navigator.vibrate) navigator.vibrate([200,100,200]);
        setTimeout(()=>setWrongScan(false), 1500);
        showToast(`Artikel "${v}" nicht in dieser Liste`, 'error');
        setScanVal('');
      }
    }
  };

  const handleCameraScan = (code) => {
    setShowCamera(false);
    handleScanInput(code);
  };

  if (loading) return React.createElement('div',{className:'loading-wrap'},React.createElement('div',{className:'spinner'}));
  if (!list) return null;

  const total = list.items.length;
  const lowConfItems = list.items.filter(i=>i.ocr_conf_level==='low');
  const hasLowConf = lowConfItems.length > 0;

  return React.createElement('div', { className:'pick-session' },
    // Header
    React.createElement('div', { className:'pick-session-header' },
      React.createElement('button', { className:'btn btn-secondary btn-sm', onClick:onBack }, '← Zurück'),
      React.createElement('div', { className:'pick-meta' },
        React.createElement('div', { className:'pick-meta-tour' },
          `Tour ${list.tour_nr||'–'} · ${list.tour_type||list.automat_name||'–'}`),
        React.createElement('div', { className:'pick-meta-customer' },
          `${list.customer_name||'–'} · ${list.customer_location||'–'}`)
      ),
      // Route mode toggle
      React.createElement('button', {
        className:`btn btn-sm ${routeMode==='lager'?'btn-primary':'btn-secondary'}`,
        onClick: toggleRouteMode,
        title: routeMode==='lager' ? 'Optimierte Lagerreihenfolge aktiv — klicken für PDF-Reihenfolge' : 'PDF-Reihenfolge aktiv — klicken für Lager-Optimierung'
      }, routeMode==='lager' ? '🗺 Lager-Route' : '📄 PDF-Order'),
      React.createElement(ProgressRing, { done:doneCount, total }),
    ),

    // OCR warning banner
    hasLowConf && React.createElement('div', { className:'ocr-banner' },
      React.createElement('span',null,'⚠'),
      React.createElement('span',null,
        `${lowConfItems.length} Artikel mit niedriger OCR-Qualität — bitte Bezeichnung und Menge prüfen!`)
    ),

    // Progress bar
    React.createElement('div', { className:'progress-bar-wrap mb-4', style:{height:8} },
      React.createElement('div', { className:'progress-bar-fill',
        style:{width:`${total>0?(doneCount/total)*100:0}%`,height:8} })
    ),

    // Active item hero
    activeItem && React.createElement('div', { className:`active-item-hero${wrongScan?' wrong-scan':''}` },
      React.createElement('div', { className:'active-item-hero-icon' }, '📦'),
      React.createElement('div', { style:{flex:1,minWidth:0} },
        React.createElement('div', { className:'active-item-hero-desc' }, activeItem.description),
        React.createElement('div', { className:'active-item-hero-detail' },
          React.createElement('span',{className:'mono'},activeItem.article_nr||'–'),
          ' · ', activeItem.lager||'–'
        ),
        React.createElement(ConfBadge, { level:activeItem.ocr_conf_level, conf:activeItem.ocr_conf })
      ),
      React.createElement('div', { style:{textAlign:'right',flexShrink:0} },
        React.createElement('div', { className:'active-item-hero-qty' }, activeItem.quantity),
        React.createElement('div', { className:'active-item-hero-qty-label' }, 'Stück')
      )
    ),

    // Items list
    React.createElement('div', { className:'pick-items-list mb-6' },
      list.items.map(item => {
        const isActive = item.id===activeItem?.id;
        const isDone = item.status==='done';
        return React.createElement('div', {
          key:item.id,
          ref: isActive?activeRef:null,
          className:`pick-item${isActive?' active':''}${isDone?' done':''}`
        },
          // Position badge — show route pos when in lager mode
          React.createElement('div', { className:'pick-item-pos', title:'Position' },
            routeMode==='lager' && item.route_position
              ? React.createElement('span',{className:'route-pos'},item.route_position)
              : item.position
          ),
          React.createElement('div', { className:'pick-item-info' },
            React.createElement('div', { className:'pick-item-desc' }, item.description),
            React.createElement('div', { className:'pick-item-meta' },
              React.createElement('span',{className:'mono'}, item.article_nr||''),
              item.lager ? ` · ${item.lager}` : '',
              ' ',
              React.createElement(ConfBadge, { level:item.ocr_conf_level, conf:item.ocr_conf })
            )
          ),
          React.createElement('div', { style:{textAlign:'center'} },
            React.createElement('div',{className:'pick-item-qty'}, item.quantity),
            React.createElement('div',{className:'pick-item-unit'},'Stück')
          ),
          React.createElement('button', {
            className:'pick-item-check',
            onClick:()=>isDone?undoItem(item.id):confirmItem(item.id)
          }, isDone?'✓':isActive?'▶':'○')
        );
      })
    ),

    // Scan bar
    !showCompleted && React.createElement('div', { className:'scan-bar' },
      React.createElement('input', {
        ref: scanRef, className:'scan-input', value:scanVal,
        onChange: e=>setScanVal(e.target.value),
        onKeyDown: e=>e.key==='Enter'&&handleScanInput(scanVal),
        placeholder:'Barcode scannen oder Enter…',
        autoFocus:true, autoComplete:'off'
      }),
      React.createElement('button', {
        className:'btn btn-secondary btn-lg btn-icon',
        onClick:()=>setShowCamera(true), title:'Kamera-Scanner'
      }, '📷'),
      React.createElement('button', {
        className:'btn btn-success btn-lg',
        onClick:()=>activeItem&&confirmItem(activeItem.id),
        disabled:!activeItem
      }, '✓ OK')
    ),

    showCamera && React.createElement(CameraScanner, {
      onScan: handleCameraScan,
      onClose:()=>setShowCamera(false)
    }),

    showCompleted && React.createElement('div', { className:'completed-overlay' },
      React.createElement('div', { className:'completed-card' },
        React.createElement('div',{className:'completed-icon'},'🎉'),
        React.createElement('div',{className:'completed-title'},'Fertig!'),
        React.createElement('div',{className:'completed-sub'},`Alle ${total} Artikel gepickt.`),
        React.createElement('button',{className:'btn btn-success btn-lg btn-full',onClick:onBack},
          '← Zurück zur Übersicht')
      )
    )
  );
}

// ─── Users View ───────────────────────────────────────────────────────────────
function UsersView({ user: currentUser, showToast }) {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editUser, setEditUser] = useState(null);
  const [showNew, setShowNew] = useState(false);
  const load = async () => {
    try { setUsers(await api.get('/api/users')); }
    catch(e) { showToast('Fehler','error'); }
    finally { setLoading(false); }
  };
  useEffect(()=>{ load(); },[]);

  return React.createElement('div', null,
    React.createElement('div',{className:'flex items-center justify-between mb-6'},
      React.createElement('div',{className:'page-title'},'👥 Benutzerverwaltung'),
      React.createElement('button',{className:'btn btn-primary btn-sm',onClick:()=>setShowNew(true)},'+ Neuer Benutzer')
    ),
    loading ? React.createElement('div',{className:'loading-wrap'},React.createElement('div',{className:'spinner'})) :
    React.createElement('div',{className:'card'},
      React.createElement('table',{className:'pick-table'},
        React.createElement('thead',null,React.createElement('tr',null,
          React.createElement('th',null,'Benutzer'),React.createElement('th',null,'Benutzername'),
          React.createElement('th',null,'Rolle'),React.createElement('th',null,'Status'),
          React.createElement('th',null,'Letzter Login'),React.createElement('th',null,'')
        )),
        React.createElement('tbody',null, users.map(u =>
          React.createElement('tr',{key:u.id},
            React.createElement('td',null,
              React.createElement('div',{className:'flex items-center gap-2'},
                React.createElement('div',{className:'user-dot',style:{background:u.color}},u.full_name.charAt(0).toUpperCase()),
                u.full_name)
            ),
            React.createElement('td',{className:'mono text-sm'},u.username),
            React.createElement('td',null,
              React.createElement('span',{className:`badge ${u.role==='admin'?'badge-in_progress':'badge-open'}`},
                u.role==='admin'?'Admin':'Picker')),
            React.createElement('td',null,
              React.createElement('span',{className:`badge ${u.active?'badge-completed':''}`},u.active?'Aktiv':'Inaktiv')),
            React.createElement('td',{className:'text-sm text-muted'},u.last_login?.slice(0,16).replace('T',' ')||'–'),
            React.createElement('td',null,
              React.createElement('div',{className:'flex gap-2'},
                React.createElement('button',{className:'btn btn-sm btn-secondary',onClick:()=>setEditUser(u)},'Bearb.'),
                u.id!==currentUser.id && React.createElement('button',{
                  className:'btn btn-sm btn-danger',
                  onClick:async()=>{
                    if(!confirm('Deaktivieren?'))return;
                    await api.del(`/api/users/${u.id}`);
                    showToast('Gespeichert','success'); load();
                  }
                }, u.active?'Deaktiv.':'–')
              )
            )
          )
        ))
      )
    ),
    (showNew||editUser) && React.createElement(UserModal,{
      user:editUser,
      onClose:()=>{setShowNew(false);setEditUser(null);},
      onDone:()=>{setShowNew(false);setEditUser(null);load();showToast('Gespeichert','success');}
    })
  );
}

function UserModal({ user, onClose, onDone }) {
  const [form, setForm] = useState({
    username:user?.username||'', full_name:user?.full_name||'', password:'',
    role:user?.role||'picker', color:user?.color||'#f97316', active:user?.active??1
  });
  const [err,setErr]=useState('');
  const f=(k,v)=>setForm(p=>({...p,[k]:v}));
  const submit=async()=>{
    setErr('');
    try {
      if(user) await api.put(`/api/users/${user.id}`,form);
      else { if(!form.password){setErr('Passwort erforderlich');return;} await api.post('/api/users',form); }
      onDone();
    } catch(e){setErr(e.error||'Fehler');}
  };
  return React.createElement(Modal,{
    title:user?'Benutzer bearbeiten':'Neuer Benutzer', onClose,
    footer: React.createElement(React.Fragment,null,
      React.createElement('button',{className:'btn btn-secondary',onClick:onClose},'Abbrechen'),
      React.createElement('button',{className:'btn btn-primary',onClick:submit},'Speichern'))
  },
    !user && React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},'Benutzername'),
      React.createElement('input',{className:'form-input',value:form.username,autoCapitalize:'none',
        onChange:e=>f('username',e.target.value)})
    ),
    React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},'Vollständiger Name'),
      React.createElement('input',{className:'form-input',value:form.full_name,onChange:e=>f('full_name',e.target.value)})
    ),
    React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},user?'Neues Passwort (leer = unverändert)':'Passwort'),
      React.createElement('input',{type:'password',className:'form-input',value:form.password,onChange:e=>f('password',e.target.value)})
    ),
    React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},'Rolle'),
      React.createElement('select',{className:'form-input',value:form.role,onChange:e=>f('role',e.target.value)},
        React.createElement('option',{value:'picker'},'Picker'),
        React.createElement('option',{value:'admin'},'Administrator'))
    ),
    user && React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},'Status'),
      React.createElement('select',{className:'form-input',value:form.active,onChange:e=>f('active',parseInt(e.target.value))},
        React.createElement('option',{value:1},'Aktiv'),React.createElement('option',{value:0},'Inaktiv'))
    ),
    React.createElement('div',{className:'form-group'},
      React.createElement('label',{className:'form-label'},'Farbe'),
      React.createElement('div',{className:'color-chips'},
        COLORS.map(c=>React.createElement('div',{key:c,className:`color-chip${form.color===c?' selected':''}`,
          style:{background:c},onClick:()=>f('color',c)})))
    ),
    err && React.createElement('div',{className:'text-danger text-sm mt-2'},err)
  );
}

// ─── Main App ─────────────────────────────────────────────────────────────────
function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [view, setView] = useState('lists');
  const [selectedList, setSelectedList] = useState(null);
  const [toasts, setToasts] = useState([]);

  const showToast = useCallback((msg, type='info') => {
    const id = Date.now();
    setToasts(prev => [...prev, {id,msg,type}]);
    setTimeout(()=>setToasts(prev=>prev.filter(t=>t.id!==id)), 3500);
  }, []);

  useEffect(() => {
    api.get('/api/auth/me').then(u=>setUser(u)).catch(()=>{}).finally(()=>setLoading(false));
  }, []);

  if (loading) return React.createElement('div',{className:'loading-wrap',style:{minHeight:'100vh'}},
    React.createElement('div',{className:'spinner'}));
  if (!user) return React.createElement(LoginView,{onLogin:u=>setUser(u)});

  const logout = async () => {
    await api.post('/api/auth/logout',{}); setUser(null); setSelectedList(null); setView('lists');
  };

  return React.createElement('div',{className:'app'},
    React.createElement('div',{className:'topbar'},
      React.createElement('img',{src:'/martin_gruppe_logo.svg',className:'topbar-logo-img',alt:'Martin Gruppe'}),
      React.createElement('div',{className:'topbar-divider'}),
      React.createElement('div',{className:'topbar-product'},'VendingPick'),
      !selectedList && React.createElement('div',{className:'nav'},
        React.createElement('button',{className:`nav-btn${view==='lists'?' active':''}`,onClick:()=>setView('lists')},'📋 Listen'),
        user.role==='admin' && React.createElement('button',{className:`nav-btn${view==='users'?' active':''}`,onClick:()=>setView('users')},'👥 Benutzer')
      ),
      React.createElement('div',{className:'topbar-spacer'}),
      React.createElement('div',{className:'topbar-user'},
        React.createElement('div',{className:'user-dot',style:{background:user.color}},user.full_name.charAt(0).toUpperCase()),
        React.createElement('span',{className:'text-sm'},user.full_name),
        React.createElement('button',{className:'btn btn-secondary btn-sm',onClick:logout},'Abmelden')
      )
    ),
    React.createElement('div',{className:'main'},
      selectedList
        ? React.createElement(PickSessionView,{listId:selectedList,user,onBack:()=>setSelectedList(null),showToast})
        : view==='lists' ? React.createElement(PicklistsView,{user,showToast,onSelect:id=>setSelectedList(id)})
        : view==='users' ? React.createElement(UsersView,{user,showToast})
        : null
    ),
    React.createElement(Toast,{toasts})
  );
}

ReactDOM.render(React.createElement(App), document.getElementById('root'));
