/* global React, RC */
// Devices — Editorial. Card grid of cam boards with their identity,
// online state, current config snapshot, OTA + USB-yaml actions.

const { useState: useSD, useEffect: useED, useCallback: useCD } = React;

function DevicesTab({ streams, toast }) {
  const [list, setList] = useSD([]);
  const [creating, setCreating] = useSD(false);
  const [editing, setEditing] = useSD(null);

  const refresh = useCD(async () => {
    try { setList(await RC.apiFetch('/api/devices')); }
    catch (e) { toast?.(e.message, 'error'); }
  }, []);
  useED(() => { refresh(); }, []);
  useED(() => {
    const t = setInterval(refresh, 5000);
    return () => clearInterval(t);
  }, [refresh]);

  const remove = async (d) => {
    if (!confirm(`Device "${d.name}" löschen?`)) return;
    try { await RC.apiFetch('/api/devices/' + d.id, { method: 'DELETE' }); refresh(); }
    catch (e) { toast?.(e.message, 'error'); }
  };
  const push = async (d) => {
    try {
      const r = await RC.apiFetch('/api/devices/' + d.id + '/push', { method: 'POST' });
      toast?.(r.online ? 'OTA pushed' : 'Device offline — picks up on next hello');
    } catch (e) { toast?.(e.message, 'error'); }
  };
  const downloadYaml = (d) => {
    const url = `${RC.baseUrl}/api/devices/${d.id}/bundle.yaml?token=${RC.getToken()}`;
    const a = document.createElement('a');
    a.href = url; a.download = `racecast-${d.name.replace(/\W+/g, '-')}.yaml`;
    a.click();
  };
  const newToken = async (d) => {
    try {
      await RC.apiFetch('/api/devices/' + d.id + '/enrollment', { method: 'POST' });
      toast?.('new enrollment token minted');
      refresh();
    } catch (e) { toast?.(e.message, 'error'); }
  };

  return (
    <>
      <div className="ed-page-head">
        <div>
          <div className="ed-page-head__lead">Hardware</div>
          <h1 className="ed-page-head__title">Cam <em>boards</em>.</h1>
        </div>
        <div className="ed-page-head__actions">
          <button className="ed-btn ed-btn--ferrari" onClick={() => setCreating(true)}>+ new device</button>
        </div>
      </div>

      {list.length === 0 ? (
        <EmptyList title="No boards adopted yet."
          body={<>Mit <strong>+ new device</strong> erzeugst du ein Provisioning-yaml. Auf einen USB-Stick (Label <span className="ed-mono" style={{ color: 'var(--ed-cream-dim)' }}>RACECAST</span>) und in die Radxa stecken — beim ersten Boot enrollt sich das Board automatisch.</>} />
      ) : (
        <div style={{ display: 'grid', gap: 14, gridTemplateColumns: 'repeat(auto-fill, minmax(380px, 1fr))' }}>
          {list.map((d) => (
            <DeviceCard key={d.id} d={d} streams={streams}
              onEdit={() => setEditing(d)}
              onDelete={() => remove(d)}
              onPush={() => push(d)}
              onDownload={() => downloadYaml(d)}
              onRotateToken={() => newToken(d)}
            />
          ))}
        </div>
      )}

      {creating && <DeviceFormModal mode="create" streams={streams}
        onClose={() => setCreating(false)}
        onSaved={() => { setCreating(false); refresh(); }}
        toast={toast} />}
      {editing && <DeviceFormModal mode="edit" device={editing} streams={streams}
        onClose={() => setEditing(null)}
        onSaved={() => { setEditing(null); refresh(); }}
        toast={toast} />}
    </>
  );
}

