/* ============================================================
   EVENTS PAGE — live ChurchSuite feed
   ============================================================ */

const CS_FEED_URL = 'https://bethanybaptist.churchsuite.com/embed/calendar/json?merge_link=1';
const CS_PUBLIC_BASE = 'https://bethanybaptist.churchsuite.com/events/';

/* ---------- Date helpers (parse "YYYY-MM-DD HH:MM:SS" as local) ---------- */
function parseCSDate(s) {
  if (!s) return null;
  const [d, t] = s.split(' ');
  const [y, mo, da] = d.split('-').map(Number);
  const [h, mi, se] = (t || '00:00:00').split(':').map(Number);
  return new Date(y, mo - 1, da, h, mi, se);
}
const MONTHS_SHORT = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const DAYS_LONG = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

function fmtTime(date) {
  let h = date.getHours();
  const m = date.getMinutes();
  const ap = h >= 12 ? 'pm' : 'am';
  h = h % 12 || 12;
  return m === 0 ? `${h}${ap}` : `${h}:${String(m).padStart(2,'0')}${ap}`;
}
function fmtDateLong(date) {
  return `${DAYS_LONG[date.getDay()]} ${date.getDate()} ${MONTHS_SHORT[date.getMonth()]} ${date.getFullYear()}`;
}

/* ---------- Recurring detection ----------
   ChurchSuite gives every event a unique id but events sharing a `name`
   in the upcoming window are clearly recurring (Midweek, Bethany Tots, etc).
   We also check rough cadence (avg gap in days). */
function detectRecurrence(events) {
  const byName = {};
  events.forEach(e => {
    (byName[e.name] = byName[e.name] || []).push(parseCSDate(e.datetime_start));
  });
  const map = {};
  Object.entries(byName).forEach(([name, dates]) => {
    if (dates.length < 2) return;
    dates.sort((a,b) => a - b);
    const gaps = [];
    for (let i = 1; i < dates.length; i++) {
      gaps.push(Math.round((dates[i] - dates[i-1]) / 86400000));
    }
    const avg = gaps.reduce((a,b) => a+b, 0) / gaps.length;
    let label = null;
    if (avg <= 1.5) label = 'Daily';
    else if (avg >= 6 && avg <= 8) label = 'Weekly';
    else if (avg >= 13 && avg <= 16) label = 'Fortnightly';
    else if (avg >= 27 && avg <= 32) label = 'Monthly';
    else if (avg > 0) label = 'Recurring';
    if (label) map[name] = label;
  });
  return map;
}

/* ---------- Age-range detection from name/description ---------- */
function detectAgeRange(e) {
  const blob = `${e.name} ${e.description}`.toLowerCase();
  if (/(p1|p2|p3|p4|p5|p6|p7|primary)\b/.test(blob)) return 'Primary';
  if (/\b(11[\s-]+18|youth|teen|teenager)\b/.test(blob)) return '11–18';
  if (/\b(toddler|tots|preschool|pre[\s-]?school)\b/.test(blob)) return '0–4';
  if (/\b(children|kids|child)\b/.test(blob)) return 'Children';
  return null;
}

/* ---------- Strip HTML for previews ---------- */
function stripHtml(html) {
  if (!html) return '';
  const tmp = document.createElement('div');
  tmp.innerHTML = html;
  return tmp.textContent || '';
}

