// Trove — homepage discovery blocks
//  • DiscoverSearch : one search box across the Wiki, Calendar and Tools
//  • ThisWeek       : what's coming up in the next fortnight, from the calendar
//  • PicksOfTheWeek : a Wiki article + a tool, rotating weekly (article prefers
//                     one tied to an event happening now)
// Own scope, so calendar date helpers are re-declared here with a dsc* prefix.

const DSC_MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const DSC_WD = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const DSC_TYPE_LABEL = { festival: 'Festival', awareness: 'Awareness day', seasonal: 'Seasonal', national: 'National day', commemoration: 'Commemoration', term: 'Term dates' };
const DSC_TYPE_COLOR = { festival: 'oklch(0.58 0.13 320)', awareness: 'oklch(0.56 0.11 245)', seasonal: 'oklch(0.56 0.11 150)', national: 'oklch(0.56 0.13 28)', commemoration: 'oklch(0.52 0.03 265)', term: 'oklch(0.62 0.10 72)' };

function dscParse(s) { const [y, m, d] = s.split('-').map(Number); return new Date(y, m - 1, d); }
function dscMidnight(d) { const x = new Date(d); x.setHours(0, 0, 0, 0); return x; }
// Every dated occurrence of every event, across all academic years in the data.
function dscAllOccurrences(events) {
  const out = [];
  events.forEach(ev => {
    Object.keys(ev.d || {}).forEach(year => {
      const d = ev.d[year];
      if (!d) return;
      const start = dscParse(Array.isArray(d) ? d[0] : d);
      const end = Array.isArray(d) ? dscParse(d[1]) : null;
      out.push({ ev, year, start, end });
    });
  });
  return out.sort((a, b) => a.start - b.start);
}
function dscRelative(start, end) {
  const today = dscMidnight(new Date());
  const s = dscMidnight(start);
  const e = end ? dscMidnight(end) : s;
  if (today >= s && today <= e) return 'Today';
  const days = Math.round((s - today) / 86400000);
  if (days === 1) return 'Tomorrow';
  if (days < 7) return DSC_WD[s.getDay()];
  if (days < 14) return 'Next week';
  return `${s.getDate()} ${DSC_MONTHS[s.getMonth()].slice(0, 3)}`;
}
// Stable week number, so the weekly picks change every Monday and never mid-week.
function dscWeekIndex() {
  const now = new Date();
  return Math.floor((now - new Date(2026, 0, 5)) / (7 * 86400000));
}

// ══════════════════════════════════════════════════════════════
// Unified search across the free content
// ══════════════════════════════════════════════════════════════
function dscNorm(s) { return (s || '').toLowerCase(); }
function dscBuildIndex() {
  const items = [];
  (window.WIKI_ARTICLES || []).forEach(a => {
    items.push({ kind: 'wiki', title: a.title, sub: `${a.category} · ${a.keystage}`, blurb: a.lead || a.summary || '', slug: a.slug,
                 hay: dscNorm(`${a.title} ${a.lead || a.summary || ''} ${a.category} ${a.keystage}`) });
  });
  (window.SCHOOL_CALENDAR || []).forEach(ev => {
    items.push({ kind: 'calendar', title: ev.title, sub: DSC_TYPE_LABEL[ev.type] || 'Event', blurb: ev.blurb, id: ev.id,
                 hay: dscNorm(`${ev.title} ${ev.blurb} ${DSC_TYPE_LABEL[ev.type]}`) });
  });
  (window.SHOWCASE_ITEMS || []).forEach(t => {
    items.push({ kind: 'tool', title: t.name, sub: t.tag, blurb: 'Interactive whiteboard tool.', slug: t.slug,
                 hay: dscNorm(`${t.name} ${t.tag} tool whiteboard`) });
  });
  return items;
}
function dscSearch(index, q) {
  const terms = dscNorm(q).split(/\s+/).filter(Boolean);
  if (!terms.length) return [];
  return index
    .map(it => {
      let score = 0;
      for (const t of terms) {
        if (!it.hay.includes(t)) return null;
        if (dscNorm(it.title).startsWith(t)) score += 6;
        else if (dscNorm(it.title).includes(t)) score += 4;
        else score += 1;
      }
      return { ...it, score };
    })
    .filter(Boolean)
    .sort((a, b) => b.score - a.score || a.title.localeCompare(b.title))
    .slice(0, 8);
}

