/* Source-derived physical ticket artwork; rows are resolved by the scoped API. */
(function () {
  const {useState,useEffect}=React;
  const MM=96/25.4,PREVIEW=.5,MARGIN=6,GUTTER=4;
  const FORMATS={shelf:{id:"shelf",label:"Shelf ticket",w:70,h:50,description:"Slots into the standard rail. One per facing."},barker:{id:"barker",label:"Bay barker",w:95,h:70,description:"Projects from the shelf edge for offers seen from the aisle."},a5:{id:"a5",label:"A5 poster",w:148,h:210,description:"One-up on A4, with a trim edge for an end-of-bay or window."}};
  const THEMES={red:{label:"Classic red",flag:"#d81f2a",fg:"#fff",ink:"#b3141d",tint:"#fdecec"},amber:{label:"Clearance",flag:"#f4a300",fg:"#241a00",ink:"#a06a00",tint:"#fff6e3"},teal:{label:"Brand teal",flag:"#0d7b6c",fg:"#fff",ink:"#0a6156",tint:"#e6f4f1"},magenta:{label:"Beauty pink",flag:"#c2185b",fg:"#fff",ink:"#a01449",tint:"#fdeaf1"},green:{label:"Wellness",flag:"#2e7d32",fg:"#fff",ink:"#256428",tint:"#eaf4ea"},violet:{label:"Premium",flag:"#5b3fa8",fg:"#fff",ink:"#4a3389",tint:"#efeafa"},navy:{label:"Navy",flag:"#0f2436",fg:"#fff",ink:"#0f2436",tint:"#e9eef3"}};
  const money=c=>c==null?"—":"$"+(c/100).toFixed(2);
  const date=d=>d?String(d).slice(0,10).split('-').reverse().join('/'):"—";
  const layout=f=>{const cols=Math.floor((210-2*MARGIN+GUTTER)/(f.w+GUTTER)),rows=Math.floor((297-2*MARGIN+GUTTER)/(f.h+GUTTER));return {cols,rows,per:cols*rows,gridW:cols*f.w+(cols-1)*GUTTER,gridH:rows*f.h+(rows-1)*GUTTER};};
  function Ticket({row,format,promotion,theme}) {
    const f=FORMATS[format],t=THEMES[theme||row.theme]||THEMES.red,scale=format==='shelf'?1:format==='barker'?1.42:2.1;
    const price=row.kind==='price'&&row.effectiveCents!=null;
    const member=promotion?.mechanic==='member',clearance=promotion?.origin==='clearance';
    const parts=price?(row.effectiveCents/100).toFixed(2).split('.'):[];
    const saving=price&&row.beforeCents!=null?row.beforeCents-row.effectiveCents:0;
    return <div className={"tk tk--"+format+(!price?" tk--offer":"")} style={{width:f.w+"mm",height:f.h+"mm","--tk-flag":t.flag,"--tk-fg":t.fg,"--tk-ink":t.ink,"--tk-tint":t.tint}}>
      <div className="tk-top"><span className="tk-flag">{row.draft||row.preview?"DRAFT PREVIEW":clearance?"CLEARANCE":member?"MEMBER PRICE":price?"SPECIAL":"OFFER"}</span>{saving>0&&<span className="tk-save">SAVE {money(saving)}</span>}</div>
      <div className="tk-name" style={{fontSize:8.5*scale}}>{row.name}</div>
      {price?<div className="tk-price"><span className="tk-cur" style={{fontSize:13*scale}}>$</span><span className="tk-d" style={{fontSize:38*scale}}>{parts[0]}</span><span className="tk-c" style={{fontSize:15*scale}}>{parts[1]}</span></div>:<div className="tk-offer" style={{fontSize:14.5*scale}}><span>{row.offerText||"See offer conditions"}</span></div>}
      <div className="tk-bot"><span className="tk-was">{row.beforeCents!=null?(price?"Shelf price ":"Each ")+money(row.beforeCents):""}</span><span className="tk-dates">{date(row.startsOn)} – {date(row.endsOn)}</span></div>
      <div className="tk-fine">{member?"Loyalty card must be presented. ":""}{clearance?"Short-dated stock. ":""}While stocks last.<span className="tk-sku">{row.sku}</span></div>
    </div>;
  }
  function PromoTickets() {
    const {screenState={},setScreen,activeStoreId}=window.useOffice();
    const [format,setFormat]=useState('shelf'),[pick,setPick]=useState(screenState.promotionTicketId||'all'),[siteId,setSiteId]=useState(activeStoreId||''),[asOf,setAsOf]=useState('');
    const [data,setData]=useState(null),[busy,setBusy]=useState(true),[error,setError]=useState(null),[colours,setColours]=useState({}),[printRoot,setPrintRoot]=useState(null);
    useEffect(()=>{const root=document.createElement('div');root.className='promo-ticket-print-root';document.body.appendChild(root);document.body.classList.add('office-promo-tickets-active');setPrintRoot(root);return()=>{document.body.classList.remove('office-promo-tickets-active');root.remove();};},[]);
    useEffect(()=>{setSiteId(activeStoreId||'');},[activeStoreId]);
    useEffect(()=>{let alive=true;setBusy(true);setError(null);setData(null);
      window.OfficeAPI.promotionsWorkspace({...siteId?{siteId}:{},...asOf?{asOf}:{}}).then(async result=>{if(result.promotions?.some(p=>p.id===pick&&p.state==='draft')){result=await window.OfficeAPI.promotionsWorkspace({siteId:siteId||result.siteId||undefined,asOf:asOf||undefined,draftId:pick});}if(alive)setData(result);}).catch(e=>{if(alive)setError(e.message||"Couldn't load printable tickets.");}).finally(()=>{if(alive)setBusy(false);});
      return()=>{alive=false;};
    },[siteId,asOf,pick]);
    const all=data?.tickets?.rows||[],promotions=data?.promotions||[],f=FORMATS[format],L=layout(f);
    const rows=all.filter(row=>pick==='all'||row.promotionId===pick);
    const held=(data?.tickets?.held||[]).filter(row=>pick==='all'||row.promotionId===pick);
    const options=promotions.filter(p=>p.channels?.includes('ticket')||all.some(row=>row.promotionId===p.id));
    const draftPreview=!!data?.tickets?.draftPreview||rows.some(row=>row.draft||row.preview);
    const sheets=Math.ceil(rows.length/L.per),ready=!busy&&!!data?.siteId&&rows.length>0;
    const promotionFor=row=>promotions.find(p=>p.id===row.promotionId);
    const tickets=items=>items.map(row=><Ticket key={row.id} row={row} format={format} promotion={promotionFor(row)} theme={colours[row.promotionId]}/>);
    const print=()=>{if(!ready)return;try{window.print();}catch(e){setError(e.message||"Couldn't open the print dialog.");}};
    return <div className="off-screen promo-ticket-screen">
      <header className="off-screen-header"><div className="off-screen-header-meta"><button className="btn btn--ghost btn--sm" style={{alignSelf:'flex-start',paddingLeft:0}} onClick={()=>setScreen('promotions')}><window.OIcon name="chevron-left"/> Promotions</button><h2 className="off-screen-title">Shelf tickets</h2><div className="off-muted" style={{fontSize:13,marginTop:4}}>Resolved from published promotion prices and register rules for the chosen date. Basket offers remain offers, not invented unit prices.</div></div>
        <div className="off-screen-actions"><button className="btn btn--ghost btn--sm" disabled={!ready} onClick={print}><window.OIcon name="download"/> Save as PDF</button><button className="btn btn--primary btn--sm" disabled={!ready} onClick={print}><window.OIcon name="printer"/> {draftPreview?'Print draft preview · ': 'Print '}{sheets} sheet{sheets===1?'':'s'}</button></div>
      </header>
      <div className="off-screen-body off-promotions-body">
        {busy&&<div className="pc-note" role="status">Loading resolved tickets…</div>}{error&&<div className="pc-warn" role="alert">{error}</div>}
        {data&&<div className="tk-layout"><aside className="tk-side">
          <section className="off-table pg-card"><div className="pg-card-h">Store and date</div><div className="pg-card-s">Tickets print for one authorised store and effective date.</div><div className="pb-levels">{(data.sites||[]).map(site=><button className={'pb-chip'+(data.siteId===site.id?' is-on':'')} key={site.id} onClick={()=>{if(site.id!==siteId){setBusy(true);setSiteId(site.id);}setPick('all');}}>{site.name}</button>)}</div><label className="promo-ticket-date">Effective date<input className="input" type="date" aria-label="Ticket effective date" value={asOf||data.effectiveDate||''} onChange={e=>{setBusy(true);setAsOf(e.target.value);}}/></label></section>
          <section className="off-table pg-card"><div className="pg-card-h">Size</div><div className="tk-formats">{Object.values(FORMATS).map(value=><button key={value.id} className={'tk-fmt'+(format===value.id?' is-on':'')} aria-pressed={format===value.id} onClick={()=>setFormat(value.id)}><div className="tk-fmt-t">{value.label}</div><div className="tk-fmt-s">{value.w} × {value.h} mm · {layout(value).per} per A4 sheet</div><div className="tk-fmt-d">{value.description}</div></button>)}</div></section>
          <section className="off-table pg-card"><div className="pg-card-h">Which promotions</div><div className="tk-picks"><button className={'tk-pick'+(pick==='all'?' is-on':'')} onClick={()=>setPick('all')}><span>Everything with tickets turned on</span><strong>{all.length}</strong></button>{options.map(p=><button className={'tk-pick'+(pick===p.id?' is-on':'')} key={p.id} onClick={()=>setPick(p.id)}><span>{p.name}</span><strong>{all.filter(row=>row.promotionId===p.id).length}</strong></button>)}</div></section>
          {held.length>0&&<section className="off-table pg-card"><div className="pg-card-h">Not printed</div><div className="pg-card-s">Held or superseded lines do not produce a misleading ticket.</div><div className="tk-sup">{held.map((row,i)=><div className="tk-supr" key={row.productId+':'+i}><div><div className="pb-ov-n">{row.name}</div><div className="pb-ov-s">{row.reason}</div></div></div>)}</div></section>}
          <section className="off-table pg-card"><div className="pg-card-h">Colour</div><div className="pg-card-s">{pick==='all'?'Select a promotion to change its colour for this print run. Saved promotion colours are used otherwise.':'Changes apply to this print run only. Saved promotion settings remain unchanged.'}</div>{pick!=='all'&&<div className="tk-swatches">{Object.entries(THEMES).map(([key,t])=><button key={key} className={'tk-sw'+((colours[pick]||all.find(row=>row.promotionId===pick)?.theme||'red')===key?' is-on':'')} onClick={()=>setColours(previous=>({...previous,[pick]:key}))}><span style={{background:t.flag}}/><em>{t.label}</em></button>)}</div>}</section>
          <section className="off-table pg-card"><div className="pg-card-h">What prints</div><div className="tk-legend">{[['SPECIAL','A resolved price with the current shelf price for comparison.','std'],['OFFER','A basket rule with conditions, rather than a unit price.','offer'],['MEMBER PRICE','Requires a loyalty card.','mem'],['CLEARANCE','Short-dated stock, kept distinct from marketing offers.','clr']].map(([label,description,tone])=><div className="tk-lg" key={label}><span className={'tk-lg-b tk-lg--'+tone}>{label}</span><span className="tk-lg-d">{description}</span></div>)}</div><div className="xp-note">Use the browser print dialog at 100% scale, A4 paper and no browser headers or footers. Choose Save as PDF there to create a PDF. Ticket borders provide trim guides.</div></section>
        </aside><main className="tk-main"><div className="tk-sheetbar"><span>{rows.length} tickets · {sheets} A4 sheets · {L.cols} × {L.rows} per page · {data.siteName||'Choose a store'}</span><span style={{marginLeft:'auto',fontSize:11.5,color:'var(--text-subtle)'}}>Shown at half size</span></div>
          {draftPreview&&<div className="pc-warn"><strong>DRAFT PREVIEW — not published.</strong> These tickets show the draft calculation and must not be displayed as a live offer.</div>}{(data.tickets?.warnings||[]).map((warning,i)=><div className="pc-warn" key={i}>{warning}</div>)}
          {!data.siteId&&<div className="pc-note">Select a store before printing tickets.</div>}
          {Array.from({length:sheets},(_,i)=><div className="tk-sheet" key={i} style={{width:210*MM*PREVIEW,height:297*MM*PREVIEW,padding:MARGIN*MM*PREVIEW}}><div className="tk-sheet-l">Sheet {i+1} of {sheets} · A4</div><div className="tk-clip" style={{width:L.gridW*MM*PREVIEW,height:L.gridH*MM*PREVIEW}}><div className="tk-sheet-in" style={{width:L.gridW*MM,gridTemplateColumns:'repeat('+L.cols+', max-content)',gap:GUTTER+'mm'}}>{tickets(rows.slice(i*L.per,(i+1)*L.per))}</div></div></div>)}
          {!rows.length&&<div className="xp-empty">No printable tickets for this promotion, store and effective date.</div>}
        </main></div>}
      </div>
      {printRoot&&window.ReactDOM.createPortal(ready?Array.from({length:sheets},(_,i)=><div className="promo-print-page" key={i} style={{gridTemplateColumns:'repeat('+L.cols+', '+f.w+'mm)'}}>{tickets(rows.slice(i*L.per,(i+1)*L.per))}</div>):null,printRoot)}
    </div>;
  }
  window.OFFICE_SCREENS=Object.assign(window.OFFICE_SCREENS||{},{promoTickets:PromoTickets});
})();