/* ---------- Add-to-calendar helpers ---------- */
function pad(n) { return String(n).padStart(2, '0'); }
function toICSDate(d) {
  return `${d.getFullYear()}${pad(d.getMonth()+1)}${pad(d.getDate())}T${pad(d.getHours())}${pad(d.getMinutes())}00`;
}
function downloadICS(ev) {
  const start = parseCSDate(ev.datetime_start);
  const end = parseCSDate(ev.datetime_end) || new Date(start.getTime() + 3600000);
  const desc = stripHtml(ev.description).replace(/\n/g, '\\n');
  const loc = ev.location?.address || '';
  const ics = [
    'BEGIN:VCALENDAR','VERSION:2.0','PRODID:-//Bethany Baptist//EN','BEGIN:VEVENT',
    `UID:${ev.identifier}@bethanybaptist.co.uk`,
    `DTSTAMP:${toICSDate(new Date())}`,
    `DTSTART:${toICSDate(start)}`,
    `DTEND:${toICSDate(end)}`,
    `SUMMARY:${ev.name}`,
    desc ? `DESCRIPTION:${desc}` : '',
    loc ? `LOCATION:${loc}` : '',
    'END:VEVENT','END:VCALENDAR',
  ].filter(Boolean).join('\r\n');
  const blob = new Blob([ics], { type: 'text/calendar' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = `${ev.identifier}.ics`;
  a.click();
}
function googleCalUrl(ev) {
  const start = parseCSDate(ev.datetime_start);
  const end = parseCSDate(ev.datetime_end) || new Date(start.getTime() + 3600000);
  const fmt = d => `${d.getFullYear()}${pad(d.getMonth()+1)}${pad(d.getDate())}T${pad(d.getHours())}${pad(d.getMinutes())}00`;
  const params = new URLSearchParams({
    action: 'TEMPLATE',
    text: ev.name,
    dates: `${fmt(start)}/${fmt(end)}`,
    details: stripHtml(ev.description),
    location: ev.location?.address || '',
  });
  return `https://calendar.google.com/calendar/render?${params}`;
}

/* ---------- Feed hook (cached for 5 minutes) ---------- */
window.useChurchSuiteEvents = function useChurchSuiteEvents() {
  const [events, setEvents] = useState(() => {
    try {
      const raw = localStorage.getItem('bb_cs_events_v1');
      if (!raw) return null;
      const { ts, v } = JSON.parse(raw);
      if (Date.now() - ts > 5*60*1000) return null;
      return v;
    } catch { return null; }
  });
  const [error, setError] = useState(null);

  useEffect(() => {
    let cancelled = false;
    fetch(CS_FEED_URL)
      .then(r => r.json())
      .then(data => {
        if (cancelled) return;
        // Filter to upcoming only (server already sends future events but be safe)
        const now = Date.now();
        const upcoming = data
          .filter(e => parseCSDate(e.datetime_start)?.getTime() >= now - 6*3600*1000) // allow 6h grace
          .sort((a,b) => parseCSDate(a.datetime_start) - parseCSDate(b.datetime_start));
        setEvents(upcoming);
        try { localStorage.setItem('bb_cs_events_v1', JSON.stringify({ ts: Date.now(), v: upcoming })); } catch {}
      })
      .catch(e => { if (!cancelled) setError(e); });
    return () => { cancelled = true; };
  }, []);

  return { events, error };
};

/* ============================================================ */

function EventsPage() {
  const { events, error } = window.useChurchSuiteEvents();
  const [cat, setCat] = useState('All');
  const [query, setQuery] = useState('');
  const [openId, setOpenId] = useState(null);

  const recurrence = useMemo(() => events ? detectRecurrence(events) : {}, [events]);

  // Build category list dynamically
  const cats = useMemo(() => {
    if (!events) return ['All'];
    const set = new Set();
    events.forEach(e => { if (e.category?.name) set.add(e.category.name); });
    return ['All', ...Array.from(set).sort()];
  }, [events]);

  // Filter
  const filtered = useMemo(() => {
    if (!events) return [];
    return events.filter(e => {
      if (cat !== 'All' && e.category?.name !== cat) return false;
      if (query) {
        const q = query.toLowerCase();
        const blob = `${e.name} ${stripHtml(e.description)} ${e.location?.address || ''}`.toLowerCase();
        if (!blob.includes(q)) return false;
      }
      return true;
    });
  }, [events, cat, query]);

  const featured = filtered[0];
  const rest = filtered.slice(1);
  const openEvent = openId && events ? events.find(e => e.identifier === openId) : null;

  return (
    <>
      <PageHead
        crumbs={[{label:'Home', href:'#/home'}, {label:'Events'}]}
        title={<>What's <em style={{fontStyle:'italic',color:'var(--c-accent)',fontWeight:400}}>happening</em></>}
        lede="Sunday gatherings, mid-week ministries, community events — there's always something on at Bethany."
      />

      <section style={{ paddingTop: 40, paddingBottom: 80 }}>
        <div className="container">

          {/* Filter row */}
          <div className="ev-controls">
            <div className="filter-chips" style={{ marginTop: 0 }}>
              {cats.map(c => (
                <button key={c}
                  className={`chip ${cat === c ? 'active' : ''}`}
                  onClick={() => setCat(c)}>
                  {c}
                </button>
              ))}
            </div>
            <div className="search-wrap" style={{ flex: '0 1 320px', minWidth: 240 }}>
              <Icon.search/>
              <input
                type="search"
                placeholder="Search events…"
                value={query}
                onChange={e => setQuery(e.target.value)}
              />
            </div>
          </div>

          {/* Loading / error / empty states */}
          {!events && !error && (
            <div className="ev-empty">
              <div className="ev-spinner" aria-hidden="true"></div>
              <div>Loading events from ChurchSuite…</div>
            </div>
          )}
          {error && (
            <div className="ev-empty">
              <div>Couldn't load events right now. Please try again shortly, or visit our <a href="https://bethanybaptist.churchsuite.com/events" target="_blank" rel="noopener">ChurchSuite calendar</a> directly.</div>
            </div>
          )}
          {events && filtered.length === 0 && (
            <div className="ev-empty">
              <div>No upcoming events match your filter. Try clearing the search or selecting a different category.</div>
            </div>
          )}

          {/* Featured */}
          {featured && (
            <FeaturedEventCard ev={featured} recurrence={recurrence[featured.name]} onOpen={() => setOpenId(featured.identifier)} />
          )}

          {/* Rest */}
          {rest.length > 0 && (
            <div className="ev-list-modern">
              {rest.map(e => (
                <EventRow
                  key={e.identifier}
                  ev={e}
                  recurrence={recurrence[e.name]}
                  onOpen={() => setOpenId(e.identifier)}
                />
              ))}
            </div>
          )}

          {/* Footer link to ChurchSuite full calendar */}
          {events && events.length > 0 && (
            <div className="ev-footer-cta">
              <div>
                <div className="eyebrow">Powered by ChurchSuite</div>
                <div style={{ marginTop: 4, fontWeight: 600 }}>Looking for a private group event?</div>
                <p style={{ margin: '6px 0 0', fontSize: 14, color: 'var(--c-muted)' }}>Sign in to ChurchSuite to see members-only events and manage your bookings.</p>
              </div>
              <a href="https://bethanybaptist.churchsuite.com" target="_blank" rel="noopener" className="btn btn-outline">Open ChurchSuite <Icon.arrow/></a>
            </div>
          )}
        </div>
      </section>

      {/* Detail modal */}
      {openEvent && (
        <EventModal
          ev={openEvent}
          recurrence={recurrence[openEvent.name]}
          onClose={() => setOpenId(null)}
        />
      )}
    </>
  );
}

/* ============================================================ */

function FeaturedEventCard({ ev, recurrence, onOpen }) {
  const start = parseCSDate(ev.datetime_start);
  const end = parseCSDate(ev.datetime_end);
  const age = detectAgeRange(ev);
  const desc = stripHtml(ev.description);

  return (
    <div className="ev-featured" onClick={onOpen} role="button" tabIndex={0} onKeyDown={e => e.key === 'Enter' && onOpen()}>
      <div className="ev-feat-date">
        <div className="efd-mo">{MONTHS_SHORT[start.getMonth()]}</div>
        <div className="efd-d">{start.getDate()}</div>
        <div className="efd-day">{DAYS_LONG[start.getDay()].slice(0,3)}</div>
      </div>
      <div className="ev-feat-body">
        <div className="ev-tags">
          <span className="ev-tag ev-tag-next">Next up</span>
          {ev.category?.name && <span className="ev-tag">{ev.category.name}</span>}
          {recurrence && <span className="ev-tag ev-tag-rec">↻ {recurrence}</span>}
          {age && <span className="ev-tag ev-tag-age">{age}</span>}
        </div>
        <h2 className="ev-feat-title">{ev.name}</h2>
        <div className="ev-feat-meta">
          <span><Icon.clock/> {fmtTime(start)}{end ? `–${fmtTime(end)}` : ''}</span>
          {ev.location?.address && <span><Icon.mapPin/> {shortAddress(ev.location.address)}</span>}
        </div>
        {desc && <p className="ev-feat-desc">{desc.slice(0, 220)}{desc.length > 220 ? '…' : ''}</p>}
        <div className="ev-feat-cta">
          <button className="btn btn-primary" onClick={e => { e.stopPropagation(); onOpen(); }}>
            View details <Icon.arrow/>
          </button>
        </div>
      </div>
    </div>
  );
}

function EventRow({ ev, recurrence, onOpen }) {
  const start = parseCSDate(ev.datetime_start);
  const end = parseCSDate(ev.datetime_end);
  const age = detectAgeRange(ev);

  return (
    <button type="button" className="ev-row" onClick={onOpen}>
      <div className="ev-row-date">
        <div className="erd-mo">{MONTHS_SHORT[start.getMonth()]}</div>
        <div className="erd-d">{start.getDate()}</div>
      </div>
      <div className="ev-row-body">
        <div className="ev-row-title-line">
          <h4>{ev.name}</h4>
          {recurrence && <span className="ev-tag ev-tag-rec">↻ {recurrence}</span>}
          {age && <span className="ev-tag ev-tag-age">{age}</span>}
        </div>
        <div className="ev-row-meta">
          <span><Icon.calendar/> {DAYS_LONG[start.getDay()]}</span>
          <span><Icon.clock/> {fmtTime(start)}{end ? `–${fmtTime(end)}` : ''}</span>
          {ev.location?.address && <span><Icon.mapPin/> {shortAddress(ev.location.address)}</span>}
          {ev.category?.name && <span className="ev-row-cat">{ev.category.name}</span>}
        </div>
      </div>
      <div className="ev-row-arrow"><Icon.arrow/></div>
    </button>
  );
}

function shortAddress(addr) {
  if (!addr) return '';
  // Trim to first 1-2 segments to keep meta line tidy
  const parts = addr.split(',').map(s => s.trim()).filter(Boolean);
  return parts.slice(0, 2).join(', ');
}

/* ============================================================ */

function EventModal({ ev, recurrence, onClose }) {
  const start = parseCSDate(ev.datetime_start);
  const end = parseCSDate(ev.datetime_end);
  const age = detectAgeRange(ev);
  const desc = ev.description; // keep HTML in modal
  const signupUrl = ev.signup_options?.tickets?.url || `${CS_PUBLIC_BASE}${ev.identifier}`;
  const signupEnabled = ev.signup_options?.signup_enabled === '1' || ev.signup_options?.tickets?.enabled === '1';
  const [addOpen, setAddOpen] = useState(false);

  // Esc to close + lock scroll
  useEffect(() => {
    const onKey = e => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [onClose]);

  return (
    <div className="ev-modal-backdrop" onClick={onClose}>
      <div className="ev-modal" onClick={e => e.stopPropagation()} role="dialog" aria-modal="true">
        <button className="ev-modal-close" onClick={onClose} aria-label="Close"><Icon.x/></button>

        <div className="ev-modal-head">
          <div className="ev-modal-date">
            <div className="emd-mo">{MONTHS_SHORT[start.getMonth()]}</div>
            <div className="emd-d">{start.getDate()}</div>
            <div className="emd-yr">{start.getFullYear()}</div>
          </div>
          <div className="ev-modal-head-body">
            <div className="ev-tags">
              {ev.category?.name && <span className="ev-tag">{ev.category.name}</span>}
              {recurrence && <span className="ev-tag ev-tag-rec">↻ {recurrence}</span>}
              {age && <span className="ev-tag ev-tag-age">{age}</span>}
            </div>
            <h2 style={{ fontFamily: 'var(--font-display)', margin: '8px 0 4px', lineHeight: 1.15 }}>{ev.name}</h2>
            <div className="ev-modal-meta">
              <span><Icon.calendar/> {fmtDateLong(start)}</span>
              <span><Icon.clock/> {fmtTime(start)}{end ? `–${fmtTime(end)}` : ''}</span>
            </div>
          </div>
        </div>

        {desc && (
          <div className="ev-modal-section">
            <h5>About this event</h5>
            <div className="ev-modal-desc" dangerouslySetInnerHTML={{ __html: desc }} />
          </div>
        )}

        {ev.location?.address && (
          <div className="ev-modal-section">
            <h5>Location</h5>
            <div style={{ marginBottom: 14, color: 'var(--c-ink-2)', fontSize: 15 }}>{ev.location.address}</div>
            <div className="ev-modal-map">
              <iframe
                title="Event location map"
                src={`https://www.google.com/maps?q=${encodeURIComponent(ev.location.address)}&output=embed`}
                loading="lazy"
                referrerPolicy="no-referrer-when-downgrade"
              />
            </div>
            <a
              href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(ev.location.address)}`}
              target="_blank" rel="noopener"
              className="btn btn-outline"
              style={{ marginTop: 14 }}>
              Get directions <Icon.arrow/>
            </a>
          </div>
        )}

        <div className="ev-modal-footer">
          <div className="ev-add-cal" data-open={addOpen}>
            <button className="btn btn-ghost" onClick={() => setAddOpen(o => !o)}>
              <Icon.calendar/> Add to calendar
            </button>
            {addOpen && (
              <div className="ev-add-cal-menu">
                <a href={googleCalUrl(ev)} target="_blank" rel="noopener" onClick={() => setAddOpen(false)}>Google Calendar</a>
                <button type="button" onClick={() => { downloadICS(ev); setAddOpen(false); }}>Apple Calendar (.ics)</button>
                <button type="button" onClick={() => { downloadICS(ev); setAddOpen(false); }}>Outlook (.ics)</button>
              </div>
            )}
          </div>
          <a
            href={signupUrl}
            target="_blank" rel="noopener"
            className="btn btn-primary">
            {signupEnabled ? <>Sign up <Icon.arrow/></> : <>View on ChurchSuite <Icon.arrow/></>}
          </a>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { EventsPage, FeaturedEventCard, EventRow, EventModal });
