/* Bookings, ticket pass, favorites */
const PAST_EV = (() => { const d = new Date(2026, 9, 3, 19, 0); return { id: 'past1', img: DP.A + 'events/poster-05.png', ts: d.getTime(), date: d, day: 'SAT', dateLbl: '3 Oct', time: '19:00', nm: 'Navratri Garba Night', ven: 'Arena Berlin', city: 'Berlin', cc: 'DE', country: 'Germany', cat: 'Festivals', price: 18, pmax: 0, st: '', tag: '', feat: false }; })();
const INITIAL_BOOKINGS = [
  { id: 'b5', ev: DP.EVENTS[DP.DEMO.bigSeated], n: 10, cats: 5, tier: 'General + VIP + Golden Circle + Family Pack + Student', tickets: ['General', 'General', 'General', 'VIP', 'VIP', 'Golden Circle', 'Family Pack', 'Family Pack', 'Student', 'Student'], total: 650, code: 'DP-9M4X-L2', pm: 'Apple Pay', status: 'confirmed' },
  { id: 'b1', ev: DP.EVENTS[DP.DEMO.seatRows], n: 2, tier: 'General', total: 20, code: 'DP-7K2M-Q9', pm: 'Apple Pay', status: 'confirmed' },
  { id: 'b2', ev: DP.EVENTS[DP.DEMO.apprFree], n: 1, tier: 'Founder Pass', total: 0, code: 'DP-R4T1-P2', pm: 'Free', status: 'pending' },
  { id: 'b3', ev: DP.EVENTS[DP.DEMO.waitSold], n: 2, tier: 'General', total: 0, code: 'DP-W9L2-K7', pm: '', status: 'waitlist', pos: 12 },
  { id: 'b4', ev: DP.EVENTS[DP.DEMO.apprPaid], n: 2, tier: 'General', total: 132, code: 'DP-D3C1-N8', pm: 'Card', status: 'declined' },
  { id: 'b0', ev: PAST_EV, n: 1, tier: 'General', total: 19, code: 'DP-3A8R-X1', pm: 'Card', used: true, status: 'confirmed' },
];
const ST = { confirmed: ['Confirmed', 'var(--red-soft)', 'var(--red)'], pending: ['Pending approval', 'var(--purple-soft)', 'var(--purple)'], waitlist: ['On waiting list', 'var(--warn-bg)', 'var(--warn-fg)'], declined: ['Not approved', 'var(--out-bg)', 'var(--out-fg)'] };

function QRPattern({ seed, size = 180 }) {
  const N = 25, r = rnd(seed); const cells = [];
  const finder = (x, y) => (x < 7 && y < 7) || (x > N - 8 && y < 7) || (x < 7 && y > N - 8);
  for (let y = 0; y < N; y++) for (let x = 0; x < N; x++) { if (finder(x, y)) continue; if (r() > .52) cells.push(<rect key={x + '-' + y} x={x} y={y} width="1" height="1" />); }
  const F = ({ x, y }) => <g><rect x={x} y={y} width="7" height="7" rx=".6" /><rect x={x + 1} y={y + 1} width="5" height="5" fill="#fff" /><rect x={x + 2} y={y + 2} width="3" height="3" /></g>;
  return <svg viewBox={`0 0 ${N} ${N}`} width={size} height={size} shapeRendering="crispEdges" fill="#1D0D31" aria-label="Ticket QR code">{cells}<F x={0} y={0} /><F x={N - 7} y={0} /><F x={0} y={N - 7} /></svg>;
}

function BookingRow({ b, onOpen }) {
  const past = b.ev.ts < DP.TODAY.getTime();
  const s = ST[b.status] || ST.confirmed; const ok = b.status === 'confirmed';
  return <button className="press" onClick={() => onOpen(b)} style={{ display: 'flex', gap: 12, alignItems: 'center', padding: 10, borderRadius: 16, border: '1px solid transparent', background: 'linear-gradient(var(--sur),var(--sur)) padding-box,var(--card-ring) border-box', boxShadow: 'var(--shadow)', textAlign: 'left', width: '100%', opacity: past ? .75 : 1 }}>
    <img src={b.ev.img} alt="" style={{ width: 64, height: 80, borderRadius: 10, objectFit: 'cover', filter: past ? 'grayscale(.6)' : 'none' }} />
    <div style={{ flex: 1, minWidth: 0 }}><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 9.5, color: 'var(--red)', fontWeight: 600, letterSpacing: '.05em' }}>{b.ev.day} · {b.ev.dateLbl.toUpperCase()} · {b.ev.time}</div><div style={{ fontWeight: 700, fontSize: 14.5, marginTop: 4, lineHeight: 1.2, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{b.ev.nm}</div><div style={{ fontSize: 12, color: 'var(--mut)', marginTop: 4, display: 'flex', alignItems: 'center', gap: 4 }}><Ico.pin size={11} />{b.ev.ven} · {b.ev.city}</div><div style={{ marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 6 }}><span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, maxWidth: '100%', minWidth: 0, fontSize: 11.5, fontWeight: 700, padding: '4px 9px', borderRadius: 7, background: past ? 'var(--out-bg)' : s[1], color: past ? 'var(--out-fg)' : s[2] }}>{ok ? <Ico.ticket size={12} /> : b.status === 'waitlist' ? <Ico.clock size={12} /> : b.status === 'pending' ? <Ico.clock size={12} /> : <Ico.x size={12} />}<span style={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{past ? 'Attended' : ok ? tierSummary(b) : s[0]}</span></span></div></div>
    {ok ? <Ico.qr size={22} style={{ color: past ? 'var(--mut2)' : 'var(--purple)', flex: 'none' }} /> : <Ico.chev size={18} style={{ color: 'var(--mut2)', flex: 'none' }} />}
  </button>;
}

