/* Home, city picker, search */
const CI = (d) => <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">{d}</svg>;
const CAT_SVG = {
  'For You': CI(<><path d="M12 3.5c.4 3.4 2 5 5.5 5.5-3.5.5-5.1 2.1-5.5 5.5-.4-3.4-2-5-5.5-5.5 3.5-.5 5.1-2.1 5.5-5.5Z"/><path d="M18.5 15c.2 1.4.8 2 2 2.2-1.2.2-1.8.8-2 2.3-.2-1.5-.8-2.1-2-2.3 1.2-.2 1.8-.8 2-2.2Z"/></>),
  Concerts: CI(<><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M8.5 21h7"/></>),
  Dance: CI(<><circle cx="13" cy="4.5" r="1.8"/><path d="m9 21 2.5-5.5L9 12l3-3.5 3 2.5 3-1"/><path d="m12 8.5-5 1.5M13.5 15.5 16 21"/></>),
  Parties: CI(<><path d="m4 20 4.5-12 7.5 7.5L4 20Z"/><path d="M14 4.5c0 1.5 1 2 1 3.5M19.5 10c-1.5 0-2 1-3.5 1M17 3v1M21 7h-1M20 3.5l-.7.7"/></>),
  Social: CI(<><circle cx="9" cy="8" r="3"/><path d="M3.5 19a5.5 5.5 0 0 1 11 0"/><path d="M15.5 5.2a3 3 0 0 1 0 5.6M17.5 14a5.5 5.5 0 0 1 3 5"/></>),
  Festivals: CI(<><path d="M3 5c6 3 12 3 18 0"/><path d="m6 6.6 1.5 4 2-3.4M12 7.7v4l2.2-3.6M17.5 6.5l-1 3.8"/><path d="M5 15v6M5 15l4 1.5L5 18M19 14v7"/></>),
  Comedy: CI(<><circle cx="12" cy="12" r="9"/><path d="M8 9.5h.01M16 9.5h.01M7.5 13.5h9a4.5 4.5 0 0 1-9 0Z"/></>)
};
const CAT_ICON = { Dance: 'dance', Parties: 'parties', Social: 'social', 'Club nights': 'parties', Meetups: 'social', Festivals: 'festivals', Comedy: 'comedy' };
CAT_SVG['Club nights'] = CAT_SVG.Parties; CAT_SVG.Meetups = CAT_SVG.Social;
const MicIcon = () => <svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10a7 7 0 0 0 14 0M12 17v5M8 22h8"/></svg>;

function useFiltered(city, cat, when, q) {
  return useMemo(() => {
    const T = DP.TODAY.getTime(), D = 864e5;
    const fri = new Date(2026, 9, 16).getTime(), sunEnd = new Date(2026, 9, 19).getTime(), monthEnd = new Date(2026, 10, 1).getTime();
    const cc = DP.CITIES[city].cc;
    const ql = (q || '').trim().toLowerCase();
    const ok = e => (cat === 'For You' || e.cat === cat) && (when === 'All' || (when === 'Next 48hrs' && e.ts <= T + 2 * D) || (when === 'Weekend' && e.ts >= Math.max(fri, T) && e.ts < sunEnd) || (when === 'This Month' && e.ts < monthEnd)) && (!ql || [e.nm, e.ven, e.city, e.cat, e.country].join(' ').toLowerCase().includes(ql));
    const all = DP.EVENTS.filter(ok).sort((a, b) => a.ts - b.ts);
    const inCity = all.filter(e => e.city === city);
    const inCountry = all.filter(e => e.city !== city && e.cc === cc).sort((a, b) => DP.km(city, a.city) - DP.km(city, b.city) || a.ts - b.ts);
    const abroad = all.filter(e => e.cc !== cc).sort((a, b) => DP.km(city, a.city) - DP.km(city, b.city) || a.ts - b.ts);
    const country = DP.CITIES[city].country;
    const tiers = [{ l: 'In ' + city, ev: inCity }];
    if (inCity.length < 8 && inCountry.length) tiers.push({ l: (inCity.length ? 'More in ' : 'Elsewhere in ') + country, s: 'Closest first', ev: inCountry });
    if (abroad.length) tiers.push({ l: 'Worth the trip', s: 'Other countries, closest first', ev: inCity.length + inCountry.length < 8 ? abroad : abroad.filter(e => e.feat) });
    return { all, tiers: tiers.filter(t => t.ev.length), inCity, inCountry, abroad };
  }, [city, cat, when, q]);
}

function Grid({ list, onOpen }) { return <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, padding: '0 16px' }}>{list.map(e => <EventCard key={e.id} ev={e} onOpen={onOpen} />)}</div>; }
function TierLabel({ l, s }) { return <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, padding: '22px 16px 12px', fontSize: 13, fontWeight: 700, color: 'var(--ink)' }}>{l}{s && <span style={{ fontSize: 11.5, fontWeight: 500, color: 'var(--mut2)' }}>· {s}</span>}</div>; }

