/* global React, Card, Button, Input, Ic, Breadcrumb, VS, LoadingState, ErrorState, GlassDropdown */

// ============================================================
// LIST SCREEN
// ============================================================
function ZaleceniaRemontoweScreen() {
  const [activeId, setActiveId] = React.useState(null);
  const [list, setList] = React.useState(null);
  const [facilities, setFacilities] = React.useState([]);
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [facilityFilter, setFacilityFilter] = React.useState('');

  const load = React.useCallback(() => {
    setList(null); setErr('');
    VS.zaleceniaProtocols(facilityFilter || undefined)
      .then((r) => setList(r || []))
      .catch((e) => setErr(e.message));
  }, [facilityFilter]);

  React.useEffect(() => {
    VS.zaleceniaFacilities()
      .then((r) => setFacilities(r || []))
      .catch(() => setFacilities([]));
  }, []);

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

  async function createNew() {
    setBusy(true);
    try {
      const r = await VS.createZaleceniaProtocol();
      setActiveId(r.id);
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  }

  async function removeRow(id) {
    if (!confirm('Usunąć ten protokół?')) return;
    try {
      await VS.deleteZaleceniaProtocol(id);
      load();
    } catch (e) {
      alert('Błąd: ' + e.message);
    }
  }

  if (activeId) {
    return (
      <ZaleceniaEditor
        protocolId={activeId}
        facilities={facilities}
        onBack={() => { setActiveId(null); load(); }}
      />
    );
  }

  return (
    <div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}>
        <div>
          <div className="uppercase-label" style={{ marginBottom: 6 }}>Raporty</div>
          <h1 style={{ margin: 0, fontSize: 24, fontWeight: 500, letterSpacing: '-0.02em' }}>Zalecenia remontowe</h1>
          <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginTop: 6 }}>
            Protokoły zaleceń remontowych dla urządzeń zakładów BC-1/2/3 i innych.
          </div>
        </div>
        <Button variant="primary" icon={<Ic.plus size={12} />} onClick={createNew} disabled={busy}>
          {busy ? 'Tworzę…' : 'Nowy protokół'}
        </Button>
      </div>

      {/* Filter */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <span className="uppercase-label">Zakład</span>
        <GlassDropdown
          value={facilityFilter || ''}
          onChange={(v) => setFacilityFilter(v || '')}
          options={[
            { value: '', label: 'Wszystkie zakłady' },
            ...(facilities || []).map((f) => ({
              value: f.id,
              label: `${f.code} — ${f.name}`,
            })),
          ]}
          placeholder="Wszystkie zakłady"
          searchPlaceholder="Szukaj zakładu…"
          emptyLabel="Brak zakładów."
          minWidth={280}
        />
      </div>

      {err && <ErrorState message={err} />}
      {!err && !list && <LoadingState />}
      {!err && list && list.length === 0 && (
        <Card>
          <div style={{ textAlign: 'center', padding: 28, color: 'var(--fg-muted)', fontSize: 13 }}>
            <div className="uppercase-label" style={{ marginBottom: 6 }}>Brak protokołów</div>
            <div>Utwórz nowy protokół aby zacząć.</div>
          </div>
        </Card>
      )}
      {!err && list && list.length > 0 && (
        <Card pad={false}>
          <div style={{
            display: 'grid', gridTemplateColumns: '140px 1fr 110px 130px 140px 200px',
            gap: 10, padding: '10px 16px', borderBottom: '1px solid var(--hairline)',
            fontSize: 10, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600,
          }}>
            <div>Zakład</div>
            <div>Tytuł</div>
            <div>Ważny do</div>
            <div>Ost. edycja</div>
            <div>Autor</div>
            <div>Akcje</div>
          </div>
          {list.map((p, i) => (
            <div
              key={p.id}
              style={{
                display: 'grid', gridTemplateColumns: '140px 1fr 110px 130px 140px 200px',
                gap: 10, padding: '10px 16px',
                borderBottom: i < list.length - 1 ? '1px solid var(--hairline)' : 'none',
                alignItems: 'center', fontSize: 12.5, cursor: 'pointer',
              }}
              onClick={() => setActiveId(p.id)}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-sunken)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
            >
              <div className="mono" style={{ color: 'var(--fg)' }}>{p.facility_code || '—'}</div>
              <div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={p.title || ''}>
                {p.title || <span style={{ color: 'var(--fg-subtle)' }}>— bez tytułu —</span>}
              </div>
              <div className="mono" style={{ color: 'var(--fg-muted)' }}>{p.date_until || '—'}</div>
              <div className="mono" style={{ color: 'var(--fg-muted)', fontSize: 11 }}>
                {p.updated_at ? p.updated_at.slice(0, 16).replace('T', ' ') : '—'}
              </div>
              <div className="mono" style={{ fontSize: 11, color: 'var(--fg-muted)' }}>{p.created_by || '—'}</div>
              <div style={{ display: 'flex', gap: 6 }} onClick={(e) => e.stopPropagation()}>
                <Button size="sm" variant="ghost" icon={<Ic.edit size={11} />} onClick={() => setActiveId(p.id)}>
                  Edytuj
                </Button>
                <Button size="sm" variant="ghost" icon={<Ic.download size={11} />}
                  onClick={() => VS.openZaleceniaPdf(p.id).catch(e => alert('Błąd pobierania PDF: ' + e.message))}>
                  PDF
                </Button>
                <Button size="sm" variant="danger" onClick={() => removeRow(p.id)}>Usuń</Button>
              </div>
            </div>
          ))}
        </Card>
      )}
    </div>
  );
}