function DeviceCard({ d, streams, onEdit, onDelete, onPush, onDownload, onRotateToken }) {
  const stream = streams.find((s) => s.id === d.streamId);
  const cellular = d.config?.network?.cellular;
  const enc = d.config?.encoder;
  const h = d.health || {};

  return (
    <div style={{
      borderTop: '1px solid var(--ed-rule-strong)',
      borderBottom: '1px solid var(--ed-rule)',
      padding: '20px 0',
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, marginBottom: 12 }}>
        <span style={{
          width: 8, height: 8, borderRadius: '50%', marginTop: 8,
          background: d.online ? '#79b75c' : 'var(--ed-cream-trace)',
          boxShadow: d.online ? '0 0 8px rgba(121, 183, 92, 0.65)' : 'none',
        }} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontFamily: 'var(--ed-serif)',
            fontVariationSettings: "'opsz' 24, 'SOFT' 30",
            fontSize: 20, fontWeight: 400, color: 'var(--ed-cream)',
            letterSpacing: '-0.005em', lineHeight: 1.2,
          }}>{d.name}</div>
          <div style={{
            fontFamily: 'var(--ed-mono)', fontSize: 11,
            color: 'var(--ed-cream-faint)', marginTop: 2,
          }}>
            {d.id} · {stream?.name || 'unbound'} · v{d.configVersion}
            {d.appliedVersion !== d.configVersion && ` (applied v${d.appliedVersion})`}
          </div>
        </div>
        <span className={'ed-pill ed-pill--' + (d.status === 'adopted' ? 'live' : 'pending')}
              style={{ flexShrink: 0 }}>
          {d.status}
        </span>
      </div>

      <div className="ed-detail" style={{ gridTemplateColumns: '90px 1fr', marginBottom: 14 }}>
        <div className="ed-detail__label">Codec</div>
        <div className="ed-detail__value ed-mono">{enc?.codec?.toUpperCase() || '—'}{enc ? ` · ${(enc.bitrate_kbps / 1000).toFixed(1)} Mbps · ${enc.fps}fps` : ''}</div>
        <div className="ed-detail__label">APN</div>
        <div className="ed-detail__value ed-mono">{cellular?.apn || '—'}</div>
        <div className="ed-detail__label">Last seen</div>
        <div className="ed-detail__value">{d.lastSeenAt ? RC.fmtTimeAgo(d.lastSeenAt) : 'never'}</div>
      </div>

      {d.online && Object.keys(h).length > 0 && (
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14,
          padding: '12px 0',
          borderTop: '1px solid var(--ed-rule)',
          borderBottom: '1px solid var(--ed-rule)',
          marginBottom: 14,
        }}>
          <Mini label="Temp" value={h.cpu_temp != null ? `${Math.round(h.cpu_temp)}°` : '—'} />
          <Mini label="Signal" value={h.signal_dbm != null ? `${h.signal_dbm} dBm` : '—'} />
          <Mini label="Modem" value={h.modem_state || '—'} />
          <Mini label="Encoder" value={h.ffmpeg_alive ? 'alive' : 'down'} />
        </div>
      )}

      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        <button className="ed-btn ed-btn--ghost" onClick={onEdit}>config</button>
        <button className="ed-btn ed-btn--ghost" onClick={onPush} disabled={d.status !== 'adopted'}>↑ ota</button>
        <button className="ed-btn ed-btn--ghost" onClick={onDownload}>↓ usb yaml</button>
        <button className="ed-btn ed-btn--ghost" onClick={onRotateToken}>↻ token</button>
        <div style={{ flex: 1 }} />
        <button className="ed-btn ed-btn--ghost" onClick={onDelete}
                style={{ borderColor: 'var(--ed-rule)', color: 'var(--ed-cream-faint)' }}>×</button>
      </div>
    </div>
  );
}

function Mini({ label, value }) {
  return (
    <div>
      <div style={{
        fontFamily: 'var(--ed-body)', fontStyle: 'italic',
        fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase',
        color: 'var(--ed-cream-faint)', marginBottom: 2,
      }}>{label}</div>
      <div style={{ fontFamily: 'var(--ed-mono)', fontSize: 12, color: 'var(--ed-cream)' }}>{value}</div>
    </div>
  );
}