function Banners({ onOpen }) {
  const [i, setI] = useState(0); const ref = useRef();
  useEffect(() => { const t = setInterval(() => { const el = ref.current; if (!el) return; const n = (Math.round(el.scrollLeft / el.clientWidth) + 1) % DP.BANNERS.length; el.scrollTo({ left: n * el.clientWidth, behavior: 'smooth' }); }, 5000); return () => clearInterval(t); }, []);
  return <div style={{ padding: '4px 0 0' }}>
    <div ref={ref} className="hs" onScroll={e => setI(Math.round(e.target.scrollLeft / e.target.clientWidth))} style={{ gap: 0 }}>
      {DP.BANNERS.map((b, k) => <div key={k} className="press" onClick={() => onOpen(DP.EVENTS.find(e => e.id === b.ev))} style={{ flex: '0 0 100%', padding: '0 16px' }}><div style={{ position: 'relative', aspectRatio: '16/9', borderRadius: 18, overflow: 'hidden', boxShadow: '0 14px 30px -18px rgba(29,13,49,.5)', background: 'var(--chip)' }}><img src={b.img} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /><span style={{ position: 'absolute', top: 10, left: 10, fontFamily: 'var(--dp-font-mono)', fontSize: 8.5, letterSpacing: '.1em', textTransform: 'uppercase', fontWeight: 700, padding: '4px 8px', borderRadius: 6, background: 'rgba(0,0,0,.45)', color: '#fff', backdropFilter: 'blur(6px)' }}>Promoted</span><span style={{ position: 'absolute', right: 10, bottom: 10, padding: '8px 14px', borderRadius: 9999, background: '#fff', color: '#1D0D31', fontWeight: 700, fontSize: 13, boxShadow: '0 8px 20px -8px rgba(0,0,0,.45)' }}>{b.price}</span></div></div>)}
    </div>
    <div style={{ display: 'flex', justifyContent: 'center', gap: 5, marginTop: 10 }}>{DP.BANNERS.map((_, k) => <span key={k} style={{ width: k === i ? 18 : 6, height: 6, borderRadius: 3, background: k === i ? 'var(--red)' : 'var(--line)', transition: 'all .3s' }}></span>)}</div>
  </div>;
}

function CatTiles({ cat, setCat, counts }) {
  return <div className="hs" style={{ gap: 4, padding: '6px 10px 4px', scrollSnapType: 'none' }}>{DP.CATS.filter(c => c === cat || counts[c] > 0).map(c => { const on = c === cat; return <button key={c} className="press" onClick={() => setCat(c)} style={{ flex: 'none', width: 72, height: 64, borderRadius: 14, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 6, background: on ? 'var(--red-soft)' : 'transparent', color: on ? 'var(--red)' : 'var(--ink)', fontSize: 12, fontWeight: 600, transition: 'all .2s' }}>{CAT_SVG[c]}<span>{c}</span></button>; })}</div>;
}
function FilterBar({ when, setWhen }) {
  const { topInset } = useApp();
  return <div style={{ position: 'sticky', top: topInset, zIndex: 6, background: 'var(--bg)' }}>
    <div className="hs" style={{ gap: 6, padding: '8px 16px 10px', scrollSnapType: 'none' }}>{DP.WHEN.map(w => <GradChip key={w} on={w === when} onClick={() => setWhen(w)} svg={window.WHEN_ICONS[w]} style={{ height: 38, fontSize: 13.5, padding: '0 16px' }}>{w === 'Next 48hrs' ? 'Upcoming in 48hrs' : w}</GradChip>)}</div>
  </div>;
}