function Bookings({ bookings, onOpen, onExplore }) {
  const { topInset, bottomInset } = useApp();
  const [tab, setTab] = useState('up');
  const T = DP.TODAY.getTime();
  const list = bookings.filter(b => tab === 'up' ? (b.ev.ts >= T && b.status !== 'declined') : (b.ev.ts < T || b.status === 'declined')).sort((a, b) => tab === 'up' ? a.ev.ts - b.ev.ts : b.ev.ts - a.ev.ts);
  return <div className="scr" style={{ paddingBottom: bottomInset + 90 }}>
    <div style={{ padding: `${topInset + 14}px 20px 0` }}><h1 style={{ color: 'var(--ink)', margin: 0, fontFamily: 'var(--dp-font-display)', fontWeight: 600, fontSize: 28, letterSpacing: '-.025em' }}>My <em style={{ fontStyle: 'italic', fontWeight: 500, color: 'var(--red)' }}>bookings</em></h1></div>
    <div style={{ margin: '16px 20px 18px', display: 'grid', gridTemplateColumns: '1fr 1fr', padding: 4, borderRadius: 9999, background: 'var(--chip)', position: 'relative' }}><span style={{ position: 'absolute', top: 4, bottom: 4, left: tab === 'up' ? 4 : 'calc(50%)', width: 'calc(50% - 4px)', borderRadius: 9999, background: 'var(--sur)', boxShadow: 'var(--shadow)', transition: 'left .3s cubic-bezier(.2,.8,.2,1)' }}></span>{[['up', 'Upcoming'], ['past', 'Past']].map(([k, l]) => <button key={k} onClick={() => setTab(k)} style={{ position: 'relative', height: 38, borderRadius: 9999, fontSize: 14, fontWeight: 700, color: tab === k ? 'var(--ink)' : 'var(--mut)', transition: 'color .2s' }}>{l}</button>)}</div>
    {list.length === 0 ? <div className="fade-in" style={{ padding: '40px 32px', textAlign: 'center' }}><img src={DP.A + 'illustrations/empty.svg'} alt="" style={{ width: 150, margin: '0 auto 16px' }} /><b style={{ fontSize: 17 }}>No {tab === 'up' ? 'upcoming' : 'past'} bookings</b><p style={{ color: 'var(--mut)', fontSize: 14, margin: '6px 0 20px' }}>Tickets you book will show up here, ready to scan.</p><Btn small onClick={onExplore} style={{ padding: '0 24px' }}>Explore Events</Btn></div> :
      <div className="fade-in" key={tab} style={{ display: 'grid', gap: 12, padding: '0 16px' }}>{list.map(b => <BookingRow key={b.id} b={b} onOpen={onOpen} />)}</div>}
  </div>;
}