// ============================================================
// EDITOR
// ============================================================
function ZaleceniaEditor({ protocolId, facilities, onBack }) {
  const [protocol, setProtocol] = React.useState(null);
  const [err, setErr] = React.useState('');
  const [users, setUsers] = React.useState(null); // null = loading, [] = none
  const [dirty, setDirty] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState('');
  // bust counters per device idx — centralny map, inkrementowany po uploadzie/usunięciu
  // żeby <img> odświeżył się bez cache
  const [trendBustMap, setTrendBustMap] = React.useState({});

  // Normalizuje odpowiedź protokołu do lokalnego state.
  const adjustProtocol = React.useCallback((p) => ({
    ...p,
    devices: Array.isArray(p.devices) ? p.devices : [],
  }), []);

  const refreshProtocol = React.useCallback(async () => {
    const p = await VS.zaleceniaProtocol(protocolId);
    setProtocol(adjustProtocol(p));
  }, [protocolId, adjustProtocol]);

  React.useEffect(() => {
    VS.zaleceniaProtocol(protocolId)
      .then((p) => setProtocol(adjustProtocol(p)))
      .catch((e) => setErr(e.message));

    // Try admin-wide user list; fallback to self-only stamp.
    VS.userStamps()
      .then((list) => setUsers(list || []))
      .catch(() => {
        VS.myStamp()
          .then((me) => setUsers([{
            user_id: me.user_id, username: me.username,
            name: me.name, cert_number: me.cert_number, has_image: me.has_image,
          }]))
          .catch(() => setUsers([]));
      });
  }, [protocolId]);

  function patch(p) {
    setProtocol((prev) => ({ ...prev, ...p }));
    setDirty(true);
  }

  function updateDevice(idx, field, value) {
    setProtocol((prev) => {
      const devices = prev.devices.map((d, i) => (i === idx ? { ...d, [field]: value } : d));
      return { ...prev, devices };
    });
    setDirty(true);
  }

  function updateDeviceUwaga(idx, uIdx, value) {
    setProtocol((prev) => {
      const devices = prev.devices.map((d, i) => {
        if (i !== idx) return d;
        const uwagi = Array.isArray(d.uwagi) ? [...d.uwagi] : [];
        uwagi[uIdx] = value;
        return { ...d, uwagi };
      });
      return { ...prev, devices };
    });
    setDirty(true);
  }

  function removeDeviceUwaga(idx, uIdx) {
    setProtocol((prev) => {
      const devices = prev.devices.map((d, i) => {
        if (i !== idx) return d;
        const uwagi = (Array.isArray(d.uwagi) ? d.uwagi : []).filter((_, j) => j !== uIdx);
        return { ...d, uwagi };
      });
      return { ...prev, devices };
    });
    setDirty(true);
  }

  function addDeviceUwaga(idx) {
    setProtocol((prev) => {
      const devices = prev.devices.map((d, i) => {
        if (i !== idx) return d;
        const uwagi = Array.isArray(d.uwagi) ? [...d.uwagi, ''] : [''];
        return { ...d, uwagi };
      });
      return { ...prev, devices };
    });
    setDirty(true);
  }

  function addDevice() {
    setProtocol((prev) => ({
      ...prev,
      devices: [...(prev.devices || []), { code: '', name: '', ocena: '', uwagi: [], trend_note: '' }],
    }));
    setDirty(true);
  }

  function removeDevice(idx) {
    // TODO: jeśli device.has_trend_image — warto wywołać backendowe usunięcie obrazka,
    // żeby nie zostawić osieroconego pliku. Dodatkowo: obecnie indeksy są stabilne,
    // więc upload wiąże obrazek do pozycji na liście — jeśli kiedyś dojdzie drag/drop
    // lub zmiana kolejności, trzeba re-indeksować po stronie backendu.
    const dev = (protocol?.devices || [])[idx];
    if (dev && dev.has_trend_image) {
      VS.deleteZaleceniaTrend(protocolId, idx).catch(() => { /* best effort */ });
    }
    setProtocol((prev) => ({ ...prev, devices: prev.devices.filter((_, i) => i !== idx) }));
    setDirty(true);
  }

  async function onTrendUpload(idx, file) {
    try {
      await VS.uploadZaleceniaTrend(protocolId, idx, file);
      setTrendBustMap((m) => ({ ...m, [idx]: Date.now() }));
      // Optymistyczny merge — tylko flaga has_trend_image, bez refreshu,
      // żeby nie nadpisać niezapisanych zmian w polach urządzeń.
      setProtocol((prev) => ({
        ...prev,
        devices: prev.devices.map((d, i) =>
          i === idx ? { ...d, has_trend_image: true } : d
        ),
      }));
    } catch (e) {
      alert('Błąd uploadu: ' + e.message);
    }
  }

  async function onTrendDelete(idx) {
    if (!confirm('Usunąć obrazek trendu?')) return;
    try {
      await VS.deleteZaleceniaTrend(protocolId, idx);
      setTrendBustMap((m) => ({ ...m, [idx]: Date.now() }));
      setProtocol((prev) => ({
        ...prev,
        devices: prev.devices.map((d, i) =>
          i === idx ? { ...d, has_trend_image: false } : d
        ),
      }));
    } catch (e) {
      alert('Błąd usuwania: ' + e.message);
    }
  }

  async function save() {
    if (!protocol) return;
    setBusy(true); setMsg('');
    try {
      const payload = {
        facility_id: protocol.facility_id,
        facility_code: protocol.facility_code || '',
        title: protocol.title || '',
        date_until: protocol.date_until || null,
        devices: (protocol.devices || []).map((d) => ({
          code: d.code || '',
          name: d.name || '',
          ocena: d.ocena || '',
          uwagi: (Array.isArray(d.uwagi) ? d.uwagi : []).filter((u) => u != null),
          trend_note: d.trend_note || '',
        })),
        opracowal_user_id: protocol.opracowal_user_id,
        opracowal_date: protocol.opracowal_date || null,
      };
      await VS.saveZaleceniaProtocol(protocolId, payload);
      setDirty(false);
      setMsg('Zapisano.');
      setTimeout(() => setMsg(''), 2500);
    } catch (e) {
      setMsg('Błąd: ' + e.message);
    } finally {
      setBusy(false);
    }
  }

  async function removeProtocol() {
    if (!confirm('Usunąć ten protokół? Operacja nieodwracalna.')) return;
    try {
      await VS.deleteZaleceniaProtocol(protocolId);
      onBack();
    } catch (e) {
      alert('Błąd: ' + e.message);
    }
  }

  async function downloadPdf() {
    if (dirty) await save();
    try {
      await VS.openZaleceniaPdf(protocolId);
    } catch (e) {
      alert('Błąd pobierania PDF: ' + e.message);
    }
  }

  if (err) return <ErrorState message={err} />;
  if (!protocol) return <LoadingState />;

  const facilityCodes = (facilities || []).map((f) => f.code);
  const selectedFacility = (facilities || []).find((f) => f.code === protocol.facility_code);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 56px)', overflow: 'hidden' }}>
      <div style={{ padding: '18px 24px', borderBottom: '1px solid var(--border)', flexShrink: 0 }}>
        <Breadcrumb items={[
          { label: 'Zalecenia remontowe', onClick: onBack },
          { label: `#${protocolId}${protocol.facility_code ? ' · ' + protocol.facility_code : ''}` },
        ]} />
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginTop: 12 }}>
          <div>
            <h1 style={{ margin: 0, fontSize: 22, fontWeight: 500, letterSpacing: '-0.02em' }}>
              Zalecenia remontowe <span className="mono" style={{ color: 'var(--fg-muted)' }}>#{protocolId}</span>
            </h1>
            <div style={{ fontSize: 11.5, color: 'var(--fg-muted)', marginTop: 6 }}>
              {dirty ? (
                <span style={{ color: 'var(--warn)' }}>● Niezapisane zmiany</span>
              ) : (
                <span>Wszystkie zmiany zapisane</span>
              )}
              {msg && (
                <span className="mono" style={{ marginLeft: 12, color: msg.startsWith('Błąd') ? 'var(--alarm)' : 'var(--ok)' }}>
                  {msg}
                </span>
              )}
            </div>
          </div>
        </div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
        {/* Metadane */}
        <Card>
          <div className="uppercase-label" style={{ marginBottom: 14 }}>Metadane</div>
          <div style={{ display: 'grid', gridTemplateColumns: '200px 1fr 180px', gap: 12 }}>
            <label>
              <div className="uppercase-label" style={{ marginBottom: 6 }}>Zakład (kod)</div>
              <input
                list={`facility-codes-${protocolId}`}
                value={protocol.facility_code || ''}
                onChange={(e) => {
                  const code = e.target.value;
                  const match = (facilities || []).find((f) => f.code === code);
                  patch({ facility_code: code, facility_id: match ? match.id : null });
                }}
                placeholder="np. BC-1"
                style={zinputStyle}
              />
              <datalist id={`facility-codes-${protocolId}`}>
                {facilityCodes.map((c, i) => <option key={i} value={c} />)}
              </datalist>
              {selectedFacility && (
                <div className="mono" style={{ fontSize: 10, color: 'var(--fg-muted)', marginTop: 4 }}>
                  {selectedFacility.name}
                </div>
              )}
            </label>

            <label>
              <div className="uppercase-label" style={{ marginBottom: 6 }}>Tytuł</div>
              <textarea
                rows={2}
                value={protocol.title || ''}
                onChange={(e) => patch({ title: e.target.value })}
                placeholder={protocol.facility_code ? `Zalecenia remontowe — ${protocol.facility_code}` : 'Tytuł protokołu'}
                style={ztextareaStyle}
              />
            </label>

            <label>
              <div className="uppercase-label" style={{ marginBottom: 6 }}>Ważny do</div>
              <input
                type="date"
                value={protocol.date_until || ''}
                onChange={(e) => patch({ date_until: e.target.value })}
                style={zinputStyle}
              />
            </label>
          </div>
        </Card>

        {/* Devices */}
        <Card pad={false}>
          <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--hairline)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div className="uppercase-label">Urządzenia</div>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
              {(protocol.devices || []).length} urządzeń
            </span>
          </div>
          <div style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 12 }}>
            {(protocol.devices || []).length === 0 && (
              <div style={{ padding: 16, textAlign: 'center', color: 'var(--fg-muted)', fontSize: 12.5 }}>
                Brak urządzeń — dodaj pierwsze.
              </div>
            )}
            {(protocol.devices || []).map((d, i) => (
              <DeviceRow
                key={i}
                protocolId={protocolId}
                idx={i}
                device={d}
                trendBust={trendBustMap[i]}
                onChange={(field, val) => updateDevice(i, field, val)}
                onRemove={() => removeDevice(i)}
                onUwagaChange={(uIdx, val) => updateDeviceUwaga(i, uIdx, val)}
                onUwagaRemove={(uIdx) => removeDeviceUwaga(i, uIdx)}
                onUwagaAdd={() => addDeviceUwaga(i)}
                onTrendUpload={(file) => onTrendUpload(i, file)}
                onTrendDelete={() => onTrendDelete(i)}
              />
            ))}
            <div>
              <Button size="sm" icon={<Ic.plus size={12} />} onClick={addDevice}>
                Dodaj urządzenie
              </Button>
            </div>
          </div>
        </Card>

        {/* Opracował */}
        <Card>
          <div className="uppercase-label" style={{ marginBottom: 14 }}>Opracował</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 180px', gap: 12 }}>
            <OpracowalBlock
              users={users}
              userId={protocol.opracowal_user_id}
              onChange={(id) => patch({ opracowal_user_id: id })}
            />
            <label>
              <div className="uppercase-label" style={{ marginBottom: 6 }}>Data opracowania</div>
              <input
                type="date"
                value={protocol.opracowal_date || ''}
                onChange={(e) => patch({ opracowal_date: e.target.value })}
                style={zinputStyle}
              />
            </label>
          </div>
        </Card>
      </div>

      {/* Sticky bottom bar */}
      <div style={{
        position: 'sticky', bottom: 0,
        background: 'var(--bg-elev)',
        borderTop: '1px solid var(--border)',
        padding: '12px 24px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        gap: 10, flexShrink: 0,
      }}>
        <Button variant="ghost" icon={<Ic.chevronLeft size={12} />} onClick={onBack}>
          Wróć do listy
        </Button>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          {dirty && (
            <span className="mono" style={{ fontSize: 11, color: 'var(--warn)' }}>● niezapisane zmiany</span>
          )}
          {msg && (
            <span className="mono" style={{ fontSize: 11, color: msg.startsWith('Błąd') ? 'var(--alarm)' : 'var(--ok)' }}>
              {msg}
            </span>
          )}
          <Button variant="primary" onClick={save} disabled={busy}>
            {busy ? 'Zapisuję…' : 'Zapisz'}
          </Button>
          <Button icon={<Ic.download size={12} />} onClick={downloadPdf} disabled={busy}>
            Pobierz PDF
          </Button>
          <Button variant="danger" onClick={removeProtocol}>
            Usuń protokół
          </Button>
        </div>
      </div>
    </div>
  );
}

