function BeforeAfter({img}){const [x,setX]=React.useState(50);const ref=React.useRef();const mv=e=>{const r=ref.current.getBoundingClientRect();setX(Math.max(0,Math.min(100,(e.clientX-r.left)/r.width*100)))};
return <div className="bsl" ref={ref} onPointerDown={e=>{e.currentTarget.setPointerCapture(e.pointerId);mv(e)}} onPointerMove={e=>e.buttons&&mv(e)} role="slider" tabIndex={0} aria-label={T('Confronto non illuminato e illuminato','Unlit versus lit comparison')} aria-valuenow={Math.round(x)} onKeyDown={e=>{if(e.key==='ArrowLeft')setX(v=>Math.max(0,v-4));if(e.key==='ArrowRight')setX(v=>Math.min(100,v+4))}}>
<div><img src={img} alt="" draggable="false"/></div><div style={{clipPath:`inset(0 ${100-x}% 0 0)`}}><img src={img} alt="" draggable="false" style={{filter:'brightness(.32) saturate(.35) contrast(1.05)'}}/></div>
<span className="lab" style={{left:16}}><Badge>{T('Spento · segnaposto','Unlit · placeholder')}</Badge></span><span className="lab" style={{right:16}}><Badge tone="accent">{T('Acceso · illustrativo','Lit · illustrative')}</Badge></span><div className="h" style={{left:x+'%'}}/></div>}
function LightSim(){const [env,setEnv]=React.useState('piazza');const e=envOf(env);const n=tt(e.name),pr=tt(e.prompt);
return <div style={{display:'flex',flexDirection:'column',gap:20}}><div className="chips" role="group" aria-label={T('Scenario','Scenario')}>{ENVS.map(v=><button key={v.id} className="chip" aria-pressed={env===v.id} onClick={()=>setEnv(v.id)}>{tt(v.name)}</button>)}</div>
{e.img?<BeforeAfter img={e.img}/>:<div className="g2"><Slot title={n+' · '+T('spento','unlit')} prompt={pr+T(' Crepuscolo, pali installati, illuminazione spenta.',' Dusk, poles installed, lighting off.')} style={{minHeight:320}}/><Slot title={n+' · '+T('acceso','lit')} prompt={pr+T(' Notte, illuminazione architettonica plausibile dai pali, non fotometrica.',' Night, plausible architectural lighting from the poles, non-photometric.')} style={{minHeight:320}}/></div>}
<div className="g2"><Ai>{T('Immagini illustrative generate con IA, non una simulazione fotometrica. Nessun valore di lux, uniformità, potenza, consumo o copertura è mostrato o implicito.','Illustrative AI imagery, not a photometric simulation. No lux, uniformity, power, consumption or coverage values are shown or implied.')}</Ai>
<div className="slot" style={{minHeight:0}}><div className="in"><Badge tone="tbc">{T('Predisposto · non ancora disponibile','Reserved · not available yet')}</Badge><h4>{T('Dati fotometrici','Photometric data')}</h4><p>{T('Spazio riservato alle schede LED e ai file fotometrici IES / LDT, da collegare quando disponibili.','Reserved for LED datasheets and IES / LDT photometric files, to be connected when supplied.')}</p></div></div></div></div>}
function ScaleView({m}){const is15=m===15;const mo=MODELS[m];return <div className="scale">{is15&&<div className="ruler" aria-hidden="true">{[0,1,2,3,4,5].map(i=><span key={i}><i style={{bottom:`${i/5.4*100}%`}}/><em style={{bottom:`${i/5.4*100}%`}}>{i} m</em></span>)}</div>}
<div style={{height:is15?`${1750/5400*100}%`:'30%',display:'flex',flexDirection:'column',alignItems:'center',gap:6}}><div style={{flex:1,minHeight:0}}><Person h="100%" dim={!is15}/></div><span className="t-mono dim" style={{fontSize:11,whiteSpace:'nowrap'}}>{is15?'≈ 1,75 m':T('Non in scala','Not to scale')}</span></div>
<img src={mo.img} alt={mo.name} style={{height:'100%',width:'auto',maxWidth:'50%',objectFit:'contain'}}/>
<div style={{position:'absolute',right:16,top:16,display:'flex',flexDirection:'column',gap:8,alignItems:'flex-end',maxWidth:260,textAlign:'right'}}><Badge tone={is15?'accent':'tbc'}>{is15?T('Scala di riferimento fino a 5.400 mm','Reference scale up to 5,400 mm'):T('Altezza da confermare','Pole height to be confirmed')}</Badge><span className="t-small" style={{fontSize:12}}>{is15?T('Da brochure p.5; può non corrispondere a ogni configurazione. Altezza della persona indicativa.','From brochure p.5; may not match every configuration. Person height indicative.'):T('Nessuna dimensione è indicata per questo modello nella documentazione.','No dimension is stated for this model in the documentation.')}</span></div></div>}
const mlist=c=>c.mods[c.model].map(i=>modName(c.model,i)).join(', ')||T('Nessuno','None');
function CompareDialog({a,b,onClose}){const col=(t,c)=><div className="card2" style={{flex:1,minWidth:240}}><span className="n">{t}</span><h3>{MODELS[c.model].name}</h3><div className="sumrow"><span>{T('Moduli','Modules')}</span><b>{mlist(c)}</b></div><div className="sumrow"><span>{T('Ambiente','Environment')}</span><b>{tt(envOf(c.env).name)}</b></div><div className="sumrow"><span>{T('Orario','Time')}</span><b>{c.time==='night'?T('Notte','Night'):T('Giorno','Day')}</b></div><div className="sumrow"><span>{T('Preferenza luce','Lighting preference')}</span><b>{lightName(c.light)}</b></div></div>;
return <div className="iv-overlay" onClick={onClose}><div className="iv-dialog" style={{width:'min(880px,100%)',maxHeight:'90vh',overflow:'auto'}} role="dialog" aria-modal="true" aria-label={T('Confronta configurazioni','Compare configurations')} onClick={e=>e.stopPropagation()}><h2>{T('Confronta configurazioni','Compare configurations')}</h2><div className="row" style={{alignItems:'stretch'}}>{col(T('A · Attuale','A · Current'),a)}{b?col(T('B · Salvata','B · Saved'),b):<StateBlock title={T('Nessuna configurazione B','Nothing saved as B')} message={T('Usa «Salva come B», modifica la configurazione e poi confronta.','Use “Save as B”, change the configuration, then compare.')}/>}</div><div className="iv-dialog__actions"><Button onClick={onClose}>{T('Chiudi','Close')}</Button></div></div></div>}
function summaryText(c){const m=MODELS[c.model];return `Vision Ecosystem — ${T('riepilogo configurazione (illustrativo)','configuration summary (illustrative)')}\n${T('Modello','Model')}: ${m.name}\n${T('Moduli','Modules')}: ${mlist(c)}\n${T('Ambiente','Environment')}: ${tt(envOf(c.env).name)} (${c.time==='night'?T('notte','night'):T('giorno','day')})\n${T('Preferenza luce','Lighting preference')}: ${lightName(c.light)}\n${T('Quantità indicativa','Indicative quantity')}: ${c.qty}\n${T('Prezzo: non mostrato · Dimensioni: da confermare','Price: not shown · Dimensions: to be confirmed')}`}
function Summary({c,h,onQuote,compact}){const m=MODELS[c.model];const [msg,setMsg]=React.useState('');const flash=t=>{setMsg(t);setTimeout(()=>setMsg(''),2600)};const R=(a,b,last)=><div className="sumrow" style={last?{border:0}:null}><span>{a}</span>{b}</div>;
return <>{R(T('Modello','Model'),<b>{m.name}</b>)}{R(`${T('Moduli','Modules')} (${c.mods[c.model].length})`,<b>{mlist(c)}</b>)}{R(T('Ambiente','Environment'),<b>{tt(envOf(c.env).name)}</b>)}{R(T('Orario','Time of day'),<b>{c.time==='night'?T('Notte','Night'):T('Giorno','Day')}</b>)}{R(T('Preferenza luce','Lighting preference'),<b>{lightName(c.light)}</b>)}{R(T('Quantità indicativa','Indicative quantity'),<b>{c.qty}</b>)}{R(T('Altezza','Height'),h?<b>{h.toFixed(2).replace('.',T(',','.'))} m<small style={{display:'block',color:'var(--fg-3)',fontWeight:400,fontSize:12}}>{T('Da modello 3D, da confermare','From 3D model, to be confirmed')}</small></b>:<TBC/>)}{R(T('Prezzo','Price'),<TBC/>,true)}
<Button onClick={onQuote} icon={<Icon name="arrow-right" size={18} color="currentColor"/>}>{T('Richiedi un preventivo','Request a Quote')}</Button>
{!compact&&<div className="row" style={{gap:8}}><Button size="sm" variant="secondary" onClick={()=>flash(T('Salvata su questo dispositivo (demo)','Saved on this device (demo)'))}>{T('Salva','Save')}</Button><Button size="sm" variant="secondary" onClick={()=>{try{navigator.clipboard.writeText(summaryText(c));flash(T('Riepilogo copiato','Summary copied'))}catch(e){flash(T('Copia non disponibile','Copy not available'))}}}>{T('Copia riepilogo','Copy summary')}</Button><span className="t-small" aria-live="polite">{msg}</span></div>}</>}
function QuoteFlow({c,onBack}){const [f,setF]=React.useState({name:'',org:'',email:'',phone:'',country:'',qty:String(c.qty),type:0,notes:'',ok:false});const [er,setEr]=React.useState({});const [ld,setLd]=React.useState(false);const [done,setDone]=React.useState(false);const u=k=>e=>setF({...f,[k]:e.target.type==='checkbox'?e.target.checked:e.target.value});
const types=[['Spazio pubblico','Public space'],['Comune / ente pubblico','Municipality / public authority'],['Area commerciale','Commercial area'],['Parcheggio','Car park'],['Proprietà privata','Private estate'],['Altro','Other']];
const submit=e=>{e.preventDefault();const x={};const R=T('Obbligatorio','Required');if(!f.name.trim())x.name=R;if(!f.org.trim())x.org=R;if(!/^\S+@\S+\.\S+$/.test(f.email))x.email=T('Inserisci un’email valida','Enter a valid email');if(!f.country.trim())x.country=R;if(!f.ok)x.ok=T('Il consenso è obbligatorio','Consent is required');setEr(x);if(Object.keys(x).length)return;setLd(true);setTimeout(()=>{setLd(false);setDone(true)},900)};
return <div className="wrap" style={{padding:'32px var(--gutter) 96px'}}><Breadcrumb items={[{label:'Home',href:'#/'},{label:T('Configuratore','Configurator'),href:'#/smart-pole-configurator/'},{label:T('Richiesta preventivo','Quote request')}]}/><h1 className="t-h1" style={{margin:'24px 0 32px'}}>{T('Richiedi un preventivo','Request a quote')}</h1>
<div className="split split--r" style={{alignItems:'start',gap:32}}><form className="card2" onSubmit={submit} noValidate style={{gap:20}}><h3>{T('I tuoi dati','Your details')}</h3><div className="g2"><Field label={T('Nome e cognome','Full name')} value={f.name} onChange={u('name')} error={er.name} autoComplete="name"/><Field label={T('Azienda o ente','Company or organisation')} value={f.org} onChange={u('org')} error={er.org}/></div><div className="g2"><Field label="Email" type="email" value={f.email} onChange={u('email')} error={er.email} autoComplete="email"/><Field label={T('Telefono','Phone')} hint={T('Facoltativo','Optional')} value={f.phone} onChange={u('phone')}/></div><div className="g2"><Field label={T('Paese e località di installazione','Country and installation site')} placeholder={T('es. Italia, Verona','e.g. Italy, Verona')} value={f.country} onChange={u('country')} error={er.country}/><Field label={T('Quantità prevista','Expected quantity')} type="number" min="1" value={f.qty} onChange={u('qty')}/></div><Field label={T('Tipologia di progetto','Project type')} as="select" options={types.map(tt)} value={tt(types[f.type])} onChange={e=>setF({...f,type:types.findIndex(t=>tt(t)===e.target.value)})}/><Field label={T('Note aggiuntive','Additional notes')} as="textarea" value={f.notes} onChange={u('notes')} hint={T('Facoltativo','Optional')}/>
<div><Checkbox checked={f.ok} onChange={u('ok')}>{T('Ho letto l’','I have read the ')}<L to={P.priv}>{T('informativa privacy','privacy policy')}</L>{T(' e acconsento a essere ricontattato per questa richiesta.',' and consent to being contacted about this request.')}</Checkbox>{er.ok&&<span className="iv-hint iv-hint--error" role="alert">{er.ok}</span>}</div>
<div className="row"><Button type="submit" loading={ld}>{ld?T('Preparazione','Preparing'):T('Richiedi un preventivo','Request a Quote')}</Button><Button type="button" variant="ghost" onClick={onBack}>{T('Torna al configuratore','Back to configurator')}</Button></div></form>
<aside className="card2" style={{position:'sticky',top:96}}><span className="t-eyebrow">{T('Riepilogo configurazione','Configuration summary')}</span><h3>{MODELS[c.model].name}</h3><img src={MODELS[c.model].img} alt="" style={{height:200,objectFit:'contain',background:'var(--bg-1)',borderRadius:8,padding:12}}/><div className="sumrow"><span>{T('Moduli','Modules')}</span><b>{mlist(c)}</b></div><div className="sumrow"><span>{T('Ambiente','Environment')}</span><b>{tt(envOf(c.env).name)} · {c.time==='night'?T('Notte','Night'):T('Giorno','Day')}</b></div><div className="sumrow"><span>{T('Preferenza luce','Lighting preference')}</span><b>{lightName(c.light)}</b></div><div className="sumrow" style={{border:0}}><span>{T('Quantità indicativa','Indicative quantity')}</span><b>{c.qty}</b></div><Note>{T('Nessun prezzo è mostrato. L’allegato del riepilogo alla richiesta è previsto nella versione definitiva.','Pricing is not shown. Attaching this summary to the request is planned for the live version.')}</Note></aside></div>
<Dialog open={done} title={T('Solo demo: nulla è stato inviato','Demo only: nothing was sent')} confirmLabel={T('Torna al configuratore','Back to configurator')} cancelLabel={T('Chiudi','Close')} onCancel={()=>setDone(false)} onConfirm={()=>{setDone(false);onBack()}}>{T('Questa bozza non ha un backend, quindi la richiesta non è stata inviata. Nella versione definitiva il riepilogo della configurazione verrebbe allegato alla richiesta.','This draft has no backend, so your request has not been submitted. In the live version the configuration summary would be attached to the request.')}</Dialog></div>}
function Configurator({embedded}){const [c,set]=useCfg();const [step,setStep]=React.useState(0);const [quote,setQuote]=React.useState(false);const [cmp,setCmp]=React.useState(false);const [ld,setLd]=React.useState(false);const [H,setH]=React.useState(null);const m=MODELS[c.model];const env=envOf(c.env);const sel=c.mods[c.model];
const tog=id=>set({mods:{...c.mods,[c.model]:sel.includes(id)?sel.filter(x=>x!==id):[...sel,id]}});
const pick=(k,v)=>{setLd(true);set({[k]:v});setTimeout(()=>setLd(false),320)};
if(quote)return <QuoteFlow c={c} onBack={()=>{setQuote(false);window.scrollTo(0,0)}}/>;
const v=c.view,night=c.time==='night',mn=sel.map(i=>modName(c.model,i)).join(', ')||T('nessun modulo','no modules');const vl=(VIEWS().find(x=>x[0]===v)||[])[1];
const stage=<div className="cfg-stage"><div className="cfg-bar"><Seg label={T('Vista','View')} opts={VIEWS()} value={v} onChange={x=>pick('view',x)}/><Seg label={T('Orario','Time')} opts={[['day',T('Giorno','Day')],['night',T('Notte','Night')]]} value={c.time} onChange={x=>pick('time',x)}/></div>
<div className="cfg-view" aria-busy={ld||undefined} style={{opacity:ld?.6:1,transition:'opacity .24s'}}>
<ThreeStage model={c.model} ids={sel} view={v} time={c.time} env={c.env} onHeight={setH}/>

<div className="cfg-tag"><Badge tone="accent">{m.short}</Badge>{v==='ctx'&&<Badge>{tt(env.name)}</Badge>}{v==='ctx'&&<Badge tone="cyan">{T('Scena 3D illustrativa','Illustrative 3D scene')}</Badge>}</div>
<div className="cfg-over">{v!=='ctx'&&H&&<div className="chips"><Badge tone="accent">{T('Altezza da modello 3D: ','Height from 3D model: ')}{H.toFixed(2).replace('.',T(',','.'))} m</Badge><Badge>{T('Trascina per ruotare','Drag to rotate')}</Badge></div>}<Ai>{T('Modello 3D semplificato, indicativo. Dimensioni e compatibilità vanno verificate sulla scheda tecnica del modello selezionato.','Simplified, indicative 3D model. Dimensions and compatibility must be verified on the datasheet of the selected model.')}</Ai></div></div>
<div className="row" style={{gap:8}}><Button size="sm" variant="secondary" icon={<Icon name="bookmark" size={16} color="currentColor"/>} onClick={()=>set({slotB:{model:c.model,mods:c.mods,env:c.env,time:c.time,light:c.light}})}>{c.slotB?T('Aggiorna B','Update B'):T('Salva come B','Save as B')}</Button><Button size="sm" variant="secondary" icon={<Icon name="columns" size={16} color="currentColor"/>} onClick={()=>setCmp(true)}>{T('Confronta A / B','Compare A / B')}</Button></div></div>;
const modelBar=<div className="cfg-model"><div className="cfg-model__h"><span className="t-eyebrow">{T('Modello','Model')}</span><Seg label={T('Modello','Model')} opts={[['15','Smart Pole 15'],['17','BS-Smart Pole 17']]} value={String(c.model)} onChange={x=>pick('model',+x)}/></div><div className="cfg-model__d"><b>{m.name}</b><span>{tt(m.desc)}</span></div><div className="chips" aria-label={T('Preset illustrativi','Illustrative presets')}>{PRESETS[c.model].map(([n,ids])=><button key={n[1]} className="chip" onClick={()=>set({mods:{...c.mods,[c.model]:ids}})}>{tt(n)}</button>)}</div></div>;
const side=<aside className="cfg-side" aria-label={T('Moduli','Modules')}><div className="cfg-side__h"><span>{T('Moduli','Modules')}</span><span>{sel.length}{T(' selezionati',' selected')}</span></div><div className="cfg-side__b"><div className="cfg-mods">{m.mods.map(x=><ModuleCard key={x.id} icon={x.icon} name={tt(x.n)} description={tt(x.d)} selected={sel.includes(x.id)} onToggle={()=>tog(x.id)}/>)}</div><Note>{T(`Sono elencati solo i moduli presenti nei modelli 3D di ${m.short}. La compatibilità tra le combinazioni è da verificare.`,`Only modules present in the ${m.short} 3D models are listed. Combination compatibility is to be verified.`)}</Note>
<div className="cfg-opts"><span className="t-eyebrow">{T('Opzioni','Options')}</span><Field label={T('Ambiente','Environment')} as="select" options={ENVS.map(e=>tt(e.name))} value={tt(env.name)} onChange={e=>{set({env:ENVS.find(x=>tt(x.name)===e.target.value).id,view:'ctx'})}}/><Field label={T('Preferenza di illuminazione','Lighting preference')} as="select" options={LIGHTS.map(l=>tt(l[1]))} value={lightName(c.light)} onChange={e=>set({light:LIGHTS.find(l=>tt(l[1])===e.target.value)[0]})} hint={T('Solo una preferenza. Nessun valore tecnico è implicito.','A preference only. No technical values are implied.')}/><Field label={T('Quantità indicativa','Indicative quantity')} type="number" min="1" value={c.qty} onChange={e=>set({qty:Math.max(1,+e.target.value||1)})}/></div></div></aside>;
const sum=<div className="cfg-sum"><ConfiguratorPanel title={T('Riepilogo','Summary')}><Summary h={H} c={c} onQuote={()=>{if(embedded){go(P.cfg);return}setQuote(true);window.scrollTo(0,0)}}/></ConfiguratorPanel></div>;
return <div className={embedded?'':'wrap'} style={embedded?{}:{padding:'32px var(--gutter) 40px'}}>{!embedded&&<><Breadcrumb items={[{label:'Home',href:'#/'},{label:T('Configuratore','Configurator')}]}/><div style={{margin:'24px 0',display:'flex',justifyContent:'space-between',gap:24,flexWrap:'wrap',alignItems:'end'}}><h1 className="t-h1" style={{margin:0}}>{T('Configura il tuo Smart Pole','Configure your Smart Pole')}</h1><span className="t-small" style={{maxWidth:420}}>{T('Interfaccia dimostrativa. Le scelte aggiornano il modello 3D e il riepilogo.','Demonstration interface. Selections update the 3D model and the summary.')}</span></div></>}
<div className="cfg-wrap">{modelBar}<div className="cfg-main">{stage}{side}</div>{sum}</div>
{cmp&&<CompareDialog a={c} b={c.slotB} onClose={()=>setCmp(false)}/>}</div>}
function ConfiguratorPage(){return <><Configurator/><Sec eyebrow={T('Anteprima illuminazione','Lighting preview')} title={T('Giorno, notte, acceso e spento.','Day, night, lit and unlit.')} lead={T('Una sezione dimostrativa per confrontare come può apparire uno spazio prima e dopo l’illuminazione. Solo illustrativa.','A demonstrative section to compare how a space may read before and after lighting. Illustrative only.')}><LightSim/></Sec></>}
Object.assign(window,{Configurator,ConfiguratorPage,LightSim,BeforeAfter,Summary});