function DiscoverSearch({ onOpenArticle, onOpenCalendar }) {
  const { isMobile } = window.useViewport();
  const [q, setQ] = React.useState('');
  const [focused, setFocused] = React.useState(false);
  const [open, setOpen] = React.useState(false);
  const wrapRef = React.useRef(null);
  const index = React.useMemo(dscBuildIndex, []);
  const results = React.useMemo(() => dscSearch(index, q), [index, q]);

  React.useEffect(() => {
    function onDoc(e) { if (!wrapRef.current?.contains(e.target)) setOpen(false); }
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);

  function pick(r) {
    setOpen(false); setQ('');
    if (r.kind === 'wiki') onOpenArticle(r.slug);
    else if (r.kind === 'calendar') onOpenCalendar(r.id);
    else window.location.href = `${window.TOOLS_URL}/tools/${r.slug}`;
  }

  const kindMeta = {
    wiki: { label: 'Wiki', color: 'var(--gold-deep)' },
    calendar: { label: 'Calendar', color: 'oklch(0.56 0.11 245)' },
    tool: { label: 'Tool', color: 'oklch(0.56 0.11 150)' },
  };
  const showList = open && q.trim().length > 0;

  return (
    <div ref={wrapRef} style={{ position: 'relative', width: '100%', zIndex: showList ? 200 : 'auto' }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 14, padding: isMobile ? '4px 8px 4px 18px' : '6px 10px 6px 26px',
        background: 'var(--bg)', border: `1px solid ${focused ? 'var(--accent)' : 'var(--border-strong)'}`,
        borderRadius: 18, boxShadow: focused ? '0 0 0 4px var(--ring)' : 'var(--shadow-sm)', transition: 'box-shadow .2s, border-color .2s',
      }}>
        <Icon.Search width={isMobile ? 20 : 24} height={isMobile ? 20 : 24} style={{ color: 'var(--fg-subtle)', flexShrink: 0 }} />
        <input
          value={q}
          onChange={(e) => { setQ(e.target.value); setOpen(true); }}
          onFocus={() => { setFocused(true); setOpen(true); }}
          onBlur={() => setFocused(false)}
          onKeyDown={(e) => { if (e.key === 'Escape') setOpen(false); if (e.key === 'Enter' && results[0]) pick(results[0]); }}
          placeholder={isMobile ? 'What do you need?' : 'What do you need?'}
          aria-label="Search the Wiki, Calendar and Tools"
          style={{ flex: 1, minWidth: 0, border: 0, outline: 'none', background: 'transparent', padding: isMobile ? '14px 0' : '18px 0', fontSize: isMobile ? 17 : 21, fontFamily: 'inherit', fontWeight: 500, color: 'var(--fg)' }}
        />
        {q && (
          <button onMouseDown={(e) => e.preventDefault()} onClick={() => { setQ(''); }} aria-label="Clear search"
            style={{ background: 'none', border: 0, cursor: 'pointer', color: 'var(--fg-subtle)', padding: 10, display: 'inline-flex' }}>
            <Icon.X width="18" height="18" />
          </button>
        )}
      </div>

      {showList && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 8px)', left: 0, right: 0,
          background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 14,
          boxShadow: 'var(--shadow-xl)', overflow: 'hidden', maxHeight: 420, overflowY: 'auto',
        }}>
          {results.length === 0 ? (
            <div style={{ padding: '18px 20px', fontSize: 14.5, color: 'var(--fg-muted)' }}>
              Nothing matched. Try a topic, a festival or a tool name.
            </div>
          ) : results.map((r, i) => (
            <button key={`${r.kind}-${r.slug || r.id}`} onMouseDown={(e) => e.preventDefault()} onClick={() => pick(r)}
              style={{
                display: 'flex', gap: 12, alignItems: 'flex-start', width: '100%', textAlign: 'left',
                padding: '12px 18px', background: 'transparent', border: 0,
                borderTop: i === 0 ? 0 : '1px solid var(--border)', cursor: 'pointer',
              }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-sunken)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              <span style={{
                flexShrink: 0, marginTop: 2, fontSize: 10.5, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase',
                color: kindMeta[r.kind].color, border: `1px solid currentColor`, borderRadius: 999, padding: '3px 8px',
              }}>{kindMeta[r.kind].label}</span>
              <span style={{ minWidth: 0 }}>
                <span style={{ display: 'block', fontSize: 14.5, fontWeight: 700, color: 'var(--fg)' }}>{r.title}</span>
                <span style={{ display: 'block', fontSize: 13, color: 'var(--fg-muted)', marginTop: 2, lineHeight: 1.45,
                               overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.blurb}</span>
              </span>
            </button>
          ))}
        </div>
      )}
      <p style={{ margin: '10px 2px 0', fontSize: 13.5, color: 'var(--fg-subtle)' }}>
        Try “fractions”, “Diwali”, “number line”, or a year group.
      </p>
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// This week: upcoming calendar events + the weekly picks
// ══════════════════════════════════════════════════════════════
function ThisWeek({ onOpenCalendar, onOpenArticle }) {
  const { isMobile } = window.useViewport();
  const events = window.SCHOOL_CALENDAR || [];
  const articles = window.WIKI_ARTICLES || [];
  const tools = window.SHOWCASE_ITEMS || [];

  const upcoming = React.useMemo(() => {
    const today = dscMidnight(new Date());
    const horizon = new Date(today.getTime() + 21 * 86400000);
    return dscAllOccurrences(events)
      .filter(o => {
        const end = o.end ? dscMidnight(o.end) : dscMidnight(o.start);
        return end >= today && dscMidnight(o.start) <= horizon;
      })
      .slice(0, 4);
  }, [events]);

  // Wiki pick: prefer an article linked to something happening now.
  const wikiPick = React.useMemo(() => {
    if (!articles.length) return null;
    const linked = upcoming.map(o => o.ev.wiki).filter(Boolean);
    for (const slug of linked) {
      const hit = articles.find(a => a.slug === slug);
      if (hit) return { article: hit, tiedTo: upcoming.find(o => o.ev.wiki === slug).ev.title };
    }
    return { article: articles[dscWeekIndex() % articles.length], tiedTo: null };
  }, [articles, upcoming]);

  const toolPick = React.useMemo(
    () => (tools.length ? tools[(dscWeekIndex() * 7) % tools.length] : null),
    [tools]
  );

  const soon = upcoming.some(o => {
    const today = dscMidnight(new Date());
    return (dscMidnight(o.start) - today) / 86400000 < 7;
  });

  if (!upcoming.length && !wikiPick && !toolPick) return null;

  return (
    <section style={{ padding: isMobile ? '32px 20px 8px' : '44px 48px 12px', maxWidth: 1280, margin: '0 auto', width: '100%' }}>
      <div style={{ marginBottom: 20 }}>
        <div className="t-micro" style={{ color: 'var(--gold-deep)', marginBottom: 6 }}>{soon ? 'In the classroom this week' : 'On the horizon'}</div>
        <h2 className="t-h1" style={{ margin: 0 }}>What’s coming up</h2>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr 1fr', gap: 18, alignItems: 'stretch' }}>
        {/* Upcoming events */}
        {upcoming.length > 0 && (
          <div className="card" style={{ background: 'var(--surface)', padding: 0, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
            <div style={{ padding: '18px 18px 12px', display: 'flex' }}>
              <span className="t-micro" style={{ color: 'var(--gold-deep)' }}>{soon ? 'Events this week' : 'Coming up next'}</span>
            </div>
            {upcoming.map((o, i) => {
              const color = DSC_TYPE_COLOR[o.ev.type] || 'var(--fg-subtle)';
              const rel = dscRelative(o.start, o.end);
              return (
                <button key={`${o.ev.id}-${o.year}`} onClick={() => onOpenCalendar(o.ev.id)}
                  style={{
                    display: 'flex', gap: 14, alignItems: 'center', width: '100%', textAlign: 'left',
                    padding: '14px 18px', background: 'transparent', border: 0,
                    borderTop: '1px solid var(--border)', cursor: 'pointer',
                  }}
                  onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-sunken)'}
                  onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
                  <span style={{ width: 3, alignSelf: 'stretch', minHeight: 34, borderRadius: 3, background: color, flexShrink: 0 }} />
                  <span style={{ flex: 1, minWidth: 0 }}>
                    <span style={{ display: 'block', fontSize: 15, fontWeight: 700, color: 'var(--fg)' }}>{o.ev.title}</span>
                    <span style={{ display: 'block', fontSize: 13, color: 'var(--fg-muted)', marginTop: 2 }}>{DSC_TYPE_LABEL[o.ev.type]}</span>
                  </span>
                  <span style={{
                    flexShrink: 0, fontSize: 12.5, fontWeight: 700, color: rel === 'Today' ? 'var(--gold-deep)' : 'var(--fg-muted)',
                    background: rel === 'Today' ? 'color-mix(in oklab, var(--accent) 16%, var(--bg))' : 'var(--bg-sunken)',
                    border: '1px solid var(--border)', borderRadius: 999, padding: '5px 11px', whiteSpace: 'nowrap',
                  }}>{rel}</span>
                </button>
              );
            })}
            <button onClick={() => onOpenCalendar()}
              style={{ display: 'flex', alignItems: 'center', gap: 6, width: '100%', justifyContent: 'center',
                       marginTop: 'auto', padding: '12px 18px', background: 'var(--bg-sunken)',
                       border: 0, borderTop: '1px solid var(--border)', cursor: 'pointer', fontSize: 13.5, fontWeight: 700, color: 'var(--gold-deep)', fontFamily: 'inherit' }}>
              See the full school year<Icon.ArrowRight width="14" height="14" />
            </button>
          </div>
        )}

        {/* Weekly picks */}
        {wikiPick && (
            <button onClick={() => onOpenArticle(wikiPick.article.slug)} className="card"
              style={{ background: 'var(--surface)', padding: 18, textAlign: 'left', cursor: 'pointer', display: 'flex', flexDirection: 'column', gap: 7, height: '100%' }}>
              <span className="t-micro" style={{ color: 'var(--gold-deep)' }}>Wiki pick of the week</span>
              <span style={{ fontFamily: 'var(--font-serif)', fontSize: 19, fontWeight: 600, letterSpacing: '-.012em', lineHeight: 1.25, color: 'var(--fg)' }}>
                {wikiPick.article.title}
              </span>
              <span style={{ fontSize: 13.5, color: 'var(--fg-muted)', lineHeight: 1.5, textWrap: 'pretty' }}>
                {(() => { const t = wikiPick.article.lead || wikiPick.article.summary || ''; return t.length > 130 ? t.slice(0, 130).trim() + '…' : t; })()}
              </span>
              {wikiPick.tiedTo && (
                <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--fg-subtle)' }}>Because {wikiPick.tiedTo} is coming up</span>
              )}
            </button>
        )}

        {toolPick && (
            <a href={`${window.TOOLS_URL}/tools/${toolPick.slug}`} className="card"
              style={{ background: 'var(--surface)', padding: 0, overflow: 'hidden', textDecoration: 'none', color: 'inherit', display: 'flex', flexDirection: 'column', height: '100%' }}>
              <div style={{ padding: 18, display: 'flex', flexDirection: 'column', gap: 6 }}>
                <span className="t-micro" style={{ color: 'var(--gold-deep)' }}>Tool of the week</span>
                <span style={{ fontSize: 16.5, fontWeight: 700, color: 'var(--fg)' }}>{toolPick.name}</span>
                <span style={{ fontSize: 13.5, color: 'var(--fg-muted)' }}>{toolPick.tag} · open it straight on the whiteboard</span>
              </div>
              <div style={{ marginTop: 'auto', width: '100%', height: 128, background: 'var(--bg-sunken)', borderTop: '1px solid var(--border-strong)' }}>
                <img src={`${window.TOOLS_URL}/thumbs/${toolPick.slug}.png`} alt="" loading="lazy"
                  style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'top', display: 'block' }} />
              </div>
            </a>
        )}
      </div>
    </section>
  );
}

window.DiscoverSearch = DiscoverSearch;
window.ThisWeek = ThisWeek;
