/* ============================================================
   PRODUCT EDITOR — pagina nuovo / duplica / modifica prodotto
   ============================================================ */

function fieldLbl(txt, req){
  return <span style={{ display:'block', fontSize:12.5, fontWeight:700, color:'var(--ink-2)', marginBottom:7 }}>{txt}{req && <span style={{ color:'var(--red)' }}> *</span>}</span>;
}
const edInput = { width:'100%', padding:'11px 13px', fontSize:14, borderRadius:'var(--r-md)', border:'1.5px solid var(--line)', background:'var(--surface-2)', color:'var(--ink)', outline:'none' };

function EditorCard({ title, sub, children, step }){
  return (
    <section style={{ background:'var(--surface)', border:'1px solid var(--line)', borderRadius:'var(--r-lg)', boxShadow:'var(--sh-1)', padding:'22px 24px' }}>
      <div style={{ display:'flex', alignItems:'flex-start', gap:12, marginBottom:18 }}>
        {step && <span style={{ width:26, height:26, borderRadius:8, flexShrink:0, background:'var(--red-tint)', color:'var(--red)', display:'flex', alignItems:'center', justifyContent:'center', fontFamily:'var(--font-display)', fontWeight:800, fontSize:14 }}>{step}</span>}
        <div>
          <h3 style={{ margin:0, fontFamily:'var(--font-display)', fontSize:17, fontWeight:800, letterSpacing:'-.01em' }}>{title}</h3>
          {sub && <div style={{ fontSize:12.5, color:'var(--ink-3)', marginTop:2 }}>{sub}</div>}
        </div>
      </div>
      {children}
    </section>
  );
}

function ContractCheck({ label, on, onClick }){
  return (
    <button onClick={onClick} style={{ display:'flex', alignItems:'center', gap:11, padding:'12px 14px', borderRadius:'var(--r-md)', textAlign:'left',
      border:'1.5px solid '+(on?'var(--red)':'var(--line)'), background:on?'var(--red-tint)':'var(--surface)', transition:'.13s' }}>
      <span style={{ width:20, height:20, borderRadius:5, flexShrink:0, border:'1.5px solid '+(on?'var(--red)':'var(--line)'), background:on?'var(--red)':'var(--surface)', display:'flex', alignItems:'center', justifyContent:'center' }}>
        {on && <Icon name="check" size={13} stroke={3} style={{ color:'#fff' }} />}
      </span>
      <span style={{ fontSize:13.5, fontWeight:700, color:on?'var(--red)':'var(--ink-2)' }}>{label}</span>
    </button>
  );
}