function TicketPass({ z, booking, onBack, closing }) {
  const { topInset, bottomInset, device, toast } = useApp();
  const [i, setI] = useState(0); const ev = booking.ev; const [big, setBig] = useState(null);
  const past = ev.ts < DP.TODAY.getTime();
  /* tap the QR: full-screen white, large code, max brightness feel (a native app would also raise screen brightness) */
  const seedOf = (k) => (booking.code.length * 31 + k * 7) % 97 + 3;
  return <div className={'push' + (closing ? ' out' : '')} style={{ position: 'absolute', inset: 0, zIndex: z || 32, background: 'linear-gradient(200deg,#E54558 0%,#3B2E4D 70%,#1D0D31 100%)', color: '#fff', display: 'flex', flexDirection: 'column' }}>
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: `${topInset + 6}px 12px 4px`, flex: 'none' }}><IconBtn icon={Ico.back} onClick={onBack} bg="rgba(255,255,255,.15)" color="#fff" label="Back" /><div style={{ flex: 1, fontWeight: 700, fontSize: 16 }}>Ticket{booking.n > 1 ? ` ${i + 1} of ${booking.n}` : ''}</div><span style={{ width: 40 }}></span></div>
    <div className="hs" onScroll={e => setI(Math.round(e.target.scrollLeft / e.target.clientWidth))} style={{ flex: 1, minHeight: 0, alignItems: 'center' }}>
      {[...Array(booking.n)].map((_, k) => <div key={k} style={{ flex: '0 0 100%', padding: '8px 24px', display: 'flex', justifyContent: 'center' }}>
        <div className="rise" style={{ width: '100%', maxWidth: 340, borderRadius: 22, overflow: 'hidden', background: '#fff', color: '#1D0D31', boxShadow: '0 30px 60px -20px rgba(0,0,0,.5)', animationDelay: k * .05 + 's' }}>
          <div style={{ display: 'flex', gap: 14, alignItems: 'center', padding: '18px 18px 14px', borderBottom: '1px solid #EEE8F2' }}><img src={ev.img} alt="" style={{ width: 64, height: 80, borderRadius: 10, objectFit: 'cover', flex: 'none' }} /><div style={{ minWidth: 0 }}><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 9.5, letterSpacing: '.1em', color: '#E54558', fontWeight: 600 }}>{ev.day} · {ev.dateLbl.toUpperCase()} 2026 · {ev.time}</div><div style={{ fontFamily: 'var(--dp-font-display)', fontWeight: 600, fontSize: 17, lineHeight: 1.2, marginTop: 4, color: '#1D0D31', display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{ev.nm}</div></div></div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, padding: '14px 18px 4px', fontSize: 12.5 }}>
            {[['Venue', ev.ven + ', ' + ev.city], ['Ticket', (booking.tickets && booking.tickets[k]) || booking.tier], [booking.seats && booking.seats.length ? 'Seat' : booking.section ? 'Section' : 'Holder', booking.seats && booking.seats.length ? booking.seats[k] : booking.section ? DP.SECTIONS.find(s => s.k === booking.section).nm : (booking.guests && booking.guests[k] ? booking.guests[k].name : DP.USER.name)], ['Entry', 'Doors ' + doorsOf(ev.time)]].map(([l, v]) => <div key={l}><div style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '.1em', color: '#9A93A6', fontFamily: 'var(--dp-font-mono)', fontWeight: 600 }}>{l}</div><div style={{ fontWeight: 700, marginTop: 2, color: '#1D0D31' }}>{v}</div></div>)}
          </div>
          <div style={{ position: 'relative', height: 28, margin: '6px 0 0' }}><span style={{ position: 'absolute', left: -14, top: 0, width: 28, height: 28, borderRadius: '50%', background: '#3B2E4D' }}></span><span style={{ position: 'absolute', right: -14, top: 0, width: 28, height: 28, borderRadius: '50%', background: '#3B2E4D' }}></span><span style={{ position: 'absolute', left: 24, right: 24, top: 13, borderTop: '2px dashed #E6E0EC' }}></span></div>
          <div style={{ padding: '8px 18px 18px', textAlign: 'center', position: 'relative' }}>
            <button aria-label="Enlarge QR code" onClick={() => !past && setBig(k)} className="press" style={{ display: 'inline-block', padding: 10, borderRadius: 14, background: '#fff', boxShadow: 'inset 0 0 0 1px #EEE8F2', opacity: past ? .35 : 1, cursor: past ? 'default' : 'zoom-in' }}><QRPattern seed={seedOf(k)} size={168} /></button>{!past && <div style={{ fontSize: 11, color: '#9A93A6', marginTop: 6 }}>Tap to enlarge</div>}<button onClick={() => window.openRefund && openRefund(ev)} style={{ display: 'block', margin: '8px auto 0', fontSize: 12.5, fontWeight: 600, color: '#1D0D31', textDecoration: 'underline', textUnderlineOffset: 2 }}>Refund policy</button>
            {past && <div style={{ position: 'absolute', left: 0, right: 0, top: 80, fontFamily: 'var(--dp-font-mono)', fontSize: 13, fontWeight: 700, letterSpacing: '.2em', color: '#1D0D31', transform: 'rotate(-10deg)' }}>USED · {ev.dateLbl.toUpperCase()}</div>}
            <div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 13, fontWeight: 600, letterSpacing: '.14em', marginTop: 10, color: '#3B2E4D' }}>{booking.code}-{k + 1}</div>
            <div style={{ fontSize: 11.5, color: '#9A93A6', marginTop: 3 }}>Show this code at the entrance. Works offline.</div>
          </div>
        </div>
      </div>)}
    </div>
    {booking.n > 1 && <div style={{ display: 'flex', justifyContent: 'center', gap: 5, flex: 'none' }}>{[...Array(booking.n)].map((_, k) => <span key={k} style={{ width: k === i ? 18 : 6, height: 6, borderRadius: 3, background: k === i ? '#fff' : 'rgba(255,255,255,.35)', transition: 'all .3s' }}></span>)}</div>}
    <div style={{ padding: `14px 24px ${bottomInset + 16}px`, flex: 'none', display: 'grid', gap: 8 }}>{!past && <div style={{ display: 'flex', gap: 8 }}><Btn kind="ghost" small onClick={() => toast('Added to calendar')} style={{ flex: 1, height: 44, background: 'rgba(255,255,255,.14)', color: '#fff' }} icon={<Ico.cal size={16} />}>Calendar</Btn><Btn kind="ghost" small onClick={() => window.openShare && window.openShare(ev)} style={{ flex: 1, height: 44, background: 'rgba(255,255,255,.14)', color: '#fff' }} icon={<Ico.share size={16} />}>Share</Btn></div>}{!past && <Btn kind={device === 'android' ? 'white' : 'dark'} style={{ background: device === 'android' ? '#fff' : '#000' }} icon={device === 'android' ? <Ico.wallet size={18} /> : <Brand.apple />}>{`Add to ${device === 'android' ? 'Google' : 'Apple'} Wallet`}</Btn>}</div>
  {big !== null && <div role="dialog" aria-label="QR code" onClick={() => setBig(null)} className="fade-in" style={{ position: 'absolute', inset: 0, zIndex: 80, background: '#fff', color: '#1D0D31', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 18, padding: 24, cursor: 'zoom-out' }}><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 11, letterSpacing: '.16em', fontWeight: 700, color: '#9A93A6' }}>SHOW AT ENTRY</div><div style={{ padding: 16, borderRadius: 20, boxShadow: '0 0 0 1px #EEE8F2', animation: 'dpPop .35s cubic-bezier(.34,1.56,.64,1) both' }}><QRPattern seed={seedOf(big)} size={280} /></div><div style={{ fontFamily: 'var(--dp-font-display)', fontWeight: 700, fontSize: 17, textAlign: 'center', maxWidth: 300 }}>{ev.nm}</div><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 13, letterSpacing: '.12em', fontWeight: 600 }}>{booking.code}{booking.n > 1 ? ` · ${big + 1}/${booking.n}` : ''}</div><div style={{ fontSize: 12.5, color: '#6B6478', display: 'flex', alignItems: 'center', gap: 6 }}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" /></svg>Brightness up for scanning · Tap to close</div></div>}
  </div>;
}

