// Adminpanel: ladda upp bild + skriv en kort beskrivning per katalogartikel.
// Detta är underlaget en framtida "produktblad"-bilaga (och AI-skrivhjälpen)
// kan hämta riktig, verifierad information från — aldrig påhittad av AI:n.
function ProductAssetsPanel({ open, onClose }) {
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');
  const [q, setQ] = React.useState('');
  const [selectedSku, setSelectedSku] = React.useState(null);
  // Man behöver inte produktblad för alla 4500 artiklar — bara för det ni
  // faktiskt offererar. Filtren gör listan till en arbetslista.
  const [filter, setFilter] = React.useState('anvands');

  const load = async () => {
    setLoading(true); setError('');
    try {
      const rows = await api('/api/product-assets');
      setItems(rows);
    } catch (e) { setError('Kunde inte hämta artikellistan.'); }
    finally { setLoading(false); }
  };

  React.useEffect(() => { if (open) { setSelectedSku(null); setQ(''); load(); } }, [open]);

  // Redigeraren monteras om vid artikelbyte (key={sku}), så osparad text
  // försvann tidigare utan ett ord. Editorn flaggar här när något är oskrivet.
  const byt = (sku) => {
    if (window.__produktbladOsparat && !window.confirm('Du har ändringar som inte är sparade. Byta artikel ändå?')) return;
    window.__produktbladOsparat = false;
    setSelectedSku(sku);
  };

  if (!open) return null;

  const bySearch = q.trim()
    ? items.filter(it => (it.name + ' ' + it.sku + ' ' + it.cat).toLowerCase().includes(q.trim().toLowerCase()))
    : items;
  const filtered = q.trim() ? bySearch : bySearch.filter(it => (
    filter === 'alla' ? true
    : filter === 'saknas' ? !(it.hasImage || it.hasDescription)
    : filter === 'utkast' ? it.status === 'utkast'
    : /* anvands */ it.usedInOffers
  ));
  const antalUtkast = items.filter(it => it.status === 'utkast').length;
  const antalSaknas = items.filter(it => it.usedInOffers && !(it.hasImage || it.hasDescription)).length;

  const selected = items.find(it => it.sku === selectedSku) || null;

  const onSaved = (updated) => {
    setItems(prev => prev.map(it => it.sku === updated.sku ? { ...it, ...updated } : it));
  };

  return (
    <div onClick={onClose} style={{
      position:'fixed', inset:0, background:'rgba(0,54,95,.32)', zIndex:60,
      display:'flex', alignItems:'center', justifyContent:'center', padding:32,
    }}>
      <div role="dialog" aria-modal="true" aria-label="Produktblad" onClick={e => e.stopPropagation()} style={{
        width:'min(1000px, 100%)', height:'85vh', background:'#fff',
        borderRadius:8, boxShadow:'0 16px 48px rgba(0,54,95,.18)',
        display:'flex', flexDirection:'column', overflow:'hidden', fontFamily:'var(--font-sans)',
      }}>
        <div style={{padding:'22px 28px', borderBottom:'1px solid var(--border)', display:'flex', justifyContent:'space-between', alignItems:'center'}}>
          <div>
            <div style={{fontSize:11, fontWeight:600, letterSpacing:'.16em', textTransform:'uppercase', color:'var(--fg-muted)'}}>Administration</div>
            <h2 style={{margin:'4px 0 0', fontFamily:'var(--font-serif)', fontWeight:500, fontSize:24, color:'var(--ulab-navy)'}}>Produktblad — bilder &amp; beskrivningar</h2>
          </div>
          <button onClick={onClose} style={{background:'transparent', border:'none', cursor:'pointer', color:'var(--ulab-navy)'}}><Icon name="close" size={22}/></button>
        </div>

        <div style={{display:'flex', flex:1, minHeight:0}}>
          {/* Vänster: sökbar artikellista */}
          <div style={{width:340, borderRight:'1px solid var(--border)', display:'flex', flexDirection:'column', minHeight:0}}>
            <div style={{padding:14, borderBottom:'1px solid var(--border)'}}>
              <input
                value={q} onChange={e => setQ(e.target.value)}
                placeholder="Sök artikelnr, namn eller kategori…"
                style={{width:'100%', boxSizing:'border-box', fontSize:13, padding:'8px 10px', border:'1px solid var(--border-strong)', borderRadius:4, fontFamily:'var(--font-sans)'}}
              />
              <div style={{marginTop:8, display:'flex', gap:4, flexWrap:'wrap'}}>
                {[['anvands','I offerter'], ['saknas','Saknar blad'], ['utkast','Utkast'], ['alla','Alla']].map(([val, txt]) => (
                  <button key={val} onClick={() => setFilter(val)} style={{
                    padding:'4px 8px', borderRadius:999, fontSize:11, fontWeight:600, cursor:'pointer',
                    fontFamily:'var(--font-sans)',
                    border:'1px solid ' + (filter===val ? 'var(--ulab-navy)' : 'var(--border-strong)'),
                    background: filter===val ? 'var(--ulab-navy)' : '#fff',
                    color: filter===val ? '#fff' : 'var(--ulab-navy)',
                  }}>{txt}{val==='utkast' && antalUtkast ? ` (${antalUtkast})` : ''}{val==='saknas' && antalSaknas ? ` (${antalSaknas})` : ''}</button>
                ))}
              </div>
              <div style={{marginTop:8, fontSize:11, color:'var(--fg-muted)'}}>
                {q.trim() ? `${filtered.length} träffar` : `${filtered.length} artiklar · ${items.filter(it => it.hasImage || it.hasDescription).length} av ${items.length} har underlag`}
              </div>
            </div>
            <div style={{flex:1, overflow:'auto'}}>
              {loading ? <div style={{padding:14, fontSize:13, color:'var(--fg-muted)'}}>Laddar…</div> : (
                filtered.slice(0, 300).map(it => (
                  <button key={it.sku} onClick={() => byt(it.sku)} style={{
                    display:'block', width:'100%', textAlign:'left', background: it.sku === selectedSku ? 'var(--ulab-cream)' : 'transparent',
                    border:'none', borderBottom:'1px solid var(--border)', padding:'10px 14px', cursor:'pointer', fontFamily:'var(--font-sans)',
                  }}>
                    <div style={{display:'flex', alignItems:'center', gap:8}}>
                      <span style={{
                        width:8, height:8, borderRadius:99, flexShrink:0,
                        background: it.status === 'utkast' ? '#f0b866'
                          : (it.hasImage || it.hasDescription) ? 'var(--ulab-teal, #2a8f7a)' : 'var(--border-strong)',
                      }} title={it.status === 'utkast' ? 'AI-utkast — inte granskat' : (it.hasImage || it.hasDescription) ? 'Granskat underlag' : 'Saknar underlag'} />
                      <div style={{fontSize:13, fontWeight:600, color:'var(--ulab-navy)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>{it.name}</div>
                    </div>
                    <div style={{fontSize:11, color:'var(--fg-muted)', marginTop:2}}>{it.sku} · {it.cat}</div>
                  </button>
                ))
              )}
              {!loading && filtered.length > 300 && (
                <div style={{padding:14, fontSize:12, color:'var(--fg-muted)'}}>Visar de första 300 träffarna — sök snävare för fler.</div>
              )}
              {!loading && filtered.length === 0 && (
                <div style={{padding:14, fontSize:13, color:'var(--fg-muted)'}}>
                  {q.trim() ? 'Inga artiklar matchade sökningen.'
                    : filter === 'anvands' ? 'Inga artiklar används i någon offert ännu. Välj "Alla" för att bläddra i katalogen.'
                    : filter === 'utkast' ? 'Inga ogranskade AI-utkast — allt är genomgånget.'
                    : filter === 'saknas' ? 'Alla artiklar som används i offerter har produktblad.'
                    : 'Inga artiklar.'}
                </div>
              )}
            </div>
          </div>

          {/* Höger: redigering av vald artikel */}
          <div style={{flex:1, overflow:'auto', padding:24}}>
            {error && <div style={{color:'var(--ulab-coral)', fontSize:13, marginBottom:14}}>{error}</div>}
            {!selected ? (
              <div style={{color:'var(--fg-muted)', fontSize:13}}>Välj en artikel i listan till vänster för att lägga till bild eller beskrivning.</div>
            ) : (
              <ProductAssetEditor key={selected.sku} item={selected} onSaved={onSaved} />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// Gör om en data:-URL (base64-bild från research-svaret) till en File, så den
// kan skickas in i samma FormData som en vanlig filuppladdning.
function dataUrlToFile(dataUrl, filename) {
  const [meta, base64] = dataUrl.split(',');
  const mime = meta.match(/data:(.*);base64/)[1];
  const bytes = atob(base64);
  const arr = new Uint8Array(bytes.length);
  for (let i = 0; i < bytes.length; i++) arr[i] = bytes.charCodeAt(i);
  return new File([arr], filename, { type: mime });
}

// Skalar ner stora bilder innan de laddas upp. En produktbild från en
// leverantör kan vara flera megabyte och 4000 px bred — det gör utskrifterna
// onödigt tunga och fyller serverns disk utan att synas i tryck. 1600 px räcker
// gott och väl för en bild som visas ~260 px bred i offerten.
// Görs i webbläsaren, så servern slipper ett bildbibliotek.
const MAX_IMAGE_PX = 1600;
async function downscaleImage(file) {
  if (!/^image\/(png|jpe?g|webp)$/.test(file.type)) return file;
  try {
    const bitmap = await createImageBitmap(file);
    if (bitmap.width <= MAX_IMAGE_PX && bitmap.height <= MAX_IMAGE_PX && file.size < 1.5 * 1024 * 1024) {
      bitmap.close && bitmap.close();
      return file;
    }
    const scale = Math.min(1, MAX_IMAGE_PX / Math.max(bitmap.width, bitmap.height));
    const canvas = document.createElement('canvas');
    canvas.width = Math.round(bitmap.width * scale);
    canvas.height = Math.round(bitmap.height * scale);
    canvas.getContext('2d').drawImage(bitmap, 0, 0, canvas.width, canvas.height);
    bitmap.close && bitmap.close();
    // PNG behåller genomskinlighet (produktbilder är ofta frilagda).
    const type = file.type === 'image/png' ? 'image/png' : 'image/jpeg';
    const blob = await new Promise(r => canvas.toBlob(r, type, 0.88));
    if (!blob || blob.size >= file.size) return file;
    return new File([blob], file.name.replace(/\.[^.]+$/, '') + (type === 'image/png' ? '.png' : '.jpg'), { type });
  } catch (e) {
    return file; // kan webbläsaren inte skala om, skicka originalet
  }
}

function ProductAssetEditor({ item, onSaved }) {
  const [description, setDescription] = React.useState(item.description || '');
  // Flaggan som listan ovan läser innan den byter artikel.
  React.useEffect(() => {
    window.__produktbladOsparat = false;
    return () => { window.__produktbladOsparat = false; };
  }, [item.sku]);
  const [preview, setPreview] = React.useState(item.imageUrl || null);
  const [file, setFile] = React.useState(null);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState('');
  const [savedMsg, setSavedMsg] = React.useState('');
  const fileInputRef = React.useRef(null);

  const [sourceUrl, setSourceUrl] = React.useState(item.sourceUrl || '');
  const [fetching, setFetching] = React.useState(false);
  const [fetchError, setFetchError] = React.useState('');
  const [notFound, setNotFound] = React.useState(null);   // { note } när AI:n inte hittade produkten
  const [variantWarning, setVariantWarning] = React.useState(''); // varning när varianten inte kunde bekräftas
  const [sources, setSources] = React.useState(item.sources || []); // källor, sparas med produktbladet
  const [specs, setSpecs] = React.useState(item.specs || []);       // strukturerad specifikation
  const [showPreview, setShowPreview] = React.useState(false);      // visa bladet som kunden får se det
  const [status, setStatus] = React.useState(item.status || null);  // 'utkast' | 'granskad' | null

  const research = async () => {
    // AI:n skrev tidigare över en färdig, mänskligt skriven beskrivning rakt av
    // — till skillnad från AI-rutan inne i offerten, som frågar först. Det är
    // någons arbete som annars försvinner med ett klick.
    if (description.trim() && !window.confirm('Det finns redan en beskrivning här. AI:ns research ersätter den. Vill du fortsätta?')) return;
    setFetching(true); setFetchError(''); setNotFound(null); setVariantWarning(''); setSources([]);
    try {
      const res = await fetch(`/api/product-assets/research`, {
        method: 'POST', credentials: 'same-origin',
        headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'offertverktyg' },
        body: JSON.stringify({ sku: item.sku, url: sourceUrl.trim() }),
      });
      const body = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(body.error || 'Kunde inte ta fram produktblad');
      setSources(body.sources || []);
      if (!body.found) {
        setNotFound({ note: body.note || 'AI:n hittade ingen tillförlitlig information om den här artikeln.' });
        return;
      }
      window.__produktbladOsparat = true;
      setDescription(body.text || '');
      setSpecs(body.specs || []);
      setStatus('utkast');   // AI:n har skrivit det — en människa måste godkänna innan det går till kund
      if (!body.variantConfirmed) {
        setVariantWarning(body.variantNote || 'AI:n kunde inte säkerställa att informationen gäller exakt den här varianten — granska extra noga.');
      }
      if (body.imageDataUrl) {
        setPreview(body.imageDataUrl);
        setFile(dataUrlToFile(body.imageDataUrl, `${item.sku}-hamtad.jpg`));
      }
    } catch (e) { setFetchError(e.message || 'Kunde inte ta fram produktblad'); }
    finally { setFetching(false); }
  };

  const onPickFile = async (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    const scaled = await downscaleImage(f);
    setFile(scaled);
    setPreview(URL.createObjectURL(scaled));
  };

  const save = async () => {
    setSaving(true); setError(''); setSavedMsg('');
    try {
      const form = new FormData();
      // "sku" måste läggas till FÖRE "image" i formuläret — servern läser av
      // sku medan filen strömmas in för att kunna namnge den, och FormData-fält
      // läses i den ordning de lades till.
      form.append('sku', item.sku);
      form.append('description', description);
      form.append('specs', JSON.stringify(specs));
      form.append('sources', JSON.stringify(sources));
      form.append('sourceUrl', sourceUrl.trim());
      // Trycker man Spara har man läst igenom texten — då räknas den som granskad.
      form.append('status', 'granskad');
      if (file) form.append('image', await downscaleImage(file));
      // Ingen Content-Type här — webbläsaren sätter den själv för multipart.
      const res = await fetch(`/api/product-assets/save`, {
        method: 'POST', body: form, credentials: 'same-origin',
        headers: { 'X-Requested-With': 'offertverktyg' },
      });
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        throw new Error(body.error || 'Kunde inte spara');
      }
      const updated = await res.json();
      onSaved(updated);
      setFile(null);
      setStatus(updated.status || 'granskad');
      window.__produktbladOsparat = false;
      setSavedMsg('Sparat.');
      setTimeout(() => setSavedMsg(''), 2000);
    } catch (e) { setError(e.message || 'Kunde inte spara'); }
    finally { setSaving(false); }
  };

  const removeImage = async () => {
    if (!confirm('Ta bort bilden för denna artikel?')) return;
    setSaving(true); setError('');
    try {
      await api(`/api/product-assets/delete-image`, { method: 'POST', body: JSON.stringify({ sku: item.sku }) });
      setPreview(null); setFile(null);
      if (fileInputRef.current) fileInputRef.current.value = '';
      onSaved({ sku: item.sku, hasImage: false, imageUrl: null });
    } catch (e) { setError('Kunde inte ta bort bilden'); }
    finally { setSaving(false); }
  };

  return (
    <div>
      <div style={{marginBottom:18}}>
        <div style={{fontSize:11, fontWeight:600, letterSpacing:'.1em', textTransform:'uppercase', color:'var(--fg-muted)', display:'flex', alignItems:'center', gap:8}}>
          <span>{item.sku} · {item.cat}</span>
          {status === 'utkast' && (
            <span style={{padding:'2px 8px', borderRadius:999, background:'#fff7ed', border:'1px solid #f0b866', color:'#8a5a12', letterSpacing:0, textTransform:'none', fontSize:11}}>
              AI-utkast · inte granskat
            </span>
          )}
          {status === 'granskad' && (
            <span style={{padding:'2px 8px', borderRadius:999, background:'#eef7f4', border:'1px solid #9fcfc1', color:'#1f6b59', letterSpacing:0, textTransform:'none', fontSize:11}}>
              Granskat
            </span>
          )}
        </div>
        <h3 style={{margin:'4px 0 0', fontFamily:'var(--font-serif)', fontWeight:500, fontSize:20, color:'var(--ulab-navy)'}}>{item.name}</h3>
      </div>

      <div style={{
        marginBottom:20, padding:16, background:'var(--ulab-cream)', borderRadius:6, border:'1px solid var(--border)',
      }}>
        <div style={{display:'flex', gap:8, alignItems:'center'}}>
          <button onClick={research} disabled={fetching} style={{
            background:'var(--ulab-navy)', color:'#fff', border:'none', padding:'10px 18px',
            borderRadius:4, fontSize:13, fontWeight:600, cursor: fetching ? 'default' : 'pointer',
            whiteSpace:'nowrap', opacity: fetching ? 0.7 : 1,
          }}>{fetching ? 'Söker och läser…' : 'Skapa produktblad med AI'}</button>
          <div style={{fontSize:11, color:'var(--fg-muted)'}}>
            {fetching
              ? 'AI:n söker på nätet — det tar vanligtvis 10–30 sekunder.'
              : <>AI:n söker själv upp <b>{item.name}</b> och skriver ett utkast som du granskar innan du sparar.</>}
          </div>
        </div>

        <div style={{marginTop:12}}>
          <label style={{fontSize:11, color:'var(--fg-muted)', display:'block', marginBottom:4}}>
            Har du en bra produktlänk? Klistra in den så använder AI:n den som utgångspunkt (och hämtar bilden därifrån). Frivilligt.
          </label>
          <input
            value={sourceUrl} onChange={e => setSourceUrl(e.target.value)}
            placeholder="https://www.dustin.se/product/…  (valfritt)"
            style={{width:'100%', boxSizing:'border-box', fontSize:13, padding:'8px 10px', border:'1px solid var(--border-strong)', borderRadius:4, fontFamily:'var(--font-sans)'}}
          />
        </div>

        {fetchError && <div style={{color:'var(--ulab-coral)', fontSize:12, marginTop:10}}>{fetchError}</div>}

        {notFound && (
          <div style={{marginTop:10, padding:'10px 12px', background:'#fff7ed', border:'1px solid #f0b866', borderRadius:4, fontSize:12, color:'#8a5a12'}}>
            ⚠ AI:n hittade inget säkert underlag för <b>{item.name}</b>: {notFound.note} Du kan fylla i manuellt nedan istället.
          </div>
        )}

        {variantWarning && (
          <div style={{marginTop:10, padding:'10px 12px', background:'#fff7ed', border:'1px solid #f0b866', borderRadius:4, fontSize:12, color:'#8a5a12'}}>
            ⚠ <b>Osäker variant:</b> {variantWarning}
          </div>
        )}

        {sources.length > 0 && (
          <div style={{marginTop:12, paddingTop:10, borderTop:'1px solid var(--border)'}}>
            <div style={{fontSize:10, fontWeight:600, letterSpacing:'.14em', textTransform:'uppercase', color:'var(--fg-muted)', marginBottom:6}}>
              Källor AI:n använde
            </div>
            <div style={{display:'flex', flexDirection:'column', gap:3}}>
              {sources.slice(0, 8).map(s => (
                <a key={s.url} href={s.url} target="_blank" rel="noopener noreferrer"
                  style={{fontSize:11, color:'var(--ulab-blue)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>
                  {s.title || s.url}
                </a>
              ))}
            </div>
          </div>
        )}
      </div>

      {showPreview && (
        <div onClick={() => setShowPreview(false)} style={{
          position:'fixed', inset:0, background:'rgba(0,54,95,.4)', zIndex:80,
          display:'flex', alignItems:'center', justifyContent:'center', padding:24,
        }}>
          <div onClick={e => e.stopPropagation()} style={{
            background:'var(--ulab-cream)', width:'min(680px,100%)', maxHeight:'88vh', overflow:'auto',
            borderRadius:6, padding:'40px 48px', boxShadow:'0 16px 48px rgba(0,54,95,.25)',
          }}>
            <div style={{fontSize:11, fontWeight:600, letterSpacing:'.22em', textTransform:'uppercase', color:'var(--ulab-coral)', marginBottom:18}}>
              Bilaga — Produktblad
            </div>
            <h2 style={{fontFamily:'var(--font-serif)', fontWeight:500, fontSize:28, color:'var(--ulab-navy)', margin:'0 0 4px'}}>{item.name}</h2>
            <div style={{height:2, width:36, background:'var(--ulab-coral)', margin:'0 0 18px'}}/>
            <div style={{fontSize:11, color:'var(--fg-muted)', marginBottom:20}}>{item.sku} · {item.cat}</div>
            <div style={{display:'flex', gap:28, alignItems:'flex-start'}}>
              {preview && <img src={preview} alt="" style={{width:220, height:220, objectFit:'contain', background:'#fff', border:'1px solid #ece5d8', borderRadius:6, flexShrink:0}}/>}
              <div style={{flex:1}}>
                {(description || '').split(/\n+/).filter(Boolean).map((line, i) => {
                  const isBullet = /^\s*[•\-*]/.test(line);
                  return isBullet
                    ? <div key={i} style={{display:'flex', gap:8, fontSize:14, color:'var(--ulab-navy)', lineHeight:1.7, marginBottom:4}}><span style={{color:'var(--ulab-coral)'}}>•</span><span>{line.replace(/^\s*[•\-*]\s*/, '')}</span></div>
                    : <p key={i} style={{margin:'0 0 10px', fontSize:14, color:'var(--ulab-navy)', lineHeight:1.7}}>{line}</p>;
                })}
              </div>
            </div>
            <div style={{marginTop:24, textAlign:'right'}}>
              <button onClick={() => setShowPreview(false)} style={{
                background:'var(--ulab-navy)', color:'#fff', border:'none', padding:'8px 16px',
                borderRadius:4, fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'var(--font-sans)',
              }}>Stäng</button>
            </div>
          </div>
        </div>
      )}

      <div style={{display:'grid', gridTemplateColumns:'220px 1fr', gap:24}}>
        <div>
          <div style={{
            width:220, height:220, borderRadius:6, border:'1px dashed var(--border-strong)',
            display:'flex', alignItems:'center', justifyContent:'center', overflow:'hidden', background:'var(--ulab-cream)',
          }}>
            {preview ? (
              <img src={preview} alt="" style={{maxWidth:'100%', maxHeight:'100%', objectFit:'contain'}} />
            ) : (
              <span style={{fontSize:12, color:'var(--fg-muted)'}}>Ingen bild</span>
            )}
          </div>
          <input ref={fileInputRef} type="file" accept="image/png,image/jpeg,image/webp" onChange={onPickFile} style={{marginTop:10, fontSize:12}} />
          {preview && (
            <button onClick={removeImage} disabled={saving} style={{
              display:'block', marginTop:8, background:'transparent', border:'1px solid var(--border-strong)',
              borderRadius:4, padding:'5px 9px', fontSize:12, color:'var(--ulab-coral)', cursor:'pointer',
            }}>Ta bort bild</button>
          )}
        </div>

        <div>
          <label style={{fontSize:12, fontWeight:600, color:'var(--ulab-navy)', display:'block', marginBottom:6}}>
            Beskrivning / specifikation
          </label>
          <textarea
            value={description} onChange={e => { window.__produktbladOsparat = true; setDescription(e.target.value); }}
            placeholder="T.ex. korta säljande punkter, tekniska specs, eller ett stycke kopierat ur tillverkarens datablad. Detta är underlaget AI-skrivhjälpen och ett framtida produktblad kommer använda — skriv bara sådant som faktiskt stämmer."
            rows={10}
            style={{width:'100%', boxSizing:'border-box', fontSize:13, padding:10, border:'1px solid var(--border-strong)', borderRadius:4, fontFamily:'var(--font-sans)', resize:'vertical'}}
          />
          {specs.length > 0 && (
            <div style={{marginTop:16}}>
              <label style={{fontSize:12, fontWeight:600, color:'var(--ulab-navy)', display:'block', marginBottom:6}}>
                Specifikation ({specs.length} rader) — redigeras rad för rad
              </label>
              <div style={{border:'1px solid var(--border)', borderRadius:4, overflow:'hidden'}}>
                {specs.map((sp, i) => (
                  <div key={i} style={{display:'grid', gridTemplateColumns:'160px 1fr 28px', gap:6, padding:'5px 8px', borderBottom: i < specs.length-1 ? '1px solid var(--border)' : 'none', alignItems:'center'}}>
                    <input value={sp.label} onChange={e => setSpecs(specs.map((x, j) => j===i ? {...x, label:e.target.value} : x))}
                      style={{fontSize:12, padding:'4px 6px', border:'1px solid var(--border)', borderRadius:3, fontFamily:'var(--font-sans)', fontWeight:600, color:'var(--ulab-navy)'}}/>
                    <input value={sp.value} onChange={e => setSpecs(specs.map((x, j) => j===i ? {...x, value:e.target.value} : x))}
                      style={{fontSize:12, padding:'4px 6px', border:'1px solid var(--border)', borderRadius:3, fontFamily:'var(--font-sans)'}}/>
                    <button onClick={() => setSpecs(specs.filter((_, j) => j!==i))} title="Ta bort raden"
                      style={{background:'transparent', border:'none', cursor:'pointer', color:'var(--fg-muted)', fontSize:14}}>×</button>
                  </div>
                ))}
              </div>
              <button onClick={() => setSpecs([...specs, {label:'', value:''}])} style={{
                marginTop:6, background:'transparent', border:'1px solid var(--border-strong)', borderRadius:4,
                padding:'4px 10px', fontSize:11, color:'var(--ulab-navy)', cursor:'pointer', fontFamily:'var(--font-sans)',
              }}>+ Lägg till rad</button>
            </div>
          )}

          <div style={{marginTop:12, display:'flex', alignItems:'center', gap:10, flexWrap:'wrap'}}>
            <button onClick={save} disabled={saving} style={{
              background:'var(--ulab-navy)', color:'#fff', border:'none', padding:'9px 16px',
              borderRadius:4, fontSize:13, fontWeight:600, cursor:'pointer',
            }}>{saving ? 'Sparar…' : (status === 'utkast' ? 'Godkänn & spara' : 'Spara')}</button>
            <button onClick={() => setShowPreview(true)} disabled={!description && !preview} style={{
              background:'transparent', border:'1px solid var(--border-strong)', borderRadius:4,
              padding:'9px 14px', fontSize:13, color:'var(--ulab-navy)',
              cursor: (!description && !preview) ? 'not-allowed' : 'pointer', opacity: (!description && !preview) ? 0.5 : 1,
            }}>Förhandsgranska bladet</button>
            {savedMsg && <span style={{fontSize:12, color:'var(--ulab-teal, #2a8f7a)'}}>{savedMsg}</span>}
            {error && <span style={{fontSize:12, color:'var(--ulab-coral)'}}>{error}</span>}
          </div>
        </div>
      </div>
    </div>
  );
}
window.ProductAssetsPanel = ProductAssetsPanel;