function ProductEditor({ mode, source, role, attributi, products, onCancel, onSave, onOpenExisting, toast, onStr }) {
  const vp = useViewport();
  // mode: 'new' | 'edit' | 'duplicate'
  const dup = mode==='duplicate';
  const isEdit = mode==='edit';
  const init = source || {};

  const [nome, setNome] = useState(init.modello!=null ? `${init.marca||''} ${init.modello||''}`.trim() : (init.nome||''));
  const [matricola, setMatricola] = useState(isEdit ? (init.matricola||init.id||'') : '');
  const [cat, setCat] = useState(init.cat || '');
  const [attrVals, setAttrVals] = useState(()=>({ ...(init.attr||{}) }));
  const [sub, setSub] = useState(init.sub || '');
  const [stato, setStato] = useState(dup ? 'DISPONIBILE' : (init.stato || 'DISPONIBILE'));
  const [liste, setListe] = useState(()=> new Set(init.liste || (init.dest?[init.dest]:[])));
  // prices
  const [pCons, setPCons] = useState(init.prezzoConsigliato!=null?String(init.prezzoConsigliato):'');
  const [pMin, setPMin]   = useState(init.prezzoMinimo!=null?String(init.prezzoMinimo):'');
  const [pGiorno, setPGiorno] = useState(init.prezzoGiorno!=null?String(init.prezzoGiorno):'');
  const [pMese, setPMese]   = useState(init.prezzoMese!=null?String(init.prezzoMese):'');
  const [showErr, setShowErr] = useState(false);
  const matRef = useRef(null);

  useEffect(()=>{ if((mode==='new'||dup) && matRef.current) setTimeout(()=>matRef.current.focus(), 350); }, []);

  // Matricola duplicata check — restituisce il prodotto esistente se la matricola è già usata
  const matTrim = matricola.trim();
  const existingProduct = matTrim ? (products||PRODOTTI).find(p => (p.matricola||p.id)===matTrim && p.id!==init.id) : null;
  const matDupe = !!existingProduct;

  // attributes available for the chosen machine type
  const catObj = CATEGORIE.find(c=>c.id===cat);
  const applicable = useMemo(()=>{
    if(!cat) return [];
    return (attributi||[]).filter(a => Array.isArray(a?.tipi) && a.tipi.includes(cat))
      .sort((a,b)=>(b.rilievo?1:0)-(a.rilievo?1:0));
  }, [cat, attributi]);
  const subAttr = applicable.find(a=>a.rilievo);
  const sedeAttrs = applicable.filter(a=>a.sede && !a.rilievo);
  const otherAttrs = applicable.filter(a=>!a.rilievo && !a.sede);

  const hasPrice = [pCons,pGiorno,pMese].some(v=>v.trim()!=='') || pMin.trim()!=='';
  const subRequired = !!subAttr;
  const errors = {
    nome: !nome.trim(),
    matricola: !matTrim || matDupe,
    cat: !cat,
    sub: subRequired && !sub,
    prezzo: !hasPrice,
  };
  const valid = !Object.values(errors).some(Boolean);

  const setAttr = (name,val) => setAttrVals(prev => { const n={...prev}; if(val===''||val==null) delete n[name]; else n[name]=val; return n; });

  // Per attributi "multiplo": il valore è una stringa separata da virgola.
  // toggleMultiAttr aggiunge/rimuove un termine dalla lista.
  const toggleMultiAttr = (name, term) => setAttrVals(prev => {
    const n = { ...prev };
    const current = (n[name] ? String(n[name]).split(',').map(s=>s.trim()).filter(Boolean) : []);
    const idx = current.indexOf(term);
    if (idx >= 0) current.splice(idx, 1); else current.push(term);
    if (current.length === 0) delete n[name]; else n[name] = current.join(', ');
    return n;
  });

  const handleOpenExisting = () => {
    if (existingProduct && onOpenExisting) {
      onOpenExisting(existingProduct);
    }
  };

  const submit = () => {
    setShowErr(true);
    if (matDupe) {
      toast('Questa matricola è già presente sul portale');
      return;
    }
    if(!valid){ toast('Completa i campi obbligatori evidenziati'); return; }
    const parsed = (s)=> s.trim()===''?null:parseFloat(s.replace(/[^\d.,]/g,'').replace(',','.'));
    const id = isEdit ? init.id : matTrim;
    const out = {
      ...init,
      id, matricola:matTrim,
      marca: nome.trim().split(' ')[0] || nome.trim(),
      modello: nome.trim().split(' ').slice(1).join(' ') || '',
      nome: nome.trim(),
      cat, sub: subRequired? sub : '',
      stato,
      liste: [...liste],
      dest: [...liste][0] || init.dest || 'Vendita',
      attr: { ...attrVals, ...(subRequired && sub ? { 'Sottocategoria': sub } : {}) },
      prezzoConsigliato: parsed(pCons),
      prezzoMinimo: parsed(pMin),
      prezzoGiorno: parsed(pGiorno),
      prezzoMese: parsed(pMese),
      nuovo: init.nuovo||false,
      posizione: init.posizione||'Da definire',
      gallery: init.gallery||0,
      sourceId: dup ? (source?.id || init.id) : undefined,   // serve a app.jsx per copiare le foto R2
    };
    // In modalità "edit" lo schema di id NON cambia (non posso cambiare id matricola per evitare di rompere relazioni)
    if (isEdit) out.id = init.id;
    onSave(out, mode);
  };

  const titleTxt = isEdit ? 'Modifica prodotto' : dup ? 'Duplica prodotto' : 'Nuovo prodotto';
  const photoId = isEdit ? ('prod-'+init.id) : ('new-'+(matTrim||'draft'));

  return (
    <div className={"scroll" + (vp.isMobile?' product-editor-mobile':'')} style={{ flex:1, minWidth:0, overflowY:'auto', overflowX:'hidden', display:'flex', flexDirection:'column' }}>
      {/* top bar */}
      <div style={{ padding: vp.isMobile?'10px 12px':'14px 30px', borderBottom:'1px solid var(--line)', background:'var(--surface)',
        display:'flex', alignItems:'center', gap: vp.isMobile?8:14, position:'sticky', top:0, zIndex:20, flexWrap: vp.isMobile?'wrap':'nowrap' }}>
        <button onClick={onCancel} style={{ display:'flex', alignItems:'center', gap:7, fontSize:13, fontWeight:700, color:'var(--ink-2)', padding:'7px 12px', borderRadius:'var(--r-md)', border:'1.5px solid var(--line)', flexShrink:0 }}>
          <Icon name="chevLeft" size={16} /> {vp.isMobile ? '' : 'Annulla'}
        </button>
        <div style={{ flex:1, minWidth:0, order: vp.isMobile?3:0, width: vp.isMobile?'100%':'auto' }}>
          <h1 style={{ margin:0, fontFamily:'var(--font-display)', fontSize: vp.isMobile?16:19, fontWeight:800, letterSpacing:'-.01em', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{titleTxt}</h1>
          <div style={{ fontSize:12, color:'var(--ink-3)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{dup?'Dati copiati':isEdit?(init.marca+' '+init.modello):'Compila i dati del mezzo'}</div>
        </div>
        {!vp.isMobile && <Btn variant="ghost" icon="clock" onClick={onStr}>Listino STR</Btn>}
        <Btn icon="check" onClick={submit} disabled={matDupe} size={vp.isMobile?'sm':'md'}>{vp.isMobile ? 'Salva' : (isEdit?'Salva modifiche':'Crea prodotto')}</Btn>
      </div>

      {dup && (
        <div style={{ margin: vp.isMobile?'12px 12px 0':'18px 30px 0', display:'flex', alignItems:'center', gap:11, padding: vp.isMobile?'10px 12px':'12px 16px', background:'#fdf0e0', borderRadius:'var(--r-md)', border:'1px solid #f3d9b0' }}>
          <Icon name="sparkle" size={18} style={{ color:'#9a5800', flexShrink:0 }} />
          <span style={{ fontSize:12.5, color:'#7a4600', fontWeight:600 }}>Stai duplicando <b>{init.marca} {init.modello}</b>. Inserisci una <b>nuova matricola</b>.</span>
        </div>
      )}

      {/* Banner matricola duplicata */}
      {matDupe && existingProduct && (
        <div style={{ margin: vp.isMobile?'12px 12px 0':'18px 30px 0', display:'flex', alignItems:'center', gap:12, padding: vp.isMobile?'12px 14px':'14px 18px',
          background:'var(--red-tint)', borderRadius:'var(--r-md)', border:'1.5px solid var(--red)', flexWrap: vp.isMobile?'wrap':'nowrap' }}>
          <span style={{ width:36, height:36, borderRadius:9, background:'var(--red)', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
            <Icon name="x" size={19} stroke={2.5} />
          </span>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontSize:13.5, fontWeight:800, color:'var(--red)', marginBottom:2 }}>Matricola già presente</div>
            <div style={{ fontSize:12.5, color:'var(--ink-2)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
              <b>{existingProduct.marca} {existingProduct.modello}</b> · {STATI[existingProduct.stato]?.label || existingProduct.stato}
            </div>
          </div>
          <Btn variant="primary" size={vp.isMobile?'sm':'md'} icon="arrowRight" onClick={handleOpenExisting}>Apri esistente</Btn>
        </div>
      )}

      <div style={{ padding: vp.isMobile?'14px 12px 40px':'22px 30px 50px', maxWidth:1120, width:'100%', margin:'0 auto',
        display:'grid', gridTemplateColumns: vp.isMobile?'1fr':'1.55fr 1fr', gap: vp.isMobile?16:22, alignItems:'start' }}>
        {/* LEFT column */}
        <div style={{ display:'flex', flexDirection:'column', gap:20 }}>
          {/* anagrafica */}
          <EditorCard step="1" title="Anagrafica" sub="Nome commerciale e matricola univoca del mezzo">
            <div style={{ display:'grid', gridTemplateColumns:'1.4fr 1fr', gap:16 }}>
              <label>
                {fieldLbl('Nome / Marca e modello', true)}
                <input value={nome} onChange={e=>setNome(e.target.value)} placeholder="es. Toyota 8FBM20T"
                  style={{ ...edInput, borderColor: showErr&&errors.nome?'var(--red)':'var(--line)' }} />
              </label>
              <label>
                {fieldLbl('Matricola (univoca)', true)}
                <input ref={matRef} value={matricola} onChange={e=>setMatricola(e.target.value)} placeholder="es. SN-48210"
                  style={{ ...edInput, borderColor: matDupe || (showErr&&errors.matricola)?'var(--red)':'var(--line)',
                    background: matDupe?'var(--red-tint)':(dup&&!matTrim?'#fdeef0':'var(--surface-2)') }} />
                {matDupe && (
                  <button onClick={handleOpenExisting} style={{ fontSize:11.5, color:'var(--red)', fontWeight:700, marginTop:6,
                    display:'flex', alignItems:'center', gap:5, textDecoration:'underline' }}>
                    <Icon name="arrowRight" size={12} /> Apri il prodotto esistente
                  </button>
                )}
                {dup && !matTrim && !matDupe && <span style={{ fontSize:11.5, color:'var(--red)', fontWeight:700, marginTop:5, display:'flex', alignItems:'center', gap:5 }}><Icon name="arrowUp" size={12} /> Da inserire</span>}
              </label>
            </div>
          </EditorCard>

          {/* categoria */}
          <EditorCard step="2" title="Categoria" sub="Seleziona il tipo di macchina: gli attributi disponibili si adattano">
            <div style={{ display:'grid', gridTemplateColumns:'repeat(2, 1fr)', gap:10, marginBottom: subAttr?18:0 }}>
              {CATEGORIE.map(c => {
                const on = cat===c.id;
                return (
                  <button key={c.id} onClick={()=>{ setCat(c.id); setSub(''); }} style={{ display:'flex', alignItems:'center', gap:11, padding:'13px 14px', borderRadius:'var(--r-md)', textAlign:'left',
                    border:'1.5px solid '+(on?'var(--red)':(showErr&&errors.cat?'var(--red-tint-2)':'var(--line)')), background:on?'var(--red-tint)':'var(--surface)', transition:'.13s' }}>
                    <span style={{ width:38, height:38, borderRadius:9, flexShrink:0, background:on?'var(--red)':'var(--line-2)', color:on?'#fff':'var(--ink-3)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                      <Icon name={c.icon} size={21} />
                    </span>
                    <span style={{ fontSize:14, fontWeight:700, color:on?'var(--red)':'var(--ink)' }}>{c.nome}</span>
                  </button>
                );
              })}
            </div>
            {subAttr && (
              <label>
                {fieldLbl(subAttr.nome+' (sottocategoria)', true)}
                <div style={{ position:'relative' }}>
                  <select value={sub} onChange={e=>setSub(e.target.value)} style={{ ...edInput, appearance:'none', paddingRight:34, borderColor: showErr&&errors.sub?'var(--red)':'var(--line)' }}>
                    <option value="">— Seleziona sottocategoria —</option>
                    {subAttr.termini.map(t=><option key={t} value={t}>{t}</option>)}
                  </select>
                  <Icon name="chevDown" size={16} style={{ position:'absolute', right:12, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
                </div>
              </label>
            )}
          </EditorCard>

          {/* attributi */}
          <EditorCard step="3" title="Attributi tecnici" sub={cat?`Attributi disponibili per ${catObj.nome}`:'Seleziona prima una categoria'}>
            {!cat ? (
              <div style={{ padding:'24px 0', textAlign:'center', color:'var(--ink-4)', fontSize:13.5, fontWeight:600 }}>
                <Icon name="tag" size={26} style={{ margin:'0 auto 8px', opacity:.5 }} /> Scegli una categoria per impostare gli attributi
              </div>
            ) : otherAttrs.length===0 ? (
              <div style={{ padding:'14px 0', color:'var(--ink-4)', fontSize:13 }}>Nessun attributo configurato per questa categoria.</div>
            ) : (
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:14 }}>
                {otherAttrs.map(a => {
                  const val = attrVals[a.nome] || '';
                  // Attributo a selezione multipla: checkbox multipli
                  if (a.multiplo && a.termini.length>0) {
                    const selected = val ? String(val).split(',').map(s=>s.trim()).filter(Boolean) : [];
                    return (
                      <div key={a.id} style={{ gridColumn:'1 / -1' }}>
                        {fieldLbl(a.nome + (selected.length? ` · ${selected.length} selezionati` : ''))}
                        <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
                          {a.termini.map(t => {
                            const on = selected.includes(t);
                            return (
                              <button key={t} type="button" onClick={()=>toggleMultiAttr(a.nome, t)}
                                style={{ display:'flex', alignItems:'center', gap:8, padding:'8px 12px', borderRadius:'var(--r-md)',
                                  border:'1.5px solid '+(on?'var(--red)':'var(--line)'), background:on?'var(--red-tint)':'var(--surface)', transition:'.13s' }}>
                                <span style={{ width:16, height:16, borderRadius:4, flexShrink:0, border:'1.5px solid '+(on?'var(--red)':'var(--line)'), background:on?'var(--red)':'var(--surface)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                                  {on && <Icon name="check" size={11} stroke={3} style={{ color:'#fff' }} />}
                                </span>
                                <span style={{ fontSize:13, fontWeight:600, color:on?'var(--red)':'var(--ink-2)' }}>{t}</span>
                              </button>
                            );
                          })}
                        </div>
                      </div>
                    );
                  }
                  // Attributo normale: dropdown o input libero
                  return (
                    <label key={a.id}>
                      {fieldLbl(a.nome)}
                      {a.termini.length>0 ? (
                        <div style={{ position:'relative' }}>
                          <select value={val} onChange={e=>setAttr(a.nome, e.target.value)} style={{ ...edInput, appearance:'none', paddingRight:34 }}>
                            <option value="">—</option>
                            {a.termini.map(t=><option key={t} value={t}>{t}</option>)}
                          </select>
                          <Icon name="chevDown" size={15} style={{ position:'absolute', right:11, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
                        </div>
                      ) : (
                        <input value={val} onChange={e=>setAttr(a.nome, e.target.value)} placeholder="valore libero" style={edInput} />
                      )}
                    </label>
                  );
                })}
              </div>
            )}
          </EditorCard>

          {/* ubicazione / sede — attributi speciali che non vanno nella scheda tecnica */}
          {cat && sedeAttrs.length>0 && (
            <EditorCard step="4" title="Ubicazione" sub="Dove si trova fisicamente il mezzo. Opzionale.">
              <div style={{ display:'grid', gridTemplateColumns:'1fr', gap:14 }}>
                {sedeAttrs.map(a => {
                  const val = attrVals[a.nome] || '';
                  return (
                    <label key={a.id}>
                      {fieldLbl(a.nome)}
                      {a.termini.length>0 ? (
                        <div style={{ position:'relative' }}>
                          <select value={val} onChange={e=>setAttr(a.nome, e.target.value)} style={{ ...edInput, appearance:'none', paddingRight:34 }}>
                            <option value="">—</option>
                            {a.termini.map(t=><option key={t} value={t}>{t}</option>)}
                          </select>
                          <Icon name="chevDown" size={15} style={{ position:'absolute', right:11, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
                        </div>
                      ) : (
                        <input value={val} onChange={e=>setAttr(a.nome, e.target.value)} placeholder="es. Piazzale A — Fila 3" style={edInput} />
                      )}
                    </label>
                  );
                })}
              </div>
            </EditorCard>
          )}

          {/* foto */}
          <EditorCard step={sedeAttrs.length>0?"5":"4"} title="Foto del mezzo" sub={isEdit ? `Trascina o seleziona, max ${(window.R2?.MAX_PHOTOS_PER_PRODUCT)||9}. La prima è la copertina del catalogo.` : dup ? 'Le foto del prodotto originale verranno copiate dopo il salvataggio' : 'Salva il prodotto, poi potrai aggiungere le foto'}>
            {isEdit ? (
              <ProductMediaManager productId={init.id} toast={toast} />
            ) : (
              <div style={{ padding:'28px 20px', textAlign:'center', background:'var(--surface-2)', border:'1.5px dashed var(--line)', borderRadius:'var(--r-md)' }}>
                <Icon name={dup?'copy':'boxes'} size={26} style={{ color:'var(--ink-4)', marginBottom:8 }} />
                <div style={{ fontSize:13, fontWeight:700, color:'var(--ink-3)' }}>
                  {dup ? 'Salva per copiare le foto' : 'Salva prima il prodotto'}
                </div>
                <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:4 }}>
                  {dup
                    ? `Le foto del prodotto "${init.marca} ${init.modello}" verranno copiate automaticamente al salvataggio.`
                    : 'Dopo aver compilato matricola e prezzi potrai caricare le foto'}
                </div>
              </div>
            )}
          </EditorCard>
        </div>

        {/* RIGHT column */}
        <div style={{ display:'flex', flexDirection:'column', gap:20, position:'sticky', top:74 }}>
          {/* prezzi */}
          <EditorCard title="Prezzi" sub="Almeno un prezzo è obbligatorio">
            <div style={{ marginBottom:16 }}>
              <div style={{ fontSize:11.5, fontWeight:800, color:'var(--ink-3)', textTransform:'uppercase', letterSpacing:'.04em', marginBottom:9 }}>Vendita</div>
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
                <label>
                  {fieldLbl('Consigliato (€)')}
                  <input value={pCons} onChange={e=>setPCons(e.target.value.replace(/[^\d.,]/g,''))} placeholder="es. 14900" style={edInput} />
                </label>
                <label>
                  {fieldLbl('Minimo (€)')}
                  <input value={pMin} onChange={e=>setPMin(e.target.value.replace(/[^\d.,]/g,''))} placeholder="es. 12400" style={edInput} />
                </label>
              </div>
            </div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
              <label>
                {fieldLbl('Noleggio breve (€/g)')}
                <input value={pGiorno} onChange={e=>setPGiorno(e.target.value.replace(/[^\d.,]/g,''))} placeholder="es. 48" style={edInput} />
              </label>
              <label>
                {fieldLbl('Noleggio breve (€/mese)')}
                <input value={pMese} onChange={e=>setPMese(e.target.value.replace(/[^\d.,]/g,''))} placeholder="es. 780" style={edInput} />
              </label>
            </div>
            {showErr && errors.prezzo && <div style={{ marginTop:11, fontSize:12, color:'var(--red)', fontWeight:600, display:'flex', alignItems:'center', gap:6 }}><Icon name="x" size={13} /> Inserisci almeno un prezzo</div>}
          </EditorCard>

          {/* contratti / liste */}
          <EditorCard title="Liste / contratti" sub="In quali liste del catalogo compare il mezzo">
            <div style={{ display:'flex', flexDirection:'column', gap:9 }}>
              {[['Vendita','Vendita'],['STR','Noleggio breve (STR)'],['LTR','Noleggio lungo (LTR)'],['Pronta consegna','Nuovo Pronta consegna']].map(([k,l])=>(
                <ContractCheck key={k} label={l} on={liste.has(k)} onClick={()=>setListe(prev=>{ const n=new Set(prev); n.has(k)?n.delete(k):n.add(k); return n; })} />
              ))}
            </div>
          </EditorCard>

          {/* stato */}
          <EditorCard title="Stato" sub="Predefinito: Disponibile">
            <div style={{ position:'relative' }}>
              <select value={stato} onChange={e=>setStato(e.target.value)} style={{ ...edInput, appearance:'none', paddingRight:34, fontWeight:700 }}>
                {Object.entries(STATI).map(([k,v])=><option key={k} value={k}>{v.label}</option>)}
              </select>
              <Icon name="chevDown" size={16} style={{ position:'absolute', right:12, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
            </div>
            {dup && <div style={{ marginTop:10, fontSize:12, color:'var(--ink-3)', display:'flex', alignItems:'center', gap:6 }}><Icon name="refresh" size={13} /> Reimpostato a "Disponibile" per il duplicato.</div>}
          </EditorCard>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   COMPONENTE: ProductImage
   Sostituisce <image-slot> in catalog/product/noleggi.
   Carica la copertina da product_media (is_main=true) e la mostra.
   Cache via window.PRODUCT_MEDIA_CACHE per evitare query ripetute.
   ============================================================ */
window.PRODUCT_MEDIA_CACHE = window.PRODUCT_MEDIA_CACHE || {};

function ProductImage({ productId, placeholder='Nessuna foto', style={}, alt='' }) {
  const [url, setUrl] = useState(window.PRODUCT_MEDIA_CACHE[productId] || null);
  const [loaded, setLoaded] = useState(!!window.PRODUCT_MEDIA_CACHE[productId]);
  const [errored, setErrored] = useState(false);
  const [isStd, setIsStd] = useState(true); // true se il formato è ~5:4 (1350x1080)

  useEffect(() => {
    let cancelled = false;
    if (!productId) return;
    if (window.PRODUCT_MEDIA_CACHE[productId] !== undefined) {
      setUrl(window.PRODUCT_MEDIA_CACHE[productId]);
      return;
    }
    (async () => {
      try {
        const list = await window.DataAPI.list('product_media', { eq:['product_id', productId] }) || [];
        const main = list.find(m => m.is_main) || list[0];
        const u = main?.url || null;
        if (!cancelled) {
          window.PRODUCT_MEDIA_CACHE[productId] = u;
          setUrl(u);
        }
      } catch(e) {
        if (!cancelled) {
          window.PRODUCT_MEDIA_CACHE[productId] = null;
          setUrl(null);
        }
      }
    })();
    return () => { cancelled = true; };
  }, [productId]);

  // Rileva se l'immagine è nel formato standard 5:4 (tolleranza) alla decodifica
  const onImgLoad = (e) => {
    setLoaded(true);
    const img = e.target;
    if (img.naturalWidth && img.naturalHeight) {
      const ratio = img.naturalWidth / img.naturalHeight;
      const target = 1350 / 1080; // 1.25
      setIsStd(Math.abs(ratio - target) < 0.06); // ~5:4 con tolleranza
    }
  };

  const wrapStyle = { position:'relative', overflow:'hidden', background:'var(--line-2)', ...style };
  if (!url || errored) {
    return (
      <div style={{ ...wrapStyle, display:'flex', alignItems:'center', justifyContent:'center', color:'var(--ink-4)', fontSize:11.5, fontWeight:600, textAlign:'center', padding:8 }}>
        {placeholder}
      </div>
    );
  }
  return (
    <div style={wrapStyle}>
      {/* Backdrop sfocato solo se il formato NON è standard 5:4 */}
      {!isStd && (
        <img src={url} alt="" aria-hidden="true"
          style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover',
            filter:'blur(18px) brightness(.8)', transform:'scale(1.15)', opacity: loaded?0.9:0 }} />
      )}
      <img src={url} alt={alt||placeholder} loading="lazy" decoding="async"
        style={{ position:'relative', width:'100%', height:'100%', display:'block', zIndex:1,
          objectFit: isStd ? 'cover' : 'contain', opacity: loaded?1:0, transition:'opacity .2s' }}
        onLoad={onImgLoad}
        onError={()=>setErrored(true)} />
    </div>
  );
}

/* ============================================================
   COMPONENTE: ProductMediaManager
   Mostra le foto del prodotto, permette upload/delete/riordino/set-as-main.
   ============================================================ */
function ProductMediaManager({ productId, toast }) {
  const [media, setMedia] = useState([]);
  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(0); // numero upload in corso
  const [draggingId, setDraggingId] = useState(null);
  const [overId, setOverId] = useState(null);
  const fileInputRef = useRef(null);
  const MAX = (window.R2?.MAX_PHOTOS_PER_PRODUCT) || 9;

  const refresh = async () => {
    try {
      const list = await window.DataAPI.list('product_media', { eq:['product_id', productId] }) || [];
      const sorted = list.slice().sort((a,b) => (a.ordine||0) - (b.ordine||0));
      setMedia(sorted);
      // Invalida cache copertina così ProductImage si aggiorna
      const main = sorted.find(m => m.is_main) || sorted[0];
      window.PRODUCT_MEDIA_CACHE[productId] = main?.url || null;
    } catch(e) {
      toast && toast('Errore caricamento foto');
    } finally { setLoading(false); }
  };

  useEffect(() => { if (productId) refresh(); else setLoading(false); }, [productId]);

  const handleFiles = async (files) => {
    const arr = Array.from(files || []);
    if (arr.length === 0) return;
    const slotsLeft = MAX - media.length;
    if (slotsLeft <= 0) { toast && toast(`Massimo ${MAX} foto per prodotto`); return; }
    const toUpload = arr.slice(0, slotsLeft);
    if (arr.length > slotsLeft) toast && toast(`Carico solo ${slotsLeft} foto (limite ${MAX})`);

    setUploading(u => u + toUpload.length);
    for (const f of toUpload) {
      try {
        await window.R2.uploadFile(productId, f);
      } catch(e) {
        console.error('upload failed:', e);
        toast && toast(`Errore: ${e?.message || 'caricamento fallito'}`);
      } finally {
        setUploading(u => u - 1);
      }
    }
    await refresh();
  };

  const handleDelete = async (m) => {
    if (!confirm('Eliminare questa foto? L\'azione è irreversibile.')) return;
    try {
      await window.R2.deleteMedia(m);
      toast && toast('Foto eliminata');
      await refresh();
    } catch(e) {
      toast && toast('Errore eliminazione');
    }
  };

  const handleSetMain = async (m) => {
    if (m.is_main) return;
    try {
      await window.R2.setAsMain(productId, m.id);
      toast && toast('Copertina aggiornata');
      await refresh();
    } catch(e) {
      toast && toast('Errore');
    }
  };

  // Drag-drop riordino
  const onDragStart = (id) => (e) => {
    setDraggingId(id);
    e.dataTransfer.effectAllowed = 'move';
  };
  const onDragOver = (id) => (e) => {
    e.preventDefault();
    if (id !== overId) setOverId(id);
  };
  const onDragEnd = () => { setDraggingId(null); setOverId(null); };
  const onDrop = (targetId) => async (e) => {
    e.preventDefault();
    if (!draggingId || draggingId === targetId) { onDragEnd(); return; }
    const idx = media.findIndex(m => m.id === draggingId);
    const tgt = media.findIndex(m => m.id === targetId);
    if (idx < 0 || tgt < 0) { onDragEnd(); return; }
    const newOrder = media.slice();
    const [moved] = newOrder.splice(idx, 1);
    newOrder.splice(tgt, 0, moved);
    setMedia(newOrder);
    onDragEnd();
    try {
      await window.R2.reorder(productId, newOrder.map(m => m.id));
      // Se la prima è diversa, auto-imposta come copertina
      if (newOrder[0] && !newOrder[0].is_main) {
        await window.R2.setAsMain(productId, newOrder[0].id);
      }
      await refresh();
    } catch(e) {
      toast && toast('Errore riordino');
      await refresh();
    }
  };

  // Drop nativo file su area
  const dropZoneOver = (e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; };
  const dropZoneDrop = (e) => { e.preventDefault(); handleFiles(e.dataTransfer.files); };

  if (loading) {
    return <div style={{ padding:'30px 20px', textAlign:'center', color:'var(--ink-3)', fontSize:13 }}>Caricamento foto…</div>;
  }

  return (
    <div onDragOver={dropZoneOver} onDrop={dropZoneDrop}>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:10 }}>
        {media.map((m, i) => {
          const isMain = m.is_main;
          const isDragging = draggingId === m.id;
          const isOver = overId === m.id && draggingId !== m.id;
          return (
            <div key={m.id}
              draggable
              onDragStart={onDragStart(m.id)}
              onDragOver={onDragOver(m.id)}
              onDrop={onDrop(m.id)}
              onDragEnd={onDragEnd}
              style={{
                position:'relative', aspectRatio:'4/3', borderRadius:10, overflow:'hidden',
                border:'2px solid '+(isMain?'var(--red)':isOver?'var(--ink-3)':'var(--line)'),
                background:'var(--line-2)', cursor:'grab',
                opacity: isDragging?0.4:1, transition:'opacity .15s, border-color .15s',
              }}>
              <img src={m.url} alt="" style={{ width:'100%', height:'100%', objectFit:'cover', display:'block' }} />
              {isMain && (
                <span style={{ position:'absolute', top:6, left:6, padding:'3px 8px', borderRadius:99,
                  background:'var(--red)', color:'#fff', fontSize:10, fontWeight:800, letterSpacing:'.04em', textTransform:'uppercase' }}>
                  Copertina
                </span>
              )}
              <div style={{ position:'absolute', top:6, right:6, display:'flex', gap:4 }}>
                {!isMain && (
                  <button onClick={()=>handleSetMain(m)} title="Imposta come copertina"
                    style={{ width:28, height:28, borderRadius:8, background:'rgba(255,255,255,.92)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--ink-2)', boxShadow:'0 1px 3px rgba(0,0,0,.2)' }}>
                    <Icon name="check" size={14} />
                  </button>
                )}
                <button onClick={()=>handleDelete(m)} title="Elimina foto"
                  style={{ width:28, height:28, borderRadius:8, background:'rgba(255,255,255,.92)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--red)', boxShadow:'0 1px 3px rgba(0,0,0,.2)' }}>
                  <Icon name="x" size={14} />
                </button>
              </div>
              <span style={{ position:'absolute', bottom:6, left:6, padding:'2px 7px', borderRadius:99, background:'rgba(0,0,0,.55)', color:'#fff', fontSize:10, fontWeight:700 }}>
                {i+1}
              </span>
            </div>
          );
        })}
        {/* Slot upload */}
        {media.length < MAX && (
          <label style={{ aspectRatio:'4/3', borderRadius:10, border:'2px dashed var(--line)', background:'var(--surface-2)',
            display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:6,
            color:'var(--ink-3)', cursor:'pointer', transition:'.15s' }}
            onMouseEnter={e=>{ e.currentTarget.style.borderColor='var(--red)'; e.currentTarget.style.color='var(--red)'; }}
            onMouseLeave={e=>{ e.currentTarget.style.borderColor='var(--line)'; e.currentTarget.style.color='var(--ink-3)'; }}>
            <Icon name="plus" size={20} />
            <span style={{ fontSize:11.5, fontWeight:700 }}>Aggiungi</span>
            <input ref={fileInputRef} type="file" multiple accept="image/jpeg,image/jpg,image/png,image/webp,image/heic,image/heif"
              onChange={(e)=>{ handleFiles(e.target.files); e.target.value=''; }}
              style={{ display:'none' }} />
          </label>
        )}
      </div>

      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:10, fontSize:12, color:'var(--ink-4)' }}>
        <span>{media.length} di {MAX} foto · trascina per riordinare</span>
        {uploading > 0 && (
          <span style={{ display:'inline-flex', alignItems:'center', gap:5, color:'var(--red)', fontWeight:700 }}>
            <span style={{ width:10, height:10, borderRadius:99, background:'var(--red)', animation:'pulse 1s infinite' }} />
            Caricamento {uploading}…
          </span>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { ProductEditor, ProductImage, ProductMediaManager });