const { useState, useEffect, useCallback, useRef } = React;

// ── Icons ───────────────────────────────────────────────────────────────────
function Icon({ name, size = 16 }) {
  const icons = {
    sun: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><circle cx="8" cy="8" r="3"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41"/></svg>,
    moon: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M13.5 10A6 6 0 016 2.5a6 6 0 100 11 6 6 0 007.5-3.5z"/></svg>,
    home: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M2 6.5L8 2l6 4.5V14H2V6.5z"/></svg>,
    shop: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="1" y="5" width="14" height="10" rx="1"/><path d="M5 5V4a3 3 0 016 0v1"/></svg>,
    box: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M8 1l7 4v6L8 15 1 11V5L8 1z"/><path d="M1 5l7 4 7-4M8 9v6"/></svg>,
    alert: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M8 2L1 14h14L8 2z"/><path d="M8 7v3M8 12v.5"/></svg>,
    cpu: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="3" y="3" width="10" height="10" rx="1"/><path d="M6 1v2M10 1v2M6 13v2M10 13v2M1 6h2M1 10h2M13 6h2M13 10h2"/></svg>,
    log: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 2h10a1 1 0 011 1v10a1 1 0 01-1 1H3a1 1 0 01-1-1V3a1 1 0 011-1z"/><path d="M5 6h6M5 9h4"/></svg>,
    settings: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><circle cx="8" cy="8" r="2.5"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41"/></svg>,
    refresh: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M13 2.5A6.5 6.5 0 112.5 9"/><path d="M1 5l1.5 4 4-1.5"/></svg>,
    close: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 3l10 10M13 3L3 13"/></svg>,
    logout: <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M10 2h3a1 1 0 011 1v10a1 1 0 01-1 1h-3M6.5 11L10 8l-3.5-3M1 8h9"/></svg>,
  };
  return icons[name] ?? null;
}

// ── API ──────────────────────────────────────────────────────────────────────
const BASE = '';