function Home({ onOpen, onSearch, onCity, onBell, onArtist }) {
  const { city, topInset, bottomInset } = useApp();
  const [cat, setCat] = useState('For You'); const [when, setWhen] = useState('All');
  const [loading, setLoading] = useState(true);
  useEffect(() => { const t = setTimeout(() => setLoading(false), 750); return () => clearTimeout(t); }, [city]);
  useEffect(() => { setLoading(true); }, [city]);
  const F = useFiltered(city, cat, when, '');
  const base = useFiltered(city, 'For You', 'All', '');
  const counts = useMemo(() => { const o = {}; DP.CATS.forEach(c => o[c] = c === 'For You' ? 1 : DP.EVENTS.filter(e => e.cat === c && e.cc === DP.CITIES[city].cc).length); return o; }, [city]);
  const cc = DP.CITIES[city].cc, country = DP.CITIES[city].country;
  const hot = useMemo(() => { const pool = DP.EVENTS.filter(e => e.cc === cc); const a = pool.filter(e => e.feat).slice(0, 4), b = pool.filter(e => !e.feat).slice(0, 4); return [...a, ...b].slice(0, 4); }, [city]);
  const hotTitle = hot.every(e => e.city === city) ? city : country;
  const filtered = cat !== 'For You' || when !== 'All';
  const countries = useMemo(() => { const m = {}; Object.keys(DP.CITIES).forEach(c => { const n = DP.EVENTS.filter(e => e.city === c).length; if (!n) return; const k = DP.CITIES[c].country; (m[k] = m[k] || { k, cc: DP.CITIES[c].cc, list: [] }).list.push({ c, n }); }); return Object.values(m).map(g => ({ ...g, list: g.list.sort((a, b) => b.n - a.n) })).sort((a, b) => (a.cc === cc ? -1 : b.cc === cc ? 1 : a.k.localeCompare(b.k))); }, [city]);
  const [ctab, setCtab] = useState(0);
  return (
    <div className="scr" style={{ paddingBottom: bottomInset + 80 }}>
      <div style={{ position: 'sticky', top: 0, zIndex: 7, height: topInset, background: 'var(--bg)' }}></div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 16px 10px' }}>
        <Logo h={24} />
        <button className="press" onClick={onCity} style={{ marginLeft: 'auto', display: 'inline-flex', alignItems: 'center', gap: 5, height: 34, padding: '0 12px 0 10px', borderRadius: 9999, border: '1px solid transparent', background: 'linear-gradient(var(--sur),var(--sur)) padding-box,linear-gradient(90deg,#E54558,#3B2E4D) border-box', color: 'var(--ink)', fontSize: 13, fontWeight: 600 }}><Ico.pin size={16} style={{ color: 'var(--red)' }} />{city}<Ico.down size={13} style={{ color: 'var(--mut)' }} /></button>
        <IconBtn icon={Ico.bell} onClick={onBell} size={36} dim={21} label="Notifications" style={{ position: 'relative' }} />
      </div>
      <CatTiles cat={cat} setCat={setCat} counts={counts} />
      <div style={{ height: 8 }}></div>
      <Banners onOpen={onOpen} />
      <button className="press" onClick={onSearch} style={{ display: 'flex', alignItems: 'center', gap: 10, width: 'calc(100% - 32px)', margin: '18px 16px 8px', height: 50, padding: '0 16px', borderRadius: 14, background: 'var(--sur)', border: '1px solid var(--line)', boxShadow: '0 6px 18px -12px rgba(29,13,49,.25)', color: 'var(--mut2)', fontSize: 14.5, fontWeight: 500, textAlign: 'left' }}><Ico.search size={19} /><span style={{ width: 1, height: 22, background: 'var(--line)' }}></span>Search events</button>
      <FilterBar when={when} setWhen={setWhen} />
      {loading ? <div style={{ padding: '18px 16px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>{[0, 1, 2, 3].map(i => <CardSkeleton key={i} />)}</div> :
        filtered ? <div className="fade-in" key={cat + when}>
          <div style={{ padding: '24px 0 0' }}><SecHead title={(cat === 'For You' ? 'Events' : cat) + (when === 'All' ? '' : ' · ' + when.toLowerCase())} sub={`${F.inCity.length} in ${city} · ${F.inCountry.length + F.abroad.length} more nearby`} action="Clear" onAction={() => { setCat('For You'); setWhen('All'); }} /></div>
          {F.all.length === 0 && <div style={{ padding: '30px 24px', textAlign: 'center', color: 'var(--mut)' }}><img src={DP.A + 'illustrations/empty.svg'} alt="" style={{ width: 120, margin: '0 auto 12px', opacity: .9 }} /><b style={{ color: 'var(--ink)' }}>Nothing {when === 'All' ? 'here yet' : when.toLowerCase()}</b><div style={{ fontSize: 13, marginTop: 4 }}>Try another date or category.</div></div>}
          {F.tiers.map(t => <div key={t.l}>{F.tiers.length > 1 && <TierLabel l={t.l} s={t.s} />}<Grid list={t.ev} onOpen={onOpen} /></div>)}
        </div> : <div className="fade-in">
          {base.inCity.length > 0 && base.inCity.length <= 4 && <section style={{ paddingTop: 32 }}><SecHead title={'In ' + city} sub={base.inCity.length + ' events coming up'} /><Grid list={base.inCity} onOpen={onOpen} /></section>}
          {hot.length > 0 && <section style={{ paddingTop: 32 }}><SecHead title="Hot & fresh in" em={hotTitle} /><Grid list={hot} onOpen={onOpen} /></section>}
          <section style={{ paddingTop: 32 }}><SecHead title="All events" em="nearby" />{base.tiers.map((t, k) => <div key={t.l}>{(base.tiers.length > 1 && k > 0) && <TierLabel l={t.l} s={t.s} />}<Grid list={t.ev.slice(0, k === 0 ? 8 : 4)} onOpen={onOpen} /></div>)}</section>
          <section style={{ paddingTop: 32 }}><SecHead title="Explore" em="cities" />
            <div className="hs" style={{ gap: 4, padding: '0 16px 14px', scrollSnapType: 'none' }}>{[{ k: 'All', all: true }, ...countries].map((g, i) => { const on = ctab === i; const n = g.all ? countries.reduce((s, c) => s + c.list.reduce((a, x) => a + x.n, 0), 0) : g.list.reduce((a, x) => a + x.n, 0); return <button key={g.k} onClick={() => setCtab(i)} style={{ flex: 'none', height: 36, padding: '0 14px', borderRadius: 9999, fontSize: 14, fontWeight: 600, background: on ? 'var(--red-soft)' : 'transparent', color: on ? 'var(--red)' : 'var(--purple)', whiteSpace: 'nowrap' }}>{g.k}<small style={{ fontWeight: 500, color: 'var(--mut2)', marginLeft: 5 }}>{n}</small></button>; })}</div>
            <div key={ctab} className="fade-in" style={{ display: 'grid', gridTemplateColumns: 'repeat(2,minmax(0,1fr))', gap: '18px 12px', padding: '0 16px' }}>{(ctab === 0 ? countries.flatMap(g => g.list) : countries[ctab - 1].list).map(({ c, n }) => <button key={c} className="press" onClick={() => onCity(c)} style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0, minHeight: 52, textAlign: 'left' }}><span style={{ width: 48, height: 48, flex: 'none', borderRadius: 12, background: 'var(--red-soft)', color: 'var(--red)', display: 'grid', placeItems: 'center' }}><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" dangerouslySetInnerHTML={{ __html: (window.CITY_ICON || {})[c] || window.CITY_ICON_GENERIC }}></svg></span><span style={{ minWidth: 0 }}><span style={{ display: 'block', fontSize: 15.5, fontWeight: 600, letterSpacing: '-.01em', color: 'var(--ink)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c}</span><span style={{ display: 'block', fontSize: 13, color: 'var(--mut)', marginTop: 2 }}>{n} {n === 1 ? 'event' : 'events'}</span></span></button>)}</div>
          </section>
          <section style={{ paddingTop: 32 }}><SecHead title="Artists on" em="tour" />
            <div style={{ display: 'grid', gap: 10, padding: '0 16px' }}>{DP.ARTISTS.map(a => <div key={a.nm} className="press" onClick={() => onArtist(a)} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 14, 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)' }}><img src={a.img} alt="" style={{ width: 56, height: 56, borderRadius: '50%', objectFit: 'cover' }} /><div style={{ flex: 1 }}><div style={{ fontWeight: 700, fontSize: 15 }}>{a.nm}</div><div style={{ fontSize: 12.5, color: 'var(--mut)', marginTop: 2 }}>{a.sub}</div></div><Ico.chev size={18} style={{ color: 'var(--mut2)' }} /></div>)}</div>
          </section>
        </div>}
    </div>
  );
}

function CityPicker({ open, onClose }) {
  const { city, setCity } = useApp();
  const [q, setQ] = useState('');
  const groups = useMemo(() => { const cc = DP.CITIES[city].cc; const m = {}; Object.keys(DP.CITIES).forEach(c => { const n = DP.EVENTS.filter(e => e.city === c).length; if (!n || !c.toLowerCase().includes(q.toLowerCase())) return; const k = DP.CITIES[c].country; (m[k] = m[k] || { k, cc: DP.CITIES[c].cc, d: DP.km(city, c), list: [] }).list.push({ c, n }); }); return Object.values(m).sort((a, b) => (a.cc === cc ? -1 : b.cc === cc ? 1 : a.d - b.d)); }, [city, q]);
  return <Sheet open={open} onClose={onClose} title="Choose your city" full>
    <Field icon={Ico.search} style={{ marginBottom: 12 }}><input value={q} onChange={e => setQ(e.target.value)} placeholder="Search city" style={inputStyle} /></Field>
    <button className="press" onClick={() => { setCity('Berlin'); onClose(); }} style={{ display: 'flex', alignItems: 'center', gap: 10, width: '100%', padding: '12px 4px', color: 'var(--red)', fontWeight: 700, fontSize: 14 }}><Ico.pin size={18} />Use my current location</button>
    {groups.map(g => <div key={g.k}><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 10.5, letterSpacing: '.14em', textTransform: 'uppercase', color: 'var(--mut2)', fontWeight: 600, padding: '14px 4px 4px' }}>{g.k}</div>{g.list.map(({ c, n }) => <Row key={c} label={c} value={n + ' events'} onClick={() => { setCity(c); onClose(); }} right={c === city ? <Ico.check size={18} style={{ color: 'var(--red)' }} /> : <span />} />)}</div>)}
  </Sheet>;
}

function SearchScreen({ z, onBack, onOpen }) {
  const { city, topInset } = useApp();
  const [q, setQ] = useState(''); const ref = useRef();
  useEffect(() => { setTimeout(() => ref.current && ref.current.focus(), 350); }, []);
  const F = useFiltered(city, 'For You', 'All', q);
  const show = q.trim().length > 1;
  const sugg = ['Diwali', 'Comedy', 'London', 'Garba', 'Bollywood'];
  return <div className="push scr" style={{ zIndex: z || 30 }}>
    <div style={{ position: 'sticky', top: 0, zIndex: 5, display: 'flex', alignItems: 'center', gap: 8, padding: `${topInset + 6}px 12px 10px`, background: 'var(--bg)' }}><IconBtn icon={Ico.back} onClick={onBack} bg="var(--chip)" label="Back" /><Field icon={Ico.search} style={{ flex: 1, height: 44 }}><input ref={ref} value={q} onChange={e => setQ(e.target.value)} placeholder="Search events, artists, venues…" style={inputStyle} />{q && <IconBtn icon={Ico.x} onClick={() => setQ('')} size={28} dim={14} bg="var(--chip)" label="Clear" />}</Field></div>
    {!show ? <div style={{ padding: '10px 16px' }}><div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--mut)', margin: '6px 0 10px' }}>Popular searches</div><div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>{sugg.map(s => <button key={s} className="press" onClick={() => setQ(s)} style={{ height: 36, padding: '0 14px', borderRadius: 9999, background: 'var(--chip)', fontSize: 13.5, fontWeight: 600 }}>{s}</button>)}</div></div> :
      <div className="fade-in" key={q}>
        {F.all.length === 0 && <div style={{ padding: '40px 24px', textAlign: 'center', color: 'var(--mut)' }}><b style={{ color: 'var(--ink)' }}>No results for “{q}”</b><div style={{ fontSize: 13, marginTop: 4 }}>Try an artist, city or category.</div></div>}
        {F.tiers.map(t => <div key={t.l}>{F.tiers.length > 1 && <TierLabel l={t.l} s={t.s} />}<div style={{ padding: '0 16px', display: 'grid', gap: 8 }}>{t.ev.map(e => <button key={e.id} className="press" onClick={() => onOpen(e)} style={{ display: 'flex', gap: 12, alignItems: 'center', padding: 8, borderRadius: 14, background: 'var(--sur)', boxShadow: 'var(--shadow)', textAlign: 'left' }}><img src={e.img} alt="" style={{ width: 56, height: 70, borderRadius: 9, objectFit: 'cover' }} /><div style={{ flex: 1, minWidth: 0 }}><div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 9.5, color: 'var(--red)', fontWeight: 600, letterSpacing: '.05em' }}>{e.day} · {e.dateLbl.toUpperCase()}</div><div style={{ fontWeight: 700, fontSize: 14, marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.nm}</div><div style={{ fontSize: 12, color: 'var(--mut)', marginTop: 3 }}>{e.ven} · {e.city}{e.cc !== DP.CITIES[city].cc ? ', ' + e.cc : ''}</div></div><div style={{ fontWeight: 700, fontSize: 13.5, color: e.price || e.pmax ? 'var(--price)' : 'var(--green)', whiteSpace: 'nowrap' }}>{DP.priceLbl(e)}</div></button>)}</div></div>)}
      </div>}
  </div>;
}

Object.assign(window, { Home, CityPicker, SearchScreen, useFiltered });