function DeviceRow({
  protocolId, idx, device, trendBust,
  onChange, onRemove, onUwagaChange, onUwagaRemove, onUwagaAdd,
  onTrendUpload, onTrendDelete,
}) {
  const uwagi = Array.isArray(device.uwagi) ? device.uwagi : [];
  const fileRef = React.useRef(null);

  async function handleUpload(e) {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    try {
      await onTrendUpload(file);
    } finally {
      if (e.target) e.target.value = '';
    }
  }

  return (
    <div style={{
      border: '1px solid var(--hairline)',
      borderRadius: 'var(--r-sm)',
      padding: 12,
      background: 'var(--bg-sunken)',
      display: 'flex', flexDirection: 'column', gap: 10,
    }}>
      <div style={{ display: 'grid', gridTemplateColumns: '110px 1fr auto', gap: 8, alignItems: 'center' }}>
        <Input value={device.code || ''} onChange={(e) => onChange('code', e.target.value)} placeholder="Kod" />
        <Input value={device.name || ''} onChange={(e) => onChange('name', e.target.value)} placeholder="Nazwa urządzenia" />
        <Button size="sm" variant="danger" onClick={onRemove}>Usuń</Button>
      </div>
      <label>
        <div className="uppercase-label" style={{ marginBottom: 4 }}>Ocena stanu dynamicznego</div>
        <textarea
          rows={2}
          value={device.ocena || ''}
          onChange={(e) => onChange('ocena', e.target.value)}
          placeholder="np. Stan dynamiczny dopuszczalny — praca bez ograniczeń"
          style={ztextareaStyle}
        />
      </label>
      <div>
        <div className="uppercase-label" style={{ marginBottom: 4 }}>Uwagi</div>
        {uwagi.length === 0 && (
          <div style={{ fontSize: 11.5, color: 'var(--fg-subtle)', marginBottom: 6 }}>Brak uwag.</div>
        )}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {uwagi.map((u, uIdx) => (
            <div key={uIdx} style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
              <Input
                value={u || ''}
                onChange={(e) => onUwagaChange(uIdx, e.target.value)}
                placeholder="Uwaga…"
                style={{ flex: 1 }}
              />
              <button
                onClick={() => onUwagaRemove(uIdx)}
                title="Usuń uwagę"
                style={{
                  width: 26, height: 26, padding: 0,
                  background: 'transparent',
                  border: '1px solid var(--border)',
                  borderRadius: 'var(--r-sm)',
                  cursor: 'pointer', color: 'var(--fg-muted)',
                  fontSize: 14, lineHeight: 1,
                }}
              >×</button>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 6 }}>
          <Button size="sm" variant="ghost" icon={<Ic.plus size={11} />} onClick={onUwagaAdd}>
            Dodaj uwagę
          </Button>
        </div>
      </div>
      <label>
        <div className="uppercase-label" style={{ marginBottom: 4 }}>Trend — notatka (opcjonalnie)</div>
        <input
          value={device.trend_note || ''}
          onChange={(e) => onChange('trend_note', e.target.value)}
          placeholder="np. tendencja rosnąca — obserwować"
          style={zinputStyle}
        />
      </label>

      {/* Wykres trendu — obrazek (screen z SKF) */}
      <div>
        <div className="uppercase-label" style={{ marginTop: 4 }}>Wykres trendu (screen z SKF)</div>
        <div style={{ display: 'flex', gap: 8, marginTop: 6, alignItems: 'flex-start' }}>
          <input
            ref={fileRef}
            type="file"
            accept="image/*"
            style={{ display: 'none' }}
            onChange={handleUpload}
          />
          <Button
            size="sm" variant="ghost"
            icon={<Ic.upload size={11} />}
            onClick={() => fileRef.current && fileRef.current.click()}
          >
            {device.has_trend_image ? 'Zmień obrazek' : 'Wgraj obrazek'}
          </Button>
          {device.has_trend_image && (
            <Button size="sm" variant="danger" onClick={onTrendDelete}>
              Usuń obrazek
            </Button>
          )}
        </div>
        {device.has_trend_image && (
          <div style={{
            marginTop: 8, maxWidth: 400,
            border: '1px solid var(--border)',
            borderRadius: 4, padding: 4,
            background: 'var(--bg-sunken)',
          }}>
            <img
              src={VS.zaleceniaTrendImageUrl(protocolId, idx, trendBust)}
              alt="Wykres trendu"
              style={{ width: '100%', objectFit: 'contain', maxHeight: 220, display: 'block' }}
            />
          </div>
        )}
      </div>
    </div>
  );
}

function OpracowalBlock({ users, userId, onChange }) {
  const selected = users ? users.find((u) => u.user_id === userId) : null;
  const isLoading = users === null;

  return (
    <div>
      <div className="uppercase-label" style={{ marginBottom: 6 }}>Użytkownik</div>
      {isLoading ? (
        <div style={{ fontSize: 12, color: 'var(--fg-muted)' }}>Ładowanie…</div>
      ) : users.length === 0 ? (
        <div style={{ fontSize: 12, color: 'var(--fg-muted)' }}>Brak dostępnych użytkowników.</div>
      ) : (
        <GlassDropdown
          value={userId ?? ''}
          onChange={(v) => onChange(v === '' ? null : v)}
          options={[
            { value: '', label: '— nie wybrano —' },
            ...users.map((u) => ({
              value: u.user_id,
              label: u.username + (u.name ? ` (${u.name})` : ''),
              hint: u.cert_number ? `nr świadectwa: ${u.cert_number}` : undefined,
            })),
          ]}
          placeholder="— nie wybrano —"
          searchPlaceholder="Szukaj użytkownika…"
          emptyLabel="Brak użytkowników."
          minWidth={320}
        />
      )}
      {selected && (
        <div style={{ marginTop: 10, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <div style={{
            width: 120, height: 50,
            border: '1px solid var(--border)',
            borderRadius: 'var(--r-sm)',
            background: 'var(--surface)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            overflow: 'hidden', flexShrink: 0,
          }}>
            {selected.has_image ? (
              <img
                src={VS.userStampImageUrl(selected.user_id)}
                alt=""
                style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
              />
            ) : (
              <span className="uppercase-label" style={{ color: 'var(--fg-subtle)', fontSize: 9 }}>brak</span>
            )}
          </div>
          <div style={{ fontSize: 11.5, lineHeight: 1.5 }}>
            <div style={{ fontWeight: 500, color: 'var(--fg)' }}>{selected.name || '—'}</div>
            <div className="mono" style={{ color: 'var(--fg-muted)', fontSize: 10.5 }}>
              {selected.cert_number ? `nr świadectwa: ${selected.cert_number}` : 'brak nr świadectwa'}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// Shared styles
const zinputStyle = {
  width: '100%', height: 30, padding: '0 10px',
  background: 'var(--surface)',
  border: '1px solid var(--border-strong)',
  borderRadius: 'var(--r-sm)',
  fontSize: 12, color: 'var(--fg)', outline: 'none',
  fontFamily: 'inherit',
};
const ztextareaStyle = {
  width: '100%', padding: 10,
  background: 'var(--surface)',
  border: '1px solid var(--border-strong)',
  borderRadius: 'var(--r-sm)',
  fontSize: 12, color: 'var(--fg)', outline: 'none',
  fontFamily: 'inherit', resize: 'vertical',
};

Object.assign(window, { ZaleceniaRemontoweScreen, ZaleceniaEditor });