async function apiFetch(path, token, opts = {}) {
  const res = await fetch(BASE + path, {
    ...opts,
    headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', ...(opts.headers ?? {}) },
  });
  if (res.status === 401) throw new Error('unauthorized');
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

async function apiLogin(username, password) {
  const res = await fetch(BASE + '/auth/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  });
  if (!res.ok) throw new Error('Login fehlgeschlagen');
  return res.json();
}

// ── Helpers ──────────────────────────────────────────────────────────────────
function fmtTime(d) {
  if (!d) return '—';
  const dt = new Date(d);
  return dt.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
}
function fmtDate(d) {
  if (!d) return '—';
  const dt = new Date(d);
  return dt.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit' }) + ' ' + fmtTime(d);
}
function timeSince(d) {
  if (!d) return '—';
  const s = Math.floor((Date.now() - new Date(d)) / 1000);
  if (s < 60) return `vor ${s}s`;
  if (s < 3600) return `vor ${Math.floor(s/60)}m`;
  return `vor ${Math.floor(s/3600)}h`;
}

function LevelPill({ level }) {
  const map = { info: 'pill-blue', warning: 'pill-yellow', error: 'pill-red', debug: 'pill-gray' };
  return <span className={`pill ${map[level] ?? 'pill-gray'}`}>{level}</span>;
}

function WorkerTypePill({ type }) {
  return <span className="pill pill-gray">{type}</span>;
}

// ── Login ────────────────────────────────────────────────────────────────────
function Login({ onLogin }) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  async function submit(e) {
    e.preventDefault();
    setError(''); setLoading(true);
    try {
      const data = await apiLogin(username, password);
      onLogin(data.access_token ?? data.token ?? data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="login-wrap">
      <form className="login-card" onSubmit={submit}>
        <div className="login-logo">
          <div className="logo-mark">W</div>
          Weitblick Connector
        </div>
        <div className="login-label">Benutzername</div>
        <input className="login-input" type="text" value={username} onChange={e => setUsername(e.target.value)} autoFocus required />
        <div className="login-label">Passwort</div>
        <input className="login-input" type="password" value={password} onChange={e => setPassword(e.target.value)} required />
        {error && <div className="login-error">{error}</div>}
        <button className="btn-primary" type="submit" disabled={loading}>
          {loading ? 'Anmelden…' : 'Anmelden'}
        </button>
      </form>
    </div>
  );
}

// ── Sidebar ──────────────────────────────────────────────────────────────────
const NAV = [
  { id: 'overview',  label: 'Übersicht', icon: 'home' },
  { id: 'shops',     label: 'Shops',     icon: 'shop' },
  { id: 'products',  label: 'Produkte',  icon: 'box' },
  { id: 'workers',   label: 'Worker',    icon: 'cpu' },
  { id: 'errors',    label: 'Fehler',    icon: 'alert' },
  { id: 'logs',      label: 'Logs',      icon: 'log' },
];

function Sidebar({ view, setView, onLogout }) {
  return (
    <aside className="sidebar">
      <div className="sidebar-logo">
        <div className="logo-mark">W</div>
        Connector
      </div>
      <nav className="sidebar-nav">
        {NAV.map(n => (
          <button key={n.id} className={`nav-item ${view === n.id ? 'active' : ''}`} onClick={() => setView(n.id)}>
            <Icon name={n.icon} size={15} />
            {n.label}
          </button>
        ))}
      </nav>
      <div className="sidebar-bottom">
        <button className="nav-item" onClick={onLogout}>
          <Icon name="logout" size={15} />
          Abmelden
        </button>
      </div>
    </aside>
  );
}

// ── Overview ─────────────────────────────────────────────────────────────────
function Overview({ workers, logs, shops, queues }) {
  const errors = logs.filter(l => l.level === 'error');
  const warnings = logs.filter(l => l.level === 'warning');
  const activeWorkers = workers.filter(w => (Date.now() - new Date(w.lastActive)) < 5 * 60 * 1000);

  return (
    <div>
      <div className="section-title">Übersicht</div>
      <div className="section-sub">Status aller Connector-Komponenten</div>

      <div className="grid-4">
        <div className="stat-card">
          <div className="stat-label">Shops</div>
          <div className="stat-value">{shops.length}</div>
          <div className="stat-sub">{shops.filter(s => s.active).length} aktiv</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Aktive Jobs</div>
          <div className="stat-value" style={{ color: queues.reduce((s,q)=>s+q.active,0) > 0 ? 'var(--green)' : 'inherit' }}>
            {queues.reduce((s, q) => s + q.active, 0)}
          </div>
          <div className="stat-sub">{queues.reduce((s, q) => s + q.waiting, 0)} wartend</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Fehler</div>
          <div className="stat-value" style={{ color: errors.length > 0 ? 'var(--red)' : 'inherit' }}>{errors.length}</div>
          <div className="stat-sub">{warnings.length} Warnungen</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Log-Einträge</div>
          <div className="stat-value">{logs.length}</div>
          <div className="stat-sub">letzte 500</div>
        </div>
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-header"><span className="card-title">Worker</span></div>
          {workers.length === 0
            ? <div className="empty">Keine Worker aktiv</div>
            : <div className="table-wrap">
                <table>
                  <thead><tr><th>Typ</th><th>Zuletzt aktiv</th><th>Status</th></tr></thead>
                  <tbody>
                    {workers.slice(0, 8).map(w => {
                      const alive = (Date.now() - new Date(w.lastActive)) < 5 * 60 * 1000;
                      return (
                        <tr key={w.id}>
                          <td><WorkerTypePill type={w.type} /></td>
                          <td className="mono">{timeSince(w.lastActive)}</td>
                          <td><span className={`dot ${alive ? 'dot-green' : 'dot-gray'}`} /></td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
          }
        </div>

        <div className="card">
          <div className="card-header"><span className="card-title">Letzte Fehler</span></div>
          {errors.length === 0
            ? <div className="empty">Keine Fehler</div>
            : <div>
                {errors.slice(0, 6).map(l => (
                  <div key={l.id} className="log-entry">
                    <div className="log-entry-header">
                      <LevelPill level={l.level} />
                      <span className="log-entry-time">{fmtDate(l.createdAt)}</span>
                    </div>
                    <div className="log-entry-message">{l.message.slice(0, 120)}{l.message.length > 120 ? '…' : ''}</div>
                  </div>
                ))}
              </div>
          }
        </div>
      </div>
    </div>
  );
}

// ── Shops ────────────────────────────────────────────────────────────────────
function Shops({ shops }) {
  return (
    <div>
      <div className="section-title">Shops</div>
      <div className="section-sub">Verbundene Shopware-Instanzen</div>
      <div className="card">
        <div className="table-wrap">
          <table>
            <thead>
              <tr><th>ID</th><th>API URL</th><th>Status</th></tr>
            </thead>
            <tbody>
              {shops.length === 0
                ? <tr><td colSpan={3}><div className="empty">Keine Shops konfiguriert</div></td></tr>
                : shops.map(s => (
                    <tr key={s.id}>
                      <td className="mono">{s.id}</td>
                      <td className="mono">{s.apiUrl}</td>
                      <td>
                        {s.active
                          ? <span className="pill pill-green"><span className="dot dot-green" style={{width:5,height:5}} /> Aktiv</span>
                          : <span className="pill pill-gray"><span className="dot dot-gray" style={{width:5,height:5}} /> Inaktiv</span>
                        }
                      </td>
                    </tr>
                  ))
              }
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ── Products ─────────────────────────────────────────────────────────────────
function Products({ token, onUnauthorized }) {
  const [data, setData] = useState({ items: [], hasMore: false });
  const [search, setSearch] = useState('');
  const [debouncedSearch, setDebouncedSearch] = useState('');
  const [offset, setOffset] = useState(0);
  const [syncing, setSyncing] = useState({});
  const [toast, setToast] = useState(null);
  const [error, setError] = useState(null);
  const limit = 100;

  // Debounce search — reset to page 1 on new search
  useEffect(() => {
    const t = setTimeout(() => {
      setDebouncedSearch(search);
      setOffset(0);
    }, 300);
    return () => clearTimeout(t);
  }, [search]);

  const load = useCallback(async () => {
    setError(null);
    try {
      const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
      if (debouncedSearch) params.set('search', debouncedSearch);
      const res = await apiFetch(`/products?${params}`, token);
      setData(res);
    } catch (e) {
      if (e.message === 'unauthorized') { onUnauthorized(); return; }
      setError(e.message);
    }
  }, [token, offset, debouncedSearch]);

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

  async function resync(product) {
    setSyncing(s => ({ ...s, [product.id]: true }));
    try {
      const res = await apiFetch(`/products/${product.id}/resync`, token, { method: 'POST' });
      setToast(`${product.mainProductNumber}: ${res.jobsQueued} Job(s) in Queue`);
      setTimeout(() => setToast(null), 3000);
    } catch {
      setToast(`Fehler bei ${product.mainProductNumber}`);
      setTimeout(() => setToast(null), 3000);
    } finally {
      setSyncing(s => ({ ...s, [product.id]: false }));
    }
  }

  return (
    <div>
      <div className="section-title">Produkte</div>
      <div className="section-sub">{data.total} indexierte Produkte</div>

      {error && <div style={{ color: 'var(--red)', fontSize: 13, marginBottom: 12 }}>Fehler: {error}</div>}

      <div style={{ display: 'flex', gap: 8, marginBottom: 16, alignItems: 'center' }}>
        <input
          className="search-input"
          placeholder="Artikelnummer suchen…"
          value={search}
          onChange={e => setSearch(e.target.value)}
        />
        <span style={{ color: 'var(--text-3)', fontSize: 12 }}>{data.items.length} Einträge</span>
      </div>

      <div className="card">
        <div className="table-wrap">
          <table>
            <thead>
              <tr>
                <th>Artikelnummer</th>
                <th>Datei</th>
                <th>Geparst</th>
                <th>Aktualisiert</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {data.items.length === 0
                ? <tr><td colSpan={5}><div className="empty">Keine Produkte gefunden</div></td></tr>
                : data.items.map(p => (
                    <tr key={p.id}>
                      <td className="mono" style={{ fontWeight: 500 }}>{p.mainProductNumber}</td>
                      <td className="mono" style={{ color: 'var(--text-3)', fontSize: 11 }}>{p.fileKey}</td>
                      <td className="mono">{fmtDate(p.parsedAt)}</td>
                      <td className="mono">{fmtDate(p.updatedAt)}</td>
                      <td>
                        {p.mainProductNumber.length < 8 && (
                          <button
                            className="btn-ghost"
                            style={{ padding: '4px 10px', fontSize: 11 }}
                            disabled={!!syncing[p.id]}
                            onClick={() => resync(p)}
                          >
                            <Icon name="refresh" size={11} />
                            {syncing[p.id] ? 'Wird gesendet…' : 'Sync'}
                          </button>
                        )}
                      </td>
                    </tr>
                  ))
              }
            </tbody>
          </table>
        </div>

        {(offset > 0 || data.hasMore) && (
          <div style={{ display: 'flex', gap: 8, padding: '12px 0 0', justifyContent: 'flex-end' }}>
            <button className="btn-ghost" disabled={offset === 0} onClick={() => setOffset(o => Math.max(0, o - limit))}>
              ← Zurück
            </button>
            <span style={{ fontSize: 12, color: 'var(--text-2)', alignSelf: 'center' }}>
              Seite {Math.floor(offset / limit) + 1}
            </span>
            <button className="btn-ghost" disabled={!data.hasMore} onClick={() => setOffset(o => o + limit)}>
              Weiter →
            </button>
          </div>
        )}
      </div>

      {toast && (
        <div className="toast-container">
          <div className="toast">{toast}</div>
        </div>
      )}
    </div>
  );
}

// ── Workers ──────────────────────────────────────────────────────────────────
function Workers({ workers, logs, queues, onSelectType }) {
  const byType = workers.reduce((acc, w) => {
    if (!acc[w.type] || new Date(w.lastActive) > new Date(acc[w.type].lastActive)) {
      acc[w.type] = w;
    }
    return acc;
  }, {});

  // Merge all known types from workers + queues
  const allTypes = new Set([
    ...Object.keys(byType),
    ...queues.map(q => q.workerType),
  ]);

  const totalActive = queues.reduce((s, q) => s + q.active, 0);
  const totalWaiting = queues.reduce((s, q) => s + q.waiting, 0);
  const totalFailed = queues.reduce((s, q) => s + q.failed, 0);

  return (
    <div>
      <div className="section-title">Worker & Queues</div>
      <div className="section-sub">Registrierte Worker und Queue-Status — Klick für Logs</div>

      <div className="grid-4" style={{ marginBottom: 20 }}>
        <div className="stat-card">
          <div className="stat-label">Aktive Jobs</div>
          <div className="stat-value" style={{ color: totalActive > 0 ? 'var(--green)' : 'inherit' }}>{totalActive}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Wartende Jobs</div>
          <div className="stat-value">{totalWaiting}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Fehlgeschlagen</div>
          <div className="stat-value" style={{ color: totalFailed > 0 ? 'var(--red)' : 'inherit' }}>{totalFailed}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Queues</div>
          <div className="stat-value">{queues.length}</div>
        </div>
      </div>

      <div className="card">
        <div className="table-wrap">
          <table>
            <thead>
              <tr><th>Typ</th><th>Worker</th><th>Zuletzt aktiv</th><th>Aktiv</th><th>Wartend</th><th>Verzögert</th><th>Fehler</th><th>Logs</th></tr>
            </thead>
            <tbody>
              {allTypes.size === 0
                ? <tr><td colSpan={8}><div className="empty">Keine Worker oder Queues gefunden</div></td></tr>
                : [...allTypes].map(type => {
                    const worker = byType[type];
                    const queue = queues.find(q => q.workerType === type);
                    const alive = worker && (Date.now() - new Date(worker.lastActive)) < 10 * 60 * 1000;
                    const typeLogCount = logs.filter(l => l.workerType === type).length;
                    return (
                      <tr key={type} style={{ cursor: 'pointer' }} onClick={() => onSelectType(type)}>
                        <td><WorkerTypePill type={type} /></td>
                        <td>
                          {worker
                            ? <span className={`dot ${alive ? 'dot-green' : 'dot-gray'}`} />
                            : <span className="dot dot-gray" style={{ opacity: 0.3 }} />
                          }
                        </td>
                        <td className="mono">{worker ? timeSince(worker.lastActive) : '—'}</td>
                        <td className="mono" style={{ color: queue?.active > 0 ? 'var(--green)' : 'inherit' }}>
                          {queue?.active ?? '—'}
                        </td>
                        <td className="mono">{queue?.waiting ?? '—'}</td>
                        <td className="mono" style={{ color: queue?.delayed > 0 ? 'var(--yellow)' : 'inherit' }}>
                          {queue?.delayed ?? '—'}
                        </td>
                        <td className="mono" style={{ color: queue?.failed > 0 ? 'var(--red)' : 'inherit' }}>
                          {queue?.failed ?? '—'}
                        </td>
                        <td className="mono">{typeLogCount}</td>
                      </tr>
                    );
                  })
              }
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ── Worker Type Drawer ────────────────────────────────────────────────────────
function WorkerDrawer({ workerType, logs, onClose }) {
  const workerLogs = logs.filter(l => l.workerType === workerType).sort((a, b) => b.id - a.id);
  const [levelFilter, setLevelFilter] = useState('all');

  const filtered = workerLogs.filter(l => levelFilter === 'all' || l.level === levelFilter);

  return (
    <div className="drawer-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="drawer">
        <div className="drawer-header">
          <div>
            <div className="drawer-title">{workerType}</div>
            <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 2 }}>{workerLogs.length} Log-Einträge</div>
          </div>
          <button className="drawer-close" onClick={onClose}><Icon name="close" size={16} /></button>
        </div>
        <div className="drawer-body">
          <div style={{ display: 'flex', gap: 6, marginBottom: 16, flexWrap: 'wrap' }}>
            {['all', 'info', 'warning', 'error', 'debug'].map(lvl => (
              <button
                key={lvl}
                className="btn-ghost"
                style={levelFilter === lvl ? { borderColor: 'var(--border-bright)', color: 'var(--text)' } : {}}
                onClick={() => setLevelFilter(lvl)}
              >
                {lvl === 'all' ? 'Alle' : lvl}
              </button>
            ))}
          </div>
          {filtered.length === 0
            ? <div className="empty">Keine Logs</div>
            : filtered.map(l => (
                <div key={l.id} className="log-entry">
                  <div className="log-entry-header">
                    <LevelPill level={l.level} />
                    <span className="log-entry-time">{fmtDate(l.createdAt)}</span>
                  </div>
                  <div className="log-entry-message">{l.message}</div>
                </div>
              ))
          }
        </div>
      </div>
    </div>
  );
}

// ── Errors ───────────────────────────────────────────────────────────────────
function Errors({ logs }) {
  const errors = logs.filter(l => l.level === 'error' || l.level === 'warning').sort((a, b) => b.id - a.id);

  return (
    <div>
      <div className="section-title">Fehler & Warnungen</div>
      <div className="section-sub">{errors.length} Einträge</div>
      <div className="card">
        {errors.length === 0
          ? <div className="empty">Keine Fehler oder Warnungen</div>
          : errors.map(l => (
              <div key={l.id} className="log-entry">
                <div className="log-entry-header">
                  <LevelPill level={l.level} />
                  <span className="log-entry-time">{fmtDate(l.createdAt)}</span>
                  <span className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>{l.workerId?.slice(0, 12)}…</span>
                </div>
                <div className="log-entry-message">{l.message}</div>
              </div>
            ))
        }
      </div>
    </div>
  );
}

// ── Logs ─────────────────────────────────────────────────────────────────────
function Logs({ logs }) {
  const [search, setSearch] = useState('');
  const [levelFilter, setLevelFilter] = useState('all');

  const filtered = logs
    .filter(l => levelFilter === 'all' || l.level === levelFilter)
    .filter(l => !search || l.message.toLowerCase().includes(search.toLowerCase()))
    .sort((a, b) => b.id - a.id);

  return (
    <div>
      <div className="section-title">Logs</div>
      <div className="section-sub">{filtered.length} Einträge</div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
        <input
          className="search-input"
          placeholder="Suche…"
          value={search}
          onChange={e => setSearch(e.target.value)}
        />
        {['all', 'info', 'warning', 'error', 'debug'].map(lvl => (
          <button
            key={lvl}
            className={`btn-ghost ${levelFilter === lvl ? 'active' : ''}`}
            style={levelFilter === lvl ? { borderColor: 'var(--border-bright)', color: 'var(--text)' } : {}}
            onClick={() => setLevelFilter(lvl)}
          >
            {lvl === 'all' ? 'Alle' : lvl}
          </button>
        ))}
      </div>

      <div className="card">
        {filtered.length === 0
          ? <div className="empty">Keine Logs</div>
          : filtered.map(l => (
              <div key={l.id} className="log-entry">
                <div className="log-entry-header">
                  <LevelPill level={l.level} />
                  <span className="log-entry-time">{fmtDate(l.createdAt)}</span>
                  <span className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>{l.workerId?.slice(0, 12)}…</span>
                </div>
                <div className="log-entry-message">{l.message}</div>
              </div>
            ))
        }
      </div>
    </div>
  );
}

// ── App ───────────────────────────────────────────────────────────────────────
function App() {
  const [theme, setTheme] = useState(() => localStorage.getItem('wc_theme') ?? 'dark');
  const [token, setToken] = useState(() => localStorage.getItem('wc_token') ?? null);

  useEffect(() => {
    document.documentElement.classList.toggle('light', theme === 'light');
    localStorage.setItem('wc_theme', theme);
  }, [theme]);

  function toggleTheme() {
    setTheme(t => t === 'dark' ? 'light' : 'dark');
  }
  const [view, setView] = useState('overview');
  const [workers, setWorkers] = useState([]);
  const [logs, setLogs] = useState([]);
  const [shops, setShops] = useState([]);
  const [queues, setQueues] = useState([]);
  const [selectedWorkerType, setSelectedWorkerType] = useState(null);
  const [loading, setLoading] = useState(false);

  function handleLogin(t) {
    localStorage.setItem('wc_token', t);
    setToken(t);
  }

  function handleLogout() {
    localStorage.removeItem('wc_token');
    setToken(null);
  }

  const load = useCallback(async () => {
    if (!token) return;
    setLoading(true);
    try {
      const rethrowUnauthorized = (e) => { if (e.message === 'unauthorized') throw e; return []; };
      const [w, l, s, q] = await Promise.all([
        apiFetch('/workers', token).catch(rethrowUnauthorized),
        apiFetch('/logs', token).catch(rethrowUnauthorized),
        apiFetch('/shops', token).catch(rethrowUnauthorized),
        apiFetch('/queues', token).catch(rethrowUnauthorized),
      ]);
      setWorkers(Array.isArray(w) ? w : []);
      setLogs(Array.isArray(l) ? l : []);
      setShops(Array.isArray(s) ? s : []);
      setQueues(Array.isArray(q) ? q : []);
    } catch (err) {
      if (err.message === 'unauthorized') handleLogout();
    } finally {
      setLoading(false);
    }
  }, [token]);

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

  // auto-refresh every 30s
  useEffect(() => {
    const t = setInterval(load, 30_000);
    return () => clearInterval(t);
  }, [load]);

  if (!token) return <Login onLogin={handleLogin} />;

  function renderView() {
    switch (view) {
      case 'overview':  return <Overview workers={workers} logs={logs} shops={shops} queues={queues} />;
      case 'shops':     return <Shops shops={shops} />;
      case 'products':  return <Products token={token} onUnauthorized={handleLogout} />;
      case 'workers':   return <Workers workers={workers} logs={logs} queues={queues} onSelectType={setSelectedWorkerType} />;
      case 'errors':   return <Errors logs={logs} />;
      case 'logs':     return <Logs logs={logs} />;
      default:         return null;
    }
  }

  const viewLabel = NAV.find(n => n.id === view)?.label ?? '';

  return (
    <div className="layout">
      <Sidebar view={view} setView={setView} onLogout={handleLogout} />
      <div className="main">
        <div className="topbar">
          <span className="topbar-title">{viewLabel}</span>
          <span className="topbar-spacer" />
          <button className="btn-ghost" onClick={load} disabled={loading}>
            <Icon name="refresh" size={13} />
            {loading ? 'Lädt…' : 'Aktualisieren'}
          </button>
          <button className="btn-ghost" onClick={toggleTheme} title={theme === 'dark' ? 'Light Mode' : 'Dark Mode'}>
            <Icon name={theme === 'dark' ? 'sun' : 'moon'} size={13} />
          </button>
        </div>
        <div className="content">
          {renderView()}
        </div>
      </div>
      {selectedWorkerType && (
        <WorkerDrawer
          workerType={selectedWorkerType}
          logs={logs}
          onClose={() => setSelectedWorkerType(null)}
        />
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