function DeviceFormModal({ mode, device, streams, onClose, onSaved, toast }) {
  const initial = mode === 'edit' ? (device.config || {}) : {};
  const [name, setName] = useSD(device?.name || '');
  const [streamId, setStreamId] = useSD(device?.streamId || streams[0]?.id || '');
  const [cell, setCell] = useSD(initial.network?.cellular || { enabled: true, apn: '', pin: '', username: '', password: '', auth: 'chap', ip_type: 'ipv4v6', roaming: false });
  const [wifi, setWifi] = useSD(initial.network?.wifi || { enabled: false, ssid: '', psk: '' });
  const [enc, setEnc] = useSD(initial.encoder || { codec: 'h265', bitrate_kbps: 6500, width: 1920, height: 1080, fps: 60, gop: 60, hw_accel: 'rkmpp', rate_control: 'cbr' });
  const [busy, setBusy] = useSD(false);
  const [created, setCreated] = useSD(null);

  const submit = async (e) => {
    e?.preventDefault?.(); setBusy(true);
    try {
      const cfg = {
        network: { primary: 'cellular', cellular: cell, wifi, ethernet: { enabled: true, dhcp: true } },
        encoder: enc,
      };
      if (mode === 'create') {
        const r = await RC.apiFetch('/api/devices', { method: 'POST', body: { name, streamId, config: cfg } });
        setCreated(r);
        toast?.('Device erstellt');
      } else {
        await RC.apiFetch('/api/devices/' + device.id, { method: 'PATCH', body: { name, streamId, config: cfg } });
        toast?.('Config gespeichert (v' + (device.configVersion + 1) + ')');
        onSaved();
      }
    } catch (err) { toast?.(err.message, 'error'); }
    finally { setBusy(false); }
  };

  return (
    <div className="ed-modal-backdrop" onClick={onClose}>
      <form className="ed-modal ed-modal--wide" onSubmit={submit} onClick={(e) => e.stopPropagation()}>
        <div className="ed-modal__head">
          <div>
            <div className="ed-modal__lead">Device</div>
            <h2 className="ed-modal__title">
              {mode === 'create' ? <>A new <em>cam board</em>.</> : <>Edit <em>{device.name}</em>.</>}
            </h2>
          </div>
          <button type="button" className="ed-modal__close" onClick={onClose}>✕</button>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
          <div className="ed-form-row--double">
            <FormField label="Name">
              <input className="ed-input" value={name} onChange={(e) => setName(e.target.value)}
                     placeholder="e.g. Cockpit Cam #1" required disabled={!!created} autoFocus />
            </FormField>
            <FormField label="Stream">
              <select className="ed-input" value={streamId} onChange={(e) => setStreamId(e.target.value)}>
                {streams.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
              </select>
            </FormField>
          </div>

          <div className="ed-aside-section" style={{ paddingTop: 20 }}>
            <div className="ed-aside-section__title">Cellular · 4G</div>
            <Toggle label="Enabled" value={!!cell.enabled} onChange={(v) => setCell({ ...cell, enabled: v })} />
            <div style={{ height: 10 }} />
            <div className="ed-form-row--double">
              <FormField label="APN">
                <input className="ed-input" value={cell.apn || ''} onChange={(e) => setCell({ ...cell, apn: e.target.value })}
                       placeholder="internet.t-mobile" />
              </FormField>
              <FormField label="SIM PIN">
                <input className="ed-input" value={cell.pin || ''} onChange={(e) => setCell({ ...cell, pin: e.target.value })}
                       placeholder="optional" pattern="[0-9]{4,8}" />
              </FormField>
            </div>
            <div className="ed-form-row--double">
              <FormField label="User">
                <input className="ed-input" value={cell.username || ''} onChange={(e) => setCell({ ...cell, username: e.target.value })} />
              </FormField>
              <FormField label="Password">
                <input className="ed-input" type="password" value={cell.password || ''} onChange={(e) => setCell({ ...cell, password: e.target.value })} />
              </FormField>
            </div>
          </div>

          <div className="ed-aside-section">
            <div className="ed-aside-section__title">WiFi · backup</div>
            <Toggle label="Enabled" value={!!wifi.enabled} onChange={(v) => setWifi({ ...wifi, enabled: v })} />
            {wifi.enabled && (<>
              <div style={{ height: 10 }} />
              <FormField label="SSID">
                <input className="ed-input" value={wifi.ssid || ''} onChange={(e) => setWifi({ ...wifi, ssid: e.target.value })} />
              </FormField>
              <FormField label="Password">
                <input className="ed-input" type="password" value={wifi.psk || ''} onChange={(e) => setWifi({ ...wifi, psk: e.target.value })} />
              </FormField>
            </>)}
          </div>

          <div className="ed-aside-section">
            <div className="ed-aside-section__title">Encoder</div>
            <div className="ed-form-row--double">
              <FormField label="Codec">
                <select className="ed-input" value={enc.codec} onChange={(e) => setEnc({ ...enc, codec: e.target.value })}>
                  <option value="h264">H.264</option>
                  <option value="h265">H.265 (HEVC)</option>
                </select>
              </FormField>
              <FormField label="HW accel">
                <select className="ed-input" value={enc.hw_accel} onChange={(e) => setEnc({ ...enc, hw_accel: e.target.value })}>
                  <option value="rkmpp">Rockchip MPP</option>
                  <option value="vaapi">VAAPI</option>
                  <option value="software">Software</option>
                </select>
              </FormField>
            </div>
            <div className="ed-form-row--double">
              <FormField label="Resolution">
                <input className="ed-input" value={`${enc.width}×${enc.height}`}
                       onChange={(e) => {
                         const [w, h] = e.target.value.split(/[x×]/i).map((n) => +n);
                         if (w && h) setEnc({ ...enc, width: w, height: h });
                       }} />
              </FormField>
              <FormField label="FPS">
                <input className="ed-input" type="number" value={enc.fps} onChange={(e) => setEnc({ ...enc, fps: +e.target.value })} />
              </FormField>
            </div>
            <FormField label={`Bitrate · ${(enc.bitrate_kbps / 1000).toFixed(1)} Mbps`}>
              <input type="range" min="500" max="15000" step="100" value={enc.bitrate_kbps}
                     onChange={(e) => setEnc({ ...enc, bitrate_kbps: +e.target.value })}
                     style={{ accentColor: 'var(--ed-ferrari)' }} />
            </FormField>
          </div>
        </div>

        {created && (
          <div style={{
            marginTop: 18, padding: '18px 20px',
            border: '1px solid var(--ed-amber)',
            borderLeft: '4px solid var(--ed-amber)',
          }}>
            <div className="ed-modal__lead" style={{ color: 'var(--ed-amber)' }}>Provisioning bundle</div>
            <p style={{ fontFamily: 'var(--ed-body)', fontSize: 13, lineHeight: 1.5,
                        color: 'var(--ed-cream-dim)', marginTop: 8 }}>
              Lade das yaml runter, schreib es auf einen USB-Stick (Label <span className="ed-mono">RACECAST</span>),
              steck ihn ins Board beim ersten Boot. Token <span className="ed-mono" style={{ color: 'var(--ed-cream)' }}>{created.enrollment.token}</span> ist 24h gültig, single-use.
            </p>
            <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
              <button type="button" className="ed-btn ed-btn--ferrari"
                onClick={() => {
                  const url = `${RC.baseUrl}/api/devices/${created.id}/bundle.yaml?token=${RC.getToken()}`;
                  const a = document.createElement('a');
                  a.href = url; a.download = `racecast-${created.name.replace(/\W+/g, '-')}.yaml`;
                  a.click();
                }}>↓ download yaml</button>
              <button type="button" className="ed-btn" onClick={onSaved}>done</button>
            </div>
          </div>
        )}

        {!created && (
          <div className="ed-modal__foot">
            <button type="button" className="ed-btn" onClick={onClose}>cancel</button>
            <button type="submit" className="ed-btn ed-btn--ferrari" disabled={busy}>
              {busy ? <span className="ed-spin" /> : (mode === 'create' ? 'create ›' : 'save + push ›')}
            </button>
          </div>
        )}
      </form>
    </div>
  );
}

function Toggle({ label, value, onChange }) {
  return (
    <label className={'ed-toggle' + (value ? ' ed-toggle--on' : '')}>
      <button type="button" className="ed-toggle__track" onClick={() => onChange(!value)}>
        <span className="ed-toggle__thumb" />
      </button>
      <span className="ed-toggle__label">{label}</span>
    </label>
  );
}

function FormField({ label, children }) {
  return (
    <label className="ed-form-row">
      <span className="ed-form-row__label">{label}</span>
      {children}
    </label>
  );
}

window.DevicesTab = DevicesTab;