function Favorites({ onOpen, onExplore }) {
  const { topInset, bottomInset, saved } = useApp();
  const list = DP.EVENTS.filter(e => saved.has(e.id)).sort((a, b) => a.ts - b.ts);
  return <div className="scr" style={{ paddingBottom: bottomInset + 90 }}>
    <div style={{ padding: `${topInset + 14}px 20px 18px`, display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}><h1 style={{ color: 'var(--ink)', margin: 0, fontFamily: 'var(--dp-font-display)', fontWeight: 600, fontSize: 28, letterSpacing: '-.025em' }}>Your <em style={{ fontStyle: 'italic', fontWeight: 500, color: 'var(--red)' }}>favorites</em></h1>{list.length > 0 && <span style={{ fontSize: 13, color: 'var(--mut)', fontWeight: 600 }}>{list.length} saved</span>}</div>
    {list.length === 0 ? <div className="fade-in" style={{ padding: '40px 32px', textAlign: 'center' }}><div style={{ width: 88, height: 88, margin: '0 auto 18px', borderRadius: '50%', background: 'var(--red-soft)', color: 'var(--red)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Ico.heart size={40} /></div><b style={{ fontSize: 17 }}>No favorites yet</b><p style={{ color: 'var(--mut)', fontSize: 14, margin: '6px 0 20px' }}>Tap the heart on any event to keep it here and get reminded before tickets run out.</p><Btn small onClick={onExplore} style={{ padding: '0 24px' }}>Explore Events</Btn></div> :
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, padding: '0 16px' }}>{list.map(e => <EventCard key={e.id} ev={e} onOpen={onOpen} />)}</div>}
  </div>;
}

Object.assign(window, { INITIAL_BOOKINGS, Bookings, TicketPass, Favorites, QRPattern });
